diff --git a/gopls/internal/regtest/misc/rename_test.go b/gopls/internal/regtest/misc/rename_test.go index 65a9ecb52e..1d980d90aa 100644 --- a/gopls/internal/regtest/misc/rename_test.go +++ b/gopls/internal/regtest/misc/rename_test.go @@ -10,6 +10,7 @@ import ( "golang.org/x/tools/internal/lsp/protocol" . "golang.org/x/tools/internal/lsp/regtest" + "golang.org/x/tools/internal/testenv" ) func TestPrepareRenamePackage(t *testing.T) { @@ -51,6 +52,41 @@ func main() { }) } +func TestRenamePackageInRenamedPackage(t *testing.T) { + // Failed at Go 1.13; not investigated + testenv.NeedsGo1Point(t, 14) + const files = ` +-- go.mod -- +module mod.com + +go 1.18 +-- main.go -- +package main + +import ( + "fmt" + "a.go" +) + +func main() { + fmt.Println(a.C) +} +-- a.go -- +package main + +const C = 1 +` + Run(t, files, func(t *testing.T, env *Env) { + env.OpenFile("main.go") + pos := env.RegexpSearch("main.go", "main") + env.Rename("main.go", pos, "pkg") + + // Check if the new package name exists. + env.RegexpSearch("main.go", "package pkg") + env.RegexpSearch("a.go", "package pkg") + }) +} + // Test for golang/go#47564. func TestRenameInTestVariant(t *testing.T) { const files = ` diff --git a/internal/lsp/source/rename.go b/internal/lsp/source/rename.go index b6f0e6531e..6bbe91afae 100644 --- a/internal/lsp/source/rename.go +++ b/internal/lsp/source/rename.go @@ -118,6 +118,41 @@ func Rename(ctx context.Context, s Snapshot, f FileHandle, pp protocol.Position, ctx, done := event.Start(ctx, "source.Rename") defer done() + pgf, err := s.ParseGo(ctx, f, ParseFull) + if err != nil { + return nil, err + } + inPackageName, err := isInPackageName(ctx, s, f, pgf, pp) + if err != nil { + return nil, err + } + + if inPackageName { + renamingPkg, err := s.PackageForFile(ctx, f.URI(), TypecheckAll, NarrowestPackage) + if err != nil { + return nil, err + } + + result := make(map[span.URI][]protocol.TextEdit) + // Rename internal references to the package in the renaming package + // Todo(dle): need more investigation on case when pkg.GoFiles != pkg.CompiledGoFiles if using cgo. + for _, f := range renamingPkg.CompiledGoFiles() { + pkgNameMappedRange := NewMappedRange(f.Tok, f.Mapper, f.File.Name.Pos(), f.File.Name.End()) + rng, err := pkgNameMappedRange.Range() + if err != nil { + return nil, err + } + result[f.URI] = []protocol.TextEdit{ + { + Range: rng, + NewText: newName, + }, + } + } + + return result, nil + } + qos, err := qualifiedObjsAtProtocolPos(ctx, s, f.URI(), pp) if err != nil { return nil, err @@ -182,6 +217,7 @@ func Rename(ctx context.Context, s Snapshot, f FileHandle, pp protocol.Position, if err != nil { return nil, err } + result := make(map[span.URI][]protocol.TextEdit) for uri, edits := range changes { // These edits should really be associated with FileHandles for maximal correctness.