diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 349cabd6da615..cd66f0b085a41 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -9,7 +9,7 @@ namespace ts.moduleSpecifiers { export function getModuleSpecifier( compilerOptions: CompilerOptions, importingSourceFile: SourceFile, - importingSourceFileName: string, + importingSourceFileName: Path, toFileName: string, host: ModuleSpecifierResolutionHost, files: ReadonlyArray, @@ -49,10 +49,10 @@ namespace ts.moduleSpecifiers { readonly moduleResolutionKind: ModuleResolutionKind; readonly addJsExtension: boolean; readonly getCanonicalFileName: GetCanonicalFileName; - readonly sourceDirectory: string; + readonly sourceDirectory: Path; } // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path - function getInfo(compilerOptions: CompilerOptions, importingSourceFile: SourceFile, importingSourceFileName: string, host: ModuleSpecifierResolutionHost): Info { + function getInfo(compilerOptions: CompilerOptions, importingSourceFile: SourceFile, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Info { const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); const addJsExtension = usesJsExtensionOnImports(importingSourceFile); const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true); @@ -271,7 +271,7 @@ namespace ts.moduleSpecifiers { moduleFileName: string, host: ModuleSpecifierResolutionHost, getCanonicalFileName: (file: string) => string, - sourceDirectory: string, + sourceDirectory: Path, ): string | undefined { if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs) { // nothing to do here @@ -290,7 +290,7 @@ namespace ts.moduleSpecifiers { const moduleSpecifier = getDirectoryOrExtensionlessFileName(moduleFileName); // Get a path that's relative to node_modules or the importing file's path // if node_modules folder is in this folder or any of its parent folders, no need to keep it. - if (!startsWith(sourceDirectory, moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex))) return undefined; + if (!startsWith(sourceDirectory, getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)))) return undefined; // If the module was found in @types, get the actual Node package name return getPackageNameFromAtTypesDirectory(moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1)); diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index e6b16efe6c7ca..8feaf430bc1eb 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -155,7 +155,7 @@ namespace Harness.LanguageService { this.vfs.mkdirpSync(ts.getDirectoryPath(newPath)); this.vfs.renameSync(oldPath, newPath); - const updater = ts.getPathUpdater(oldPath, newPath, ts.createGetCanonicalFileName(/*useCaseSensitiveFileNames*/ false)); + const updater = ts.getPathUpdater(oldPath, newPath, ts.createGetCanonicalFileName(this.useCaseSensitiveFileNames())); this.scriptInfos.forEach((scriptInfo, key) => { const newFileName = updater(key); if (newFileName !== undefined) { @@ -189,6 +189,10 @@ namespace Harness.LanguageService { assert.isOk(script); return ts.computeLineAndCharacterOfPosition(script.getLineMap(), position); } + + useCaseSensitiveFileNames() { + return !this.vfs.ignoreCase; + } } /// Native adapter @@ -251,7 +255,6 @@ namespace Harness.LanguageService { return 0; } - log = ts.noop; trace = ts.noop; error = ts.noop; diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index 43a0589536ca3..bfb737ef03c73 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -104,8 +104,8 @@ namespace ts { ): void { const allFiles = program.getSourceFiles(); for (const sourceFile of allFiles) { - const newFromOld = oldToNew(sourceFile.fileName); - const newImportFromPath = newFromOld !== undefined ? newFromOld : sourceFile.fileName; + const newFromOld = oldToNew(sourceFile.path) as Path; + const newImportFromPath = newFromOld !== undefined ? newFromOld : sourceFile.path; const newImportFromDirectory = getDirectoryPath(newImportFromPath); const oldFromNew: string | undefined = newToOld(sourceFile.fileName); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ad3a2ea1e9ed4..687ec12e4b74d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -9290,7 +9290,7 @@ declare namespace ts.moduleSpecifiers { interface ModuleSpecifierPreferences { readonly importModuleSpecifierPreference?: "relative" | "non-relative"; } - function getModuleSpecifier(compilerOptions: CompilerOptions, importingSourceFile: SourceFile, importingSourceFileName: string, toFileName: string, host: ModuleSpecifierResolutionHost, files: ReadonlyArray, preferences?: ModuleSpecifierPreferences): string; + function getModuleSpecifier(compilerOptions: CompilerOptions, importingSourceFile: SourceFile, importingSourceFileName: Path, toFileName: string, host: ModuleSpecifierResolutionHost, files: ReadonlyArray, preferences?: ModuleSpecifierPreferences): string; function getModuleSpecifiers(moduleSymbol: Symbol, compilerOptions: CompilerOptions, importingSourceFile: SourceFile, host: ModuleSpecifierResolutionHost, files: ReadonlyArray, preferences: ModuleSpecifierPreferences): ReadonlyArray>; } declare namespace ts { diff --git a/tests/cases/fourslash/importNameCodeFix_getCanonicalFileName.ts b/tests/cases/fourslash/importNameCodeFix_getCanonicalFileName.ts new file mode 100644 index 0000000000000..73bcf7439a239 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFix_getCanonicalFileName.ts @@ -0,0 +1,16 @@ +/// + +// @Filename: /howNow/node_modules/brownCow/index.d.ts +////export const foo: number; + +// @Filename: /howNow/a.ts +////foo; + +// Before fixing this bug, we compared a canonicalized `hownow` to a non-canonicalized `howNow`. + +goTo.file("/howNow/a.ts"); +verify.importFixAtPosition([ +`import { foo } from "brownCow"; + +foo;`, +]);