internal/lsp: fix godef for embedded type aliases
In
type myAlias = someType
type _ struct {
myAlias
}
Previously running "definition" on the "myAlias" field would take you
to the definition of "someType" instead of "myAlias". This is because
we were using the field's (*types.Var).Type() which has already
forgotten it is an alias. Fix by instead looking up the field name
ident in types.Info.Uses which yields the *types.TypeName (for the
type alias).
Fixes golang/go#42254.
Change-Id: Idbbd0c49ba6f701f52568b3ab1143d8e24037c69
Reviewed-on: https://go-review.googlesource.com/c/tools/+/272186
Run-TryBot: Muir Manders <muir@mnd.rs>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Muir Manders <muir@mnd.rs>
Trust: Rebecca Stambler <rstambler@golang.org>
Trust: Robert Findley <rfindley@google.com>
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index 753d12b..362604e 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -157,14 +157,6 @@
enclosing: searchForEnclosing(pkg.GetTypesInfo(), path),
}
- var wasEmbeddedField bool
- for _, n := range path[1:] {
- if field, ok := n.(*ast.Field); ok {
- wasEmbeddedField = len(field.Names) == 0
- break
- }
- }
-
result.Name = result.ident.Name
var err error
if result.MappedRange, err = posToMappedRange(snapshot, pkg, result.ident.Pos(), result.ident.End()); err != nil {
@@ -253,13 +245,12 @@
}
}
- if wasEmbeddedField {
- // The original position was on the embedded field declaration, so we
- // try to dig out the type and jump to that instead.
- if v, ok := result.Declaration.obj.(*types.Var); ok {
- if typObj := typeToObject(v.Type()); typObj != nil {
- result.Declaration.obj = typObj
- }
+ // If the original position was an embedded field, we want to jump
+ // to the field's type definition, not the field's definition.
+ if v, ok := result.Declaration.obj.(*types.Var); ok && v.Embedded() {
+ // types.Info.Uses contains the embedded field's *types.TypeName.
+ if typeName := pkg.GetTypesInfo().Uses[ident]; typeName != nil {
+ result.Declaration.obj = typeName
}
}
diff --git a/internal/lsp/testdata/godef/a/a.go.golden b/internal/lsp/testdata/godef/a/a.go.golden
index 139a177..08a1882 100644
--- a/internal/lsp/testdata/godef/a/a.go.golden
+++ b/internal/lsp/testdata/godef/a/a.go.golden
@@ -74,10 +74,6 @@
```
[`a.Random2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Random2)
--- a-hover --
-```go
-
-```
-- aPackage-hover --
Package a is a package for testing go to definition\.
-- err-definition --
diff --git a/internal/lsp/testdata/godef/b/b.go b/internal/lsp/testdata/godef/b/b.go
index a510a45..23d908f 100644
--- a/internal/lsp/testdata/godef/b/b.go
+++ b/internal/lsp/testdata/godef/b/b.go
@@ -22,10 +22,13 @@
e.Goodbye() //@hover("Goodbye", AGoodbye)
}
+type aAlias = a.A //@mark(aAlias, "aAlias")
+
type S1 struct { //@S1
- F1 int //@mark(S1F1, "F1")
- S2 //@godef("S2", S2),mark(S1S2, "S2")
- a.A //@godef("A", AString)
+ F1 int //@mark(S1F1, "F1")
+ S2 //@godef("S2", S2),mark(S1S2, "S2")
+ a.A //@godef("A", AString)
+ aAlias //@godef("a", aAlias)
}
type S2 struct { //@S2
diff --git a/internal/lsp/testdata/godef/b/b.go.golden b/internal/lsp/testdata/godef/b/b.go.golden
index ad8a98b..19ece5d 100644
--- a/internal/lsp/testdata/godef/b/b.go.golden
+++ b/internal/lsp/testdata/godef/b/b.go.golden
@@ -143,11 +143,12 @@
[`a.AStuff` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#AStuff)
-- S1-definition --
-godef/b/b.go:25:6-8: defined here as ```go
+godef/b/b.go:27:6-8: defined here as ```go
type S1 struct {
- F1 int //@mark(S1F1, "F1")
- S2 //@godef("S2", S2),mark(S1S2, "S2")
- a.A //@godef("A", AString)
+ F1 int //@mark(S1F1, "F1")
+ S2 //@godef("S2", S2),mark(S1S2, "S2")
+ a.A //@godef("A", AString)
+ aAlias //@godef("a", aAlias)
}
```
@@ -157,31 +158,32 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 25,
+ "line": 27,
"column": 6,
- "offset": 521
+ "offset": 566
},
"end": {
- "line": 25,
+ "line": 27,
"column": 8,
- "offset": 523
+ "offset": 568
}
},
- "description": "```go\ntype S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2),mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", AString)\n}\n```\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1)"
+ "description": "```go\ntype S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2),mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", AString)\n\taAlias //@godef(\"a\", aAlias)\n}\n```\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1)"
}
-- S1-hover --
```go
type S1 struct {
- F1 int //@mark(S1F1, "F1")
- S2 //@godef("S2", S2),mark(S1S2, "S2")
- a.A //@godef("A", AString)
+ F1 int //@mark(S1F1, "F1")
+ S2 //@godef("S2", S2),mark(S1S2, "S2")
+ a.A //@godef("A", AString)
+ aAlias //@godef("a", aAlias)
}
```
[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1)
-- S1F1-definition --
-godef/b/b.go:26:2-4: defined here as ```go
+godef/b/b.go:28:2-4: defined here as ```go
field F1 int
```
@@ -193,14 +195,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 26,
+ "line": 28,
"column": 2,
- "offset": 540
+ "offset": 585
},
"end": {
- "line": 26,
+ "line": 28,
"column": 4,
- "offset": 542
+ "offset": 587
}
},
"description": "```go\nfield F1 int\n```\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1.F1)\n\n\\@mark\\(S1F1, \\\"F1\\\"\\)"
@@ -215,7 +217,7 @@
\@mark\(S1F1, \"F1\"\)
-- S1S2-definition --
-godef/b/b.go:27:2-4: defined here as ```go
+godef/b/b.go:29:2-4: defined here as ```go
field S2 S2
```
@@ -227,14 +229,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 27,
+ "line": 29,
"column": 2,
- "offset": 569
+ "offset": 617
},
"end": {
- "line": 27,
+ "line": 29,
"column": 4,
- "offset": 571
+ "offset": 619
}
},
"description": "```go\nfield S2 S2\n```\n\n[`(b.S1).S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1.S2)\n\n\\@godef\\(\\\"S2\\\", S2\\),mark\\(S1S2, \\\"S2\\\"\\)"
@@ -249,7 +251,7 @@
\@godef\(\"S2\", S2\),mark\(S1S2, \"S2\"\)
-- S2-definition --
-godef/b/b.go:31:6-8: defined here as ```go
+godef/b/b.go:34:6-8: defined here as ```go
type S2 struct {
F1 string //@mark(S2F1, "F1")
F2 int //@mark(S2F2, "F2")
@@ -263,14 +265,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 31,
+ "line": 34,
"column": 6,
- "offset": 653
+ "offset": 741
},
"end": {
- "line": 31,
+ "line": 34,
"column": 8,
- "offset": 655
+ "offset": 743
}
},
"description": "```go\ntype S2 struct {\n\tF1 string //@mark(S2F1, \"F1\")\n\tF2 int //@mark(S2F2, \"F2\")\n\t*a.A //@godef(\"A\", AString),godef(\"a\",AImport)\n}\n```\n\n[`b.S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S2)"
@@ -287,7 +289,7 @@
[`b.S2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S2)
-- S2F1-definition --
-godef/b/b.go:32:2-4: defined here as ```go
+godef/b/b.go:35:2-4: defined here as ```go
field F1 string
```
@@ -299,14 +301,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 32,
+ "line": 35,
"column": 2,
- "offset": 672
+ "offset": 760
},
"end": {
- "line": 32,
+ "line": 35,
"column": 4,
- "offset": 674
+ "offset": 762
}
},
"description": "```go\nfield F1 string\n```\n\n[`(b.S2).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S2.F1)\n\n\\@mark\\(S2F1, \\\"F1\\\"\\)"
@@ -321,7 +323,7 @@
\@mark\(S2F1, \"F1\"\)
-- S2F2-definition --
-godef/b/b.go:33:2-4: defined here as ```go
+godef/b/b.go:36:2-4: defined here as ```go
field F2 int
```
@@ -333,14 +335,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 33,
+ "line": 36,
"column": 2,
- "offset": 705
+ "offset": 793
},
"end": {
- "line": 33,
+ "line": 36,
"column": 4,
- "offset": 707
+ "offset": 795
}
},
"description": "```go\nfield F2 int\n```\n\n[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S2.F2)\n\n\\@mark\\(S2F2, \\\"F2\\\"\\)"
@@ -354,8 +356,36 @@
[`(b.S2).F2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S2.F2)
\@mark\(S2F2, \"F2\"\)
+-- aAlias-definition --
+godef/b/b.go:25:6-12: defined here as ```go
+type aAlias = a.A //@mark(aAlias, "aAlias")
+
+```
+-- aAlias-definition-json --
+{
+ "span": {
+ "uri": "file://godef/b/b.go",
+ "start": {
+ "line": 25,
+ "column": 6,
+ "offset": 521
+ },
+ "end": {
+ "line": 25,
+ "column": 12,
+ "offset": 527
+ }
+ },
+ "description": "```go\ntype aAlias = a.A //@mark(aAlias, \"aAlias\")\n\n```"
+}
+
+-- aAlias-hover --
+```go
+type aAlias = a.A //@mark(aAlias, "aAlias")
+
+```
-- bX-definition --
-godef/b/b.go:54:7-8: defined here as ```go
+godef/b/b.go:57:7-8: defined here as ```go
const X untyped int = 0
```
@@ -367,14 +397,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 54,
+ "line": 57,
"column": 7,
- "offset": 1140
+ "offset": 1228
},
"end": {
- "line": 54,
+ "line": 57,
"column": 8,
- "offset": 1141
+ "offset": 1229
}
},
"description": "```go\nconst X untyped int = 0\n```\n\n[`b.X` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#X)\n\n\\@mark\\(bX, \\\"X\\\"\\),godef\\(\\\"X\\\", bX\\)"
diff --git a/internal/lsp/testdata/godef/b/c.go.golden b/internal/lsp/testdata/godef/b/c.go.golden
index 7852da7..9554c0d 100644
--- a/internal/lsp/testdata/godef/b/c.go.golden
+++ b/internal/lsp/testdata/godef/b/c.go.golden
@@ -1,9 +1,10 @@
-- S1-definition --
-godef/b/b.go:25:6-8: defined here as ```go
+godef/b/b.go:27:6-8: defined here as ```go
type S1 struct {
- F1 int //@mark(S1F1, "F1")
- S2 //@godef("S2", S2),mark(S1S2, "S2")
- a.A //@godef("A", AString)
+ F1 int //@mark(S1F1, "F1")
+ S2 //@godef("S2", S2),mark(S1S2, "S2")
+ a.A //@godef("A", AString)
+ aAlias //@godef("a", aAlias)
}
```
@@ -13,31 +14,32 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 25,
+ "line": 27,
"column": 6,
- "offset": 521
+ "offset": 566
},
"end": {
- "line": 25,
+ "line": 27,
"column": 8,
- "offset": 523
+ "offset": 568
}
},
- "description": "```go\ntype S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2),mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", AString)\n}\n```\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1)"
+ "description": "```go\ntype S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2),mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", AString)\n\taAlias //@godef(\"a\", aAlias)\n}\n```\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1)"
}
-- S1-hover --
```go
type S1 struct {
- F1 int //@mark(S1F1, "F1")
- S2 //@godef("S2", S2),mark(S1S2, "S2")
- a.A //@godef("A", AString)
+ F1 int //@mark(S1F1, "F1")
+ S2 //@godef("S2", S2),mark(S1S2, "S2")
+ a.A //@godef("A", AString)
+ aAlias //@godef("a", aAlias)
}
```
[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1)
-- S1F1-definition --
-godef/b/b.go:26:2-4: defined here as ```go
+godef/b/b.go:28:2-4: defined here as ```go
field F1 int
```
@@ -49,14 +51,14 @@
"span": {
"uri": "file://godef/b/b.go",
"start": {
- "line": 26,
+ "line": 28,
"column": 2,
- "offset": 540
+ "offset": 585
},
"end": {
- "line": 26,
+ "line": 28,
"column": 4,
- "offset": 542
+ "offset": 587
}
},
"description": "```go\nfield F1 int\n```\n\n[`(b.S1).F1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b?utm_source=gopls#S1.F1)\n\n\\@mark\\(S1F1, \\\"F1\\\"\\)"
diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden
index f10805c..a8a3799 100644
--- a/internal/lsp/testdata/summary.txt.golden
+++ b/internal/lsp/testdata/summary.txt.golden
@@ -15,7 +15,7 @@
SemanticTokenCount = 2
SuggestedFixCount = 38
FunctionExtractionCount = 12
-DefinitionsCount = 63
+DefinitionsCount = 64
TypeDefinitionsCount = 2
HighlightsCount = 69
ReferencesCount = 25