diff --git a/internal/lsp/source/rename.go b/internal/lsp/source/rename.go index 5ac65fbd6e..00f26f585e 100644 --- a/internal/lsp/source/rename.go +++ b/internal/lsp/source/rename.go @@ -40,14 +40,19 @@ func (i *IdentifierInfo) Rename(ctx context.Context, newName string) (map[span.U ctx, done := trace.StartSpan(ctx, "source.Rename") defer done() + // If the object declaration is nil, assume it is an import spec. + if i.decl.obj == nil { + // Find the corresponding package name for this import spec + // and rename that instead. + ident, err := i.getPkgName(ctx) + if err != nil { + return nil, err + } + return ident.Rename(ctx, newName) + } if i.Name == newName { return nil, errors.Errorf("old and new names are the same: %s", newName) } - // If the object declaration is nil, assume it is an import spec and return an error. - // TODO(suzmue): support renaming of identifiers in an import spec. - if i.decl.obj == nil { - return nil, errors.Errorf("renaming import %q not supported", i.Name) - } if !isValidIdentifier(i.Name) { return nil, errors.Errorf("invalid identifier to rename: %q", i.Name) } @@ -104,6 +109,52 @@ func (i *IdentifierInfo) Rename(ctx context.Context, newName string) (map[span.U return changes, nil } +// getPkgName gets the pkg name associated with an identifer representing +// the import path in an import spec. +func (i *IdentifierInfo) getPkgName(ctx context.Context) (*IdentifierInfo, error) { + file := i.File.FileSet().File(i.Range.Start) + pkgLine := file.Line(i.Range.Start) + + for _, obj := range i.pkg.GetTypesInfo().Defs { + pkgName, ok := obj.(*types.PkgName) + if ok && file.Line(pkgName.Pos()) == pkgLine { + return getPkgNameIdentifier(ctx, i, pkgName) + } + } + for _, obj := range i.pkg.GetTypesInfo().Implicits { + pkgName, ok := obj.(*types.PkgName) + if ok && file.Line(pkgName.Pos()) == pkgLine { + return getPkgNameIdentifier(ctx, i, pkgName) + } + } + return nil, errors.Errorf("no package name for %q", i.Name) +} + +// getPkgNameIdentifier returns an IdentifierInfo representing pkgName. +// pkgName must be in the same package and file as ident. +func getPkgNameIdentifier(ctx context.Context, ident *IdentifierInfo, pkgName *types.PkgName) (*IdentifierInfo, error) { + decl := declaration{ + obj: pkgName, + wasImplicit: true, + } + var err error + if decl.rng, err = objToRange(ctx, ident.File.FileSet(), decl.obj); err != nil { + return nil, err + } + if decl.node, err = objToNode(ctx, ident.File.View(), ident.pkg.GetTypes(), decl.obj, decl.rng); err != nil { + return nil, err + } + return &IdentifierInfo{ + Name: pkgName.Name(), + Range: decl.rng, + File: ident.File, + decl: decl, + pkg: ident.pkg, + wasEmbeddedField: false, + qf: ident.qf, + }, nil +} + // Rename all references to the identifier. func (r *renamer) update() (map[span.URI][]diff.TextEdit, error) { result := make(map[span.URI][]diff.TextEdit) diff --git a/internal/lsp/testdata/rename/a/random.go.golden b/internal/lsp/testdata/rename/a/random.go.golden index 518757f14f..b1a20ff850 100644 --- a/internal/lsp/testdata/rename/a/random.go.golden +++ b/internal/lsp/testdata/rename/a/random.go.golden @@ -5,7 +5,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -43,6 +43,96 @@ func sw() { } } +-- f2name-rename -- +random.go: +package a + +import ( + lg "log" + "fmt" //@rename("fmt", "fmty") + f2name "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") +) + +func Random() int { + y := 6 + 7 + return y +} + +func Random2(y int) int { //@rename("y", "z") + return y +} + +type Pos struct { + x, y int +} + +func (p *Pos) Sum() int { + return p.x + p.y //@rename("x", "myX") +} + +func _() { + var p Pos //@rename("p", "pos") + _ = p.Sum() //@rename("Sum", "GetSum") +} + +func sw() { + var x interface{} + + switch y := x.(type) { //@rename("y", "y0") + case int: + fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format") + case string: + lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log") + default: + f2name.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2") + } +} + +-- f2y-rename -- +random.go: +package a + +import ( + lg "log" + "fmt" //@rename("fmt", "fmty") + f2y "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") +) + +func Random() int { + y := 6 + 7 + return y +} + +func Random2(y int) int { //@rename("y", "z") + return y +} + +type Pos struct { + x, y int +} + +func (p *Pos) Sum() int { + return p.x + p.y //@rename("x", "myX") +} + +func _() { + var p Pos //@rename("p", "pos") + _ = p.Sum() //@rename("Sum", "GetSum") +} + +func sw() { + var x interface{} + + switch y := x.(type) { //@rename("y", "y0") + case int: + fmt.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format") + case string: + lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log") + default: + f2y.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2") + } +} + -- fmt2-rename -- random.go: package a @@ -50,7 +140,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - fmt2 "fmt" + fmt2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -89,7 +179,50 @@ func sw() { } -- fmty-rename -- -renaming import "fmt" not supported +random.go: +package a + +import ( + lg "log" + fmty "fmt" //@rename("fmt", "fmty") + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") +) + +func Random() int { + y := 6 + 7 + return y +} + +func Random2(y int) int { //@rename("y", "z") + return y +} + +type Pos struct { + x, y int +} + +func (p *Pos) Sum() int { + return p.x + p.y //@rename("x", "myX") +} + +func _() { + var p Pos //@rename("p", "pos") + _ = p.Sum() //@rename("Sum", "GetSum") +} + +func sw() { + var x interface{} + + switch y := x.(type) { //@rename("y", "y0") + case int: + fmty.Printf("%d", y) //@rename("y", "y1"),rename("fmt", "format") + case string: + lg.Printf("%s", y) //@rename("y", "y2"),rename("lg","log") + default: + f2.Printf("%v", y) //@rename("y", "y3"),rename("f2","fmt2") + } +} + -- format-rename -- random.go: package a @@ -97,7 +230,7 @@ package a import ( lg "log" format "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -142,7 +275,7 @@ package a import ( "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -187,7 +320,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -232,7 +365,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -277,7 +410,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -322,7 +455,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -367,7 +500,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -412,7 +545,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { @@ -457,7 +590,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { diff --git a/internal/lsp/testdata/rename/a/random.go.in b/internal/lsp/testdata/rename/a/random.go.in index 12026d0503..069db27baa 100644 --- a/internal/lsp/testdata/rename/a/random.go.in +++ b/internal/lsp/testdata/rename/a/random.go.in @@ -3,7 +3,7 @@ package a import ( lg "log" "fmt" //@rename("fmt", "fmty") - f2 "fmt" + f2 "fmt" //@rename("f2", "f2name"),rename("fmt","f2y") ) func Random() int { diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index a79c1e3726..c0a5b31fae 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -38,7 +38,7 @@ const ( ExpectedTypeDefinitionsCount = 2 ExpectedHighlightsCount = 2 ExpectedReferencesCount = 5 - ExpectedRenamesCount = 18 + ExpectedRenamesCount = 20 ExpectedSymbolsCount = 1 ExpectedSignaturesCount = 21 ExpectedLinksCount = 4