mirror of
https://github.com/golang/go
synced 2024-11-18 08:14:41 -07:00
internal/lsp: fix hover for implicit type switch variable declarations
There was a bug in the hover for type switch variables. For example: var x interface{} switch y := x.(type) { case string: case int: } Hovering over y would previously show "var y string", because y's object would be mapped to the first types.Object in the type switch. Now we show the hover for y as "var y interface{}", since it's not yet in the cases. Change-Id: Ia9bd0afc4ddbb9d33bbd0c78fa32ffa75836a326 Reviewed-on: https://go-review.googlesource.com/c/tools/+/244497 Run-TryBot: Rebecca Stambler <rstambler@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
cbb3c69a37
commit
7017fd6b13
@ -96,7 +96,13 @@ func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverInformation,
|
||||
}
|
||||
h.Signature = b.String()
|
||||
case types.Object:
|
||||
h.Signature = objectString(x, i.qf)
|
||||
// If the variable is implicitly declared in a type switch, we need to
|
||||
// manually generate its object string.
|
||||
if v, ok := x.(*types.Var); ok && i.Declaration.typeSwitchImplicit {
|
||||
h.Signature = fmt.Sprintf("var %s %s", v.Name(), types.TypeString(i.enclosing, i.qf))
|
||||
} else {
|
||||
h.Signature = objectString(x, i.qf)
|
||||
}
|
||||
}
|
||||
if obj := i.Declaration.obj; obj != nil {
|
||||
h.SingleLine = objectString(obj, i.qf)
|
||||
|
@ -43,6 +43,10 @@ type Declaration struct {
|
||||
MappedRange []mappedRange
|
||||
node ast.Node
|
||||
obj types.Object
|
||||
|
||||
// typeSwitchImplicit indicates that the declaration is in an implicit
|
||||
// type switch.
|
||||
typeSwitchImplicit bool
|
||||
}
|
||||
|
||||
// Identifier returns identifier information for a position
|
||||
@ -152,9 +156,10 @@ func findIdentifier(ctx context.Context, s Snapshot, pkg Package, file *ast.File
|
||||
|
||||
result.Declaration.obj = pkg.GetTypesInfo().ObjectOf(result.ident)
|
||||
if result.Declaration.obj == nil {
|
||||
// If there was no types.Object for the declaration, there might be an implicit local variable
|
||||
// declaration in a type switch.
|
||||
// If there was no types.Object for the declaration, there might be an
|
||||
// implicit local variable declaration in a type switch.
|
||||
if objs := typeSwitchImplicits(pkg, path); len(objs) > 0 {
|
||||
result.Declaration.typeSwitchImplicit = true
|
||||
// There is no types.Object for the declaration of an implicit local variable,
|
||||
// but all of the types.Objects associated with the usages of this variable can be
|
||||
// used to connect it back to the declaration.
|
||||
@ -244,6 +249,15 @@ func searchForEnclosing(pkg Package, path []ast.Node) types.Type {
|
||||
return t.Type()
|
||||
}
|
||||
}
|
||||
case *ast.TypeSwitchStmt:
|
||||
// The right-hand side of a type switch should only have one
|
||||
// element, and we need to track its type in order to generate
|
||||
// hover information for implicit type switch variables.
|
||||
if assign, ok := n.Assign.(*ast.AssignStmt); ok && len(assign.Rhs) == 1 {
|
||||
if rhs := assign.Rhs[0].(*ast.TypeAssertExpr); ok {
|
||||
return pkg.GetTypesInfo().TypeOf(rhs.X)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -269,12 +283,10 @@ func objToDecl(ctx context.Context, v View, srcPkg Package, obj types.Object) (a
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
posToDecl, err := ph.PosToDecl(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return posToDecl[obj.Pos()], nil
|
||||
}
|
||||
|
||||
|
@ -514,7 +514,7 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) {
|
||||
return []byte(hover), nil
|
||||
}))
|
||||
if hover != expectHover {
|
||||
t.Errorf("for %v got %q want %q", d.Src, hover, expectHover)
|
||||
t.Errorf("hover for %s failed:\n%s", d.Src, tests.Diff(expectHover, hover))
|
||||
}
|
||||
}
|
||||
if !d.OnlyHover {
|
||||
|
@ -5,11 +5,11 @@ import "fmt"
|
||||
func TypeStuff() { //@Stuff
|
||||
var x string
|
||||
|
||||
switch y := interface{}(x).(type) { //@mark(switchY, "y"),mark(switchStringY,"y"),godef("y", switchY)
|
||||
case int:
|
||||
fmt.Printf("%v", y) //@godef("y", switchY)
|
||||
case string:
|
||||
fmt.Printf("%v", y) //@godef("y", switchStringY)
|
||||
switch y := interface{}(x).(type) { //@mark(switchY, "y"),godef("y", switchY)
|
||||
case int: //@mark(intY, "int")
|
||||
fmt.Printf("%v", y) //@hover("y", intY)
|
||||
case string: //@mark(stringY, "string")
|
||||
fmt.Printf("%v", y) //@hover("y", stringY)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,32 +1,14 @@
|
||||
-- switchStringY-definition --
|
||||
godef/a/f.go:8:9-10: defined here as ```go
|
||||
var y string
|
||||
-- intY-hover --
|
||||
```go
|
||||
var y int
|
||||
```
|
||||
-- switchStringY-definition-json --
|
||||
{
|
||||
"span": {
|
||||
"uri": "file://godef/a/f.go",
|
||||
"start": {
|
||||
"line": 8,
|
||||
"column": 9,
|
||||
"offset": 76
|
||||
},
|
||||
"end": {
|
||||
"line": 8,
|
||||
"column": 10,
|
||||
"offset": 77
|
||||
}
|
||||
},
|
||||
"description": "```go\nvar y string\n```"
|
||||
}
|
||||
|
||||
-- switchStringY-hover --
|
||||
-- stringY-hover --
|
||||
```go
|
||||
var y string
|
||||
```
|
||||
-- switchY-definition --
|
||||
godef/a/f.go:8:9-10: defined here as ```go
|
||||
var y int
|
||||
var y interface{}
|
||||
```
|
||||
-- switchY-definition-json --
|
||||
{
|
||||
@ -43,10 +25,10 @@ var y int
|
||||
"offset": 77
|
||||
}
|
||||
},
|
||||
"description": "```go\nvar y int\n```"
|
||||
"description": "```go\nvar y interface{}\n```"
|
||||
}
|
||||
|
||||
-- switchY-hover --
|
||||
```go
|
||||
var y int
|
||||
var y interface{}
|
||||
```
|
||||
|
@ -19,3 +19,13 @@ godef(bMember, Member)
|
||||
godef(bVar, Other)
|
||||
godef(bFunc, Things)
|
||||
*/
|
||||
|
||||
func _() {
|
||||
var x interface{} //@mark(eInterface, "interface{}")
|
||||
switch x := x.(type) { //@hover("x", eInterface)
|
||||
case string: //@mark(eString, "string")
|
||||
fmt.Println(x) //@hover("x", eString)
|
||||
case int: //@mark(eInt, "int")
|
||||
fmt.Println(x) //@hover("x", eInt)
|
||||
}
|
||||
}
|
||||
|
@ -130,3 +130,15 @@ func a.Things(val []string) []a.Thing
|
||||
```
|
||||
|
||||
[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)
|
||||
-- eInt-hover --
|
||||
```go
|
||||
var x int
|
||||
```
|
||||
-- eInterface-hover --
|
||||
```go
|
||||
var x interface{}
|
||||
```
|
||||
-- eString-hover --
|
||||
```go
|
||||
var x string
|
||||
```
|
||||
|
2
internal/lsp/testdata/lsp/summary.txt.golden
vendored
2
internal/lsp/testdata/lsp/summary.txt.golden
vendored
@ -13,7 +13,7 @@ FormatCount = 6
|
||||
ImportCount = 8
|
||||
SuggestedFixCount = 31
|
||||
FunctionExtractionCount = 5
|
||||
DefinitionsCount = 53
|
||||
DefinitionsCount = 56
|
||||
TypeDefinitionsCount = 2
|
||||
HighlightsCount = 69
|
||||
ReferencesCount = 11
|
||||
|
Loading…
Reference in New Issue
Block a user