From d0938c85ec65816448d730e9342f65620dbb857a Mon Sep 17 00:00:00 2001 From: Vitaly Date: Thu, 2 Feb 2023 03:43:07 +0300 Subject: [PATCH] imports: display completions to files with extensions from ambient modules (#52406) --- src/services/stringCompletions.ts | 19 ++++++++++++++----- ...etionsAllowModuleAugmentationExtensions.ts | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/pathCompletionsAllowModuleAugmentationExtensions.ts diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 42939f7fe13..205bbfc5d66 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -531,7 +531,7 @@ function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile const scriptPath = sourceFile.path; const scriptDirectory = getDirectoryPath(scriptPath); - const extensionOptions = getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile, preferences, mode); + const extensionOptions = getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile, typeChecker, preferences, mode); return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && (isRootedDiskPath(literalValue) || isUrl(literalValue)) ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, extensionOptions) @@ -546,9 +546,9 @@ interface ExtensionOptions { readonly resolutionMode?: ResolutionMode; } -function getExtensionOptions(compilerOptions: CompilerOptions, referenceKind: ReferenceKind, importingSourceFile: SourceFile, preferences?: UserPreferences, resolutionMode?: ResolutionMode): ExtensionOptions { +function getExtensionOptions(compilerOptions: CompilerOptions, referenceKind: ReferenceKind, importingSourceFile: SourceFile, typeChecker?: TypeChecker, preferences?: UserPreferences, resolutionMode?: ResolutionMode): ExtensionOptions { return { - extensionsToSearch: flatten(getSupportedExtensionsForModuleResolution(compilerOptions)), + extensionsToSearch: flatten(getSupportedExtensionsForModuleResolution(compilerOptions, typeChecker)), referenceKind, importingSourceFile, endingPreference: preferences?.importModuleSpecifierEnding, @@ -565,8 +565,17 @@ function getCompletionEntriesForRelativeModules(literalValue: string, scriptDire } } -function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions): readonly Extension[][] { - const extensions = getSupportedExtensions(compilerOptions); +function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions, typeChecker?: TypeChecker): readonly Extension[][] { + /** file extensions from ambient modules declarations e.g. *.css */ + const ambientModulesExtensions = !typeChecker ? [] : mapDefined(typeChecker.getAmbientModules(), + module => { + const name = module.name.slice(1, -1); + if (!name.startsWith("*.") || name.includes("/")) return; + return name.slice(1); + } + ) as Extension[]; + + const extensions = [...getSupportedExtensions(compilerOptions), ambientModulesExtensions]; const moduleResolution = getEmitModuleResolutionKind(compilerOptions); return moduleResolutionUsesNodeModules(moduleResolution) ? getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) : diff --git a/tests/cases/fourslash/pathCompletionsAllowModuleAugmentationExtensions.ts b/tests/cases/fourslash/pathCompletionsAllowModuleAugmentationExtensions.ts new file mode 100644 index 00000000000..f51990e27e4 --- /dev/null +++ b/tests/cases/fourslash/pathCompletionsAllowModuleAugmentationExtensions.ts @@ -0,0 +1,17 @@ +/// + +// @Filename: /project/foo.css +//// export const foo = 0; + +// @Filename: declarations.d.ts +//// declare module "*.css" {} + +// @Filename: /project/main.ts +//// import {} from ".//**/" + +// Extensionless by default +verify.completions({ + marker: "", + isNewIdentifierLocation: true, + exact: ["foo.css"], +});