internal/lsp: fix link anchors for struct fields
This change fixes the link anchors for fields within a struct or
composite literal by getting the enclosing types.Type.
Fixes golang/go#36138
Change-Id: I534a900fad6fa6fa1b1acaa5a63ca264c5d34c39
Reviewed-on: https://go-review.googlesource.com/c/tools/+/211582
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go
index f16620f..868c265 100644
--- a/internal/lsp/source/hover.go
+++ b/internal/lsp/source/hover.go
@@ -93,13 +93,11 @@
switch obj := obj.(type) {
case *types.Var:
if obj.IsField() {
- // If the object is a field, and we have an associated selector,
- // we can determine the struct.
- if selection, ok := i.pkg.GetTypesInfo().Selections[i.selector]; ok {
- switch rtyp := deref(selection.Recv()).(type) {
- case *types.Named:
- rTypeName = rtyp.Obj().Name()
- }
+ // If the object is a field, and we have an associated selector
+ // composite literal, or struct, we can determine the link.
+ switch typ := i.enclosing.(type) {
+ case *types.Named:
+ rTypeName = typ.Obj().Name()
}
}
case *types.Func:
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index 2cfdf72..0cf7955 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -33,8 +33,10 @@
Declaration Declaration
- ident *ast.Ident
- selector *ast.SelectorExpr
+ ident *ast.Ident
+
+ // enclosing is an expression used to determine the link anchor for an identifier.
+ enclosing types.Type
pkg Package
qf types.Qualifier
@@ -120,12 +122,12 @@
}
}
result := &IdentifierInfo{
- File: ph,
- Snapshot: s,
- qf: qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()),
- pkg: pkg,
- ident: searchForIdent(path[0]),
- selector: searchForSelector(path),
+ File: ph,
+ Snapshot: s,
+ qf: qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()),
+ pkg: pkg,
+ ident: searchForIdent(path[0]),
+ enclosing: searchForEnclosing(pkg, path),
}
// No identifier at the given position.
@@ -232,11 +234,23 @@
return nil
}
-func searchForSelector(path []ast.Node) *ast.SelectorExpr {
+func searchForEnclosing(pkg Package, path []ast.Node) types.Type {
for _, n := range path {
- switch node := n.(type) {
+ switch n := n.(type) {
case *ast.SelectorExpr:
- return node
+ if selection, ok := pkg.GetTypesInfo().Selections[n]; ok {
+ return deref(selection.Recv())
+ }
+ case *ast.CompositeLit:
+ if t, ok := pkg.GetTypesInfo().Types[n]; ok {
+ return t.Type
+ }
+ case *ast.TypeSpec:
+ if _, ok := n.Type.(*ast.StructType); ok {
+ if t, ok := pkg.GetTypesInfo().Defs[n.Name]; ok {
+ return t.Type()
+ }
+ }
}
}
return nil
diff --git a/internal/lsp/testdata/godef/a/d.go b/internal/lsp/testdata/godef/a/d.go
index 4025788..3b76e82 100644
--- a/internal/lsp/testdata/godef/a/d.go
+++ b/internal/lsp/testdata/godef/a/d.go
@@ -17,7 +17,9 @@
}
func useThings() {
- t := Thing{} //@mark(aStructType, "ing")
+ t := Thing{ //@mark(aStructType, "ing")
+ Member: "string", //@mark(fMember, "ember")
+ }
fmt.Print(t.Member) //@mark(aMember, "ember")
fmt.Print(Other) //@mark(aVar, "ther")
Things() //@mark(aFunc, "ings")
@@ -30,6 +32,8 @@
godef(aVar, Other)
godef(aFunc, Things)
godef(aMethod, Method)
+godef(fMember, Member)
+godef(Member, Member)
//param
//package name
diff --git a/internal/lsp/testdata/godef/b/c.go.golden b/internal/lsp/testdata/godef/b/c.go.golden
index 30fb109..cf7e753 100644
--- a/internal/lsp/testdata/godef/b/c.go.golden
+++ b/internal/lsp/testdata/godef/b/c.go.golden
@@ -39,7 +39,7 @@
-- S1F1-definition --
godef/b/b.go:9:2-4: defined here as \@mark\(S1F1, \"F1\"\)
-[`b.F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#F1)
+[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)
```go
field F1 int
@@ -59,13 +59,13 @@
"offset": 214
}
},
- "description": "\\@mark\\(S1F1, \\\"F1\\\"\\)\n\n[`b.F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#F1)\n\n```go\nfield F1 int\n```"
+ "description": "\\@mark\\(S1F1, \\\"F1\\\"\\)\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)\n\n```go\nfield F1 int\n```"
}
-- S1F1-hover --
\@mark\(S1F1, \"F1\"\)
-[`b.F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#F1)
+[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1.F1)
```go
field F1 int
diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden
index 1067353..b96f1d6 100644
--- a/internal/lsp/testdata/summary.txt.golden
+++ b/internal/lsp/testdata/summary.txt.golden
@@ -11,7 +11,7 @@
FormatCount = 6
ImportCount = 7
SuggestedFixCount = 1
-DefinitionsCount = 39
+DefinitionsCount = 41
TypeDefinitionsCount = 2
HighlightsCount = 44
ReferencesCount = 7