1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:04:44 -07:00

internal/lsp: support renaming of import spec

This change allows renamings of the name of an import spec.
Since there is not always explicit identifier available to select and
rename, allow renaming packages from positions within the import spec.

Change-Id: I0a8aaa92c26e1795ddb9c31a1165b2f2ee89aa34
Reviewed-on: https://go-review.googlesource.com/c/tools/+/191165
Run-TryBot: Suzy Mueller <suzmue@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
Suzy Mueller 2019-08-21 22:40:36 -04:00
parent aa644d2adf
commit c4a336ef6a
4 changed files with 203 additions and 19 deletions

View File

@ -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)

View File

@ -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 {

View File

@ -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 {

View File

@ -38,7 +38,7 @@ const (
ExpectedTypeDefinitionsCount = 2
ExpectedHighlightsCount = 2
ExpectedReferencesCount = 5
ExpectedRenamesCount = 18
ExpectedRenamesCount = 20
ExpectedSymbolsCount = 1
ExpectedSignaturesCount = 21
ExpectedLinksCount = 4