From 8e69f41f4c1d3af3de4720f545de00f22b4c0934 Mon Sep 17 00:00:00 2001 From: Eloy Robillard Date: Sun, 25 Feb 2024 15:05:37 +0100 Subject: [PATCH] Prevent self-imports on "Move to File" refactor --- src/services/refactors/moveToFile.ts | 12 +++++++++-- .../fourslash/moveToFile_noSelfImports1.ts | 19 ++++++++++++++++++ .../fourslash/moveToFile_noSelfImports2.ts | 20 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/moveToFile_noSelfImports1.ts create mode 100644 tests/cases/fourslash/moveToFile_noSelfImports2.ts diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 1d3d072d89c07..b64a9573f19de 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -18,6 +18,7 @@ import { ClassDeclaration, codefix, combinePaths, + Comparison, concatenate, contains, createModuleSpecifierResolutionHost, @@ -52,12 +53,14 @@ import { getDirectoryPath, getLocaleSpecificMessage, getModifiers, + getNormalizedAbsolutePath, getPropertySymbolFromBindingElement, getQuotePreference, getRangesWhere, getRefactorContextSpan, getRelativePathFromFile, getSourceFileOfNode, + getStringComparer, getSynthesizedDeepClone, getTokenAtPosition, getUniqueName, @@ -429,7 +432,12 @@ export function updateImportsInOtherFiles( }; deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file - const pathToTargetFileWithExtension = resolvePath(getDirectoryPath(oldFile.path), targetFileName); + const pathToTargetFileWithExtension = resolvePath(getDirectoryPath(getNormalizedAbsolutePath(oldFile.fileName, program.getCurrentDirectory())), targetFileName); + + // no self-imports + + if (getStringComparer(!program.useCaseSensitiveFileNames())(pathToTargetFileWithExtension, sourceFile.fileName) === Comparison.EqualTo) return; + const newModuleSpecifier = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.fileName, pathToTargetFileWithExtension, createModuleSpecifierResolutionHost(program, host)); const newImportDeclaration = filterImport(importNode, makeStringLiteral(newModuleSpecifier, quotePreference), shouldMove); if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration); @@ -581,7 +589,7 @@ export function makeImportOrRequire( useEs6Imports: boolean, quotePreference: QuotePreference, ): AnyImportOrRequireStatement | undefined { - const pathToTargetFile = resolvePath(getDirectoryPath(sourceFile.path), targetFileNameWithExtension); + const pathToTargetFile = resolvePath(getDirectoryPath(getNormalizedAbsolutePath(sourceFile.fileName, program.getCurrentDirectory())), targetFileNameWithExtension); const pathToTargetFileWithCorrectExtension = getModuleSpecifier(program.getCompilerOptions(), sourceFile, sourceFile.fileName, pathToTargetFile, createModuleSpecifierResolutionHost(program, host)); if (useEs6Imports) { diff --git a/tests/cases/fourslash/moveToFile_noSelfImports1.ts b/tests/cases/fourslash/moveToFile_noSelfImports1.ts new file mode 100644 index 0000000000000..a0527eeb6bb0f --- /dev/null +++ b/tests/cases/fourslash/moveToFile_noSelfImports1.ts @@ -0,0 +1,19 @@ +/// + +//@Filename: /bar.ts +////import { y } from "./a"; + +// @Filename: /a.ts +////[|export const y = 1;|] + +verify.moveToFile({ + newFileContents: { + "/a.ts": "", + + "/bar.ts": +` +export const y = 1; +`, + }, + interactiveRefactorArguments: { targetFile: "/bar.ts" } +}); diff --git a/tests/cases/fourslash/moveToFile_noSelfImports2.ts b/tests/cases/fourslash/moveToFile_noSelfImports2.ts new file mode 100644 index 0000000000000..3ae5d2621a8eb --- /dev/null +++ b/tests/cases/fourslash/moveToFile_noSelfImports2.ts @@ -0,0 +1,20 @@ +/// + +//@Filename: /bar.ts +////import { y, z } from "./a"; + +// @Filename: /a.ts +////[|export const y = 1;|] +////export const z = 2; + +verify.moveToFile({ + newFileContents: { + "/a.ts": "export const z = 2;", + + "/bar.ts": +`import { z } from "./a"; +export const y = 1; +`, + }, + interactiveRefactorArguments: { targetFile: "/bar.ts" } +});