From c96c3af78892a0f4a222481dc3a237ae9d93721a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 22 Mar 2026 11:54:34 +0100 Subject: [PATCH] Fixes a crash when renaming import path of a JSON file --- .../importAllowRenameOfImportPath2_test.go | 27 +++++++++++++++++ .../importAllowRenameOfImportPath3_test.go | 27 +++++++++++++++++ .../importAllowRenameOfImportPath4_test.go | 29 +++++++++++++++++++ .../importAllowRenameOfImportPath5_test.go | 27 +++++++++++++++++ internal/ls/findallreferences.go | 11 ++++--- .../allowRenameOfImportPath2.baseline.jsonc | 3 ++ .../allowRenameOfImportPath3.baseline.jsonc | 7 +++++ .../allowRenameOfImportPath4.baseline.jsonc | 3 ++ .../allowRenameOfImportPath5.baseline.jsonc | 3 ++ 9 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 internal/fourslash/tests/importAllowRenameOfImportPath2_test.go create mode 100644 internal/fourslash/tests/importAllowRenameOfImportPath3_test.go create mode 100644 internal/fourslash/tests/importAllowRenameOfImportPath4_test.go create mode 100644 internal/fourslash/tests/importAllowRenameOfImportPath5_test.go create mode 100644 testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath2.baseline.jsonc create mode 100644 testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath3.baseline.jsonc create mode 100644 testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath4.baseline.jsonc create mode 100644 testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath5.baseline.jsonc diff --git a/internal/fourslash/tests/importAllowRenameOfImportPath2_test.go b/internal/fourslash/tests/importAllowRenameOfImportPath2_test.go new file mode 100644 index 00000000000..3fe59a90028 --- /dev/null +++ b/internal/fourslash/tests/importAllowRenameOfImportPath2_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/ls/lsutil" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestAllowRenameOfImportPath2(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /src/example.ts +import brushPackageJson from './visx-brush/[|package|].json'; +// @Filename: /src/visx-brush/package.json +{ "name": "brush" } +` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + prefs := &lsutil.UserPreferences{ + AllowRenameOfImportPath: core.TSTrue, + } + f.VerifyBaselineRename(t, prefs, f.Ranges()[0]) +} diff --git a/internal/fourslash/tests/importAllowRenameOfImportPath3_test.go b/internal/fourslash/tests/importAllowRenameOfImportPath3_test.go new file mode 100644 index 00000000000..0516815f694 --- /dev/null +++ b/internal/fourslash/tests/importAllowRenameOfImportPath3_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/ls/lsutil" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestAllowRenameOfImportPath3(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /src/example.ts +import stuff from './[|stuff|].cts'; +// @Filename: /src/stuff.cts +export = { name: "stuff" }; +` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + prefs := &lsutil.UserPreferences{ + AllowRenameOfImportPath: core.TSTrue, + } + f.VerifyBaselineRename(t, prefs, f.Ranges()[0]) +} diff --git a/internal/fourslash/tests/importAllowRenameOfImportPath4_test.go b/internal/fourslash/tests/importAllowRenameOfImportPath4_test.go new file mode 100644 index 00000000000..6ef34f974f5 --- /dev/null +++ b/internal/fourslash/tests/importAllowRenameOfImportPath4_test.go @@ -0,0 +1,29 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/ls/lsutil" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestAllowRenameOfImportPath4(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /src/example.ts +import styles from './[|styles|].css'; +// @Filename: /src/styles.css +body { color: red; } +// @Filename: /src/globals.d.ts +declare module "*.css"; +` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + prefs := &lsutil.UserPreferences{ + AllowRenameOfImportPath: core.TSTrue, + } + f.VerifyBaselineRename(t, prefs, f.Ranges()[0]) +} diff --git a/internal/fourslash/tests/importAllowRenameOfImportPath5_test.go b/internal/fourslash/tests/importAllowRenameOfImportPath5_test.go new file mode 100644 index 00000000000..d3143e0532d --- /dev/null +++ b/internal/fourslash/tests/importAllowRenameOfImportPath5_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/ls/lsutil" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestAllowRenameOfImportPath5(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /src/example.ts +import styles from './[|styles|].css'; +// @Filename: /src/styles.css +body { color: red; } +` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + prefs := &lsutil.UserPreferences{ + AllowRenameOfImportPath: core.TSTrue, + } + f.VerifyBaselineRename(t, prefs, f.Ranges()[0]) +} diff --git a/internal/ls/findallreferences.go b/internal/ls/findallreferences.go index 91ebe84f8c4..a7837b6c440 100644 --- a/internal/ls/findallreferences.go +++ b/internal/ls/findallreferences.go @@ -867,7 +867,7 @@ func (l *LanguageService) getReferencedSymbolsForNode(ctx context.Context, posit } if moduleSymbol := checker.GetMergedSymbol(resolvedRef.file.Symbol); moduleSymbol != nil { - return l.getReferencedSymbolsForModule(ctx, program, moduleSymbol /*excludeImportTypeOfExportEquals*/, false, sourceFiles, sourceFilesSet) + return l.getReferencedSymbolsForModule(ctx, program, moduleSymbol /*excludeImportTypeOfExportEquals*/, false, sourceFiles, sourceFilesSet, options) } // !!! not implemented @@ -913,7 +913,7 @@ func (l *LanguageService) getReferencedSymbolsForNode(ctx context.Context, posit } if symbol.Name == ast.InternalSymbolNameExportEquals { - return l.getReferencedSymbolsForModule(ctx, program, symbol.Parent, false /*excludeImportTypeOfExportEquals*/, sourceFiles, sourceFilesSet) + return l.getReferencedSymbolsForModule(ctx, program, symbol.Parent, false /*excludeImportTypeOfExportEquals*/, sourceFiles, sourceFilesSet, options) } moduleReferences := l.getReferencedSymbolsForModuleIfDeclaredBySourceFile(ctx, symbol, program, sourceFiles, checker, options, sourceFilesSet) // !!! cancellationToken @@ -987,7 +987,7 @@ func (l *LanguageService) getReferencedSymbolsForModuleIfDeclaredBySourceFile(ct } exportEquals := symbol.Exports[ast.InternalSymbolNameExportEquals] // If exportEquals != nil, we're about to add references to `import("mod")` anyway, so don't double-count them. - moduleReferences := l.getReferencedSymbolsForModule(ctx, program, symbol, exportEquals != nil, sourceFiles, sourceFilesSet) + moduleReferences := l.getReferencedSymbolsForModule(ctx, program, symbol, exportEquals != nil, sourceFiles, sourceFilesSet, options) if exportEquals == nil || exportEquals.Flags&ast.SymbolFlagsAlias == 0 || !sourceFilesSet.Has(moduleSourceFileName) { return moduleReferences } @@ -1308,7 +1308,7 @@ func getMergedAliasedSymbolOfNamespaceExportDeclaration(node *ast.Node, symbol * return nil } -func (l *LanguageService) getReferencedSymbolsForModule(ctx context.Context, program *compiler.Program, symbol *ast.Symbol, excludeImportTypeOfExportEquals bool, sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[string]) []*SymbolAndEntries { +func (l *LanguageService) getReferencedSymbolsForModule(ctx context.Context, program *compiler.Program, symbol *ast.Symbol, excludeImportTypeOfExportEquals bool, sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[string], options refOptions) []*SymbolAndEntries { debug.Assert(symbol.ValueDeclaration != nil) checker, done := program.GetTypeChecker(ctx) @@ -1380,6 +1380,9 @@ func (l *LanguageService) getReferencedSymbolsForModule(ctx context.Context, pro exported := symbol.Exports[ast.InternalSymbolNameExportEquals] if exported != nil && len(exported.Declarations) > 0 { for _, decl := range exported.Declarations { + if options.use == referenceUseRename && ast.IsSourceFile(decl) { + continue + } sourceFile := ast.GetSourceFileOfNode(decl) if sourceFilesSet.Has(sourceFile.FileName()) { var node *ast.Node diff --git a/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath2.baseline.jsonc b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath2.baseline.jsonc new file mode 100644 index 00000000000..764e04481fb --- /dev/null +++ b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath2.baseline.jsonc @@ -0,0 +1,3 @@ +// === findRenameLocations === +// === /src/example.ts === +// import brushPackageJson from '[|./visx-brush//*RENAME*/package.jsonRENAME|]'; \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath3.baseline.jsonc b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath3.baseline.jsonc new file mode 100644 index 00000000000..c34dca5382f --- /dev/null +++ b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath3.baseline.jsonc @@ -0,0 +1,7 @@ +// === findRenameLocations === +// === /src/example.ts === +// import stuff from '[|.//*RENAME*/stuff.ctsRENAME|]'; + +// === /src/stuff.cts === +// [|exportRENAME|] = { name: "stuff" }; +// \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath4.baseline.jsonc b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath4.baseline.jsonc new file mode 100644 index 00000000000..4fd346d53df --- /dev/null +++ b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath4.baseline.jsonc @@ -0,0 +1,3 @@ +// === findRenameLocations === +// === /src/example.ts === +// import styles from './/*RENAME*/styles.css'; \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath5.baseline.jsonc b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath5.baseline.jsonc new file mode 100644 index 00000000000..4fd346d53df --- /dev/null +++ b/testdata/baselines/reference/fourslash/findRenameLocations/allowRenameOfImportPath5.baseline.jsonc @@ -0,0 +1,3 @@ +// === findRenameLocations === +// === /src/example.ts === +// import styles from './/*RENAME*/styles.css'; \ No newline at end of file