internal/lsp: add "type "  to hover messages for structs/interfaces/etc

Fixes golang/go#41357

Change-Id: Iccc039425110ea37499e18d8a81e577a9c1b0b01
Reviewed-on: https://go-review.googlesource.com/c/tools/+/260006
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Peter Weinberger <pjw@google.com>
diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go
index b2cba20..5f91152 100644
--- a/internal/lsp/source/hover.go
+++ b/internal/lsp/source/hover.go
@@ -46,6 +46,10 @@
 
 	source  interface{}
 	comment *ast.CommentGroup
+
+	// isTypeName reports whether the identifier is a type name. In such cases,
+	// the hover has the prefix "type ".
+	isType bool
 }
 
 func Hover(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*protocol.Hover, error) {
@@ -95,6 +99,9 @@
 			return nil, err
 		}
 		h.Signature = b.String()
+		if h.isType {
+			h.Signature = "type " + h.Signature
+		}
 	case types.Object:
 		// If the variable is implicitly declared in a type switch, we need to
 		// manually generate its object string.
@@ -267,6 +274,7 @@
 			if err != nil {
 				return nil, err
 			}
+			_, info.isType = obj.(*types.TypeName)
 		}
 	case *ast.TypeSpec:
 		if obj.Parent() == types.Universe {
diff --git a/internal/lsp/testdata/godef/a/d.go.golden b/internal/lsp/testdata/godef/a/d.go.golden
index 9bcf614..1427f37 100644
--- a/internal/lsp/testdata/godef/a/d.go.golden
+++ b/internal/lsp/testdata/godef/a/d.go.golden
@@ -98,7 +98,7 @@
 \@Other
 -- Thing-definition --
 godef/a/d.go:5:6-11: defined here as ```go
-Thing struct {
+type Thing struct {
 	Member string //@Member
 }
 ```
@@ -119,12 +119,12 @@
 			"offset": 67
 		}
 	},
-	"description": "```go\nThing struct {\n\tMember string //@Member\n}\n```\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)"
+	"description": "```go\ntype Thing struct {\n\tMember string //@Member\n}\n```\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)"
 }
 
 -- Thing-hover --
 ```go
-Thing struct {
+type Thing struct {
 	Member string //@Member
 }
 ```
diff --git a/internal/lsp/testdata/godef/b/b.go.golden b/internal/lsp/testdata/godef/b/b.go.golden
index e2ff0bb..4ebb96a 100644
--- a/internal/lsp/testdata/godef/b/b.go.golden
+++ b/internal/lsp/testdata/godef/b/b.go.golden
@@ -82,7 +82,7 @@
 [`a` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a)
 -- AString-definition --
 godef/a/a.go:26:6-7: defined here as ```go
-A string //@mark(AString, "A")
+type A string //@mark(AString, "A")
 
 ```
 
@@ -102,12 +102,12 @@
 			"offset": 453
 		}
 	},
-	"description": "```go\nA string //@mark(AString, \"A\")\n\n```\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)"
+	"description": "```go\ntype A string //@mark(AString, \"A\")\n\n```\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)"
 }
 
 -- AString-hover --
 ```go
-A string //@mark(AString, "A")
+type A string //@mark(AString, "A")
 
 ```
 
@@ -144,7 +144,7 @@
 [`a.AStuff` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#AStuff)
 -- S1-definition --
 godef/b/b.go:25:6-8: defined here as ```go
-S1 struct {
+type S1 struct {
 	F1  int //@mark(S1F1, "F1")
 	S2      //@godef("S2", S2),mark(S1S2, "S2")
 	a.A     //@godef("A", AString)
@@ -167,12 +167,12 @@
 			"offset": 523
 		}
 	},
-	"description": "```go\nS1 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#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}\n```\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)"
 }
 
 -- S1-hover --
 ```go
-S1 struct {
+type S1 struct {
 	F1  int //@mark(S1F1, "F1")
 	S2      //@godef("S2", S2),mark(S1S2, "S2")
 	a.A     //@godef("A", AString)
@@ -250,7 +250,7 @@
 \@godef\(\"S2\", S2\),mark\(S1S2, \"S2\"\)
 -- S2-definition --
 godef/b/b.go:31:6-8: defined here as ```go
-S2 struct {
+type S2 struct {
 	F1   string //@mark(S2F1, "F1")
 	F2   int    //@mark(S2F2, "F2")
 	*a.A        //@godef("A", AString),godef("a",AImport)
@@ -273,12 +273,12 @@
 			"offset": 655
 		}
 	},
-	"description": "```go\nS2 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#S2)"
+	"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#S2)"
 }
 
 -- S2-hover --
 ```go
-S2 struct {
+type S2 struct {
 	F1   string //@mark(S2F1, "F1")
 	F2   int    //@mark(S2F2, "F2")
 	*a.A        //@godef("A", AString),godef("a",AImport)
diff --git a/internal/lsp/testdata/godef/b/c.go.golden b/internal/lsp/testdata/godef/b/c.go.golden
index 85c6854..d551f22 100644
--- a/internal/lsp/testdata/godef/b/c.go.golden
+++ b/internal/lsp/testdata/godef/b/c.go.golden
@@ -1,6 +1,6 @@
 -- S1-definition --
 godef/b/b.go:25:6-8: defined here as ```go
-S1 struct {
+type S1 struct {
 	F1  int //@mark(S1F1, "F1")
 	S2      //@godef("S2", S2),mark(S1S2, "S2")
 	a.A     //@godef("A", AString)
@@ -23,12 +23,12 @@
 			"offset": 523
 		}
 	},
-	"description": "```go\nS1 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#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}\n```\n\n[`b.S1` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)"
 }
 
 -- S1-hover --
 ```go
-S1 struct {
+type S1 struct {
 	F1  int //@mark(S1F1, "F1")
 	S2      //@godef("S2", S2),mark(S1S2, "S2")
 	a.A     //@godef("A", AString)
diff --git a/internal/lsp/testdata/godef/b/e.go.golden b/internal/lsp/testdata/godef/b/e.go.golden
index 1e11a0f..d5eb1e9 100644
--- a/internal/lsp/testdata/godef/b/e.go.golden
+++ b/internal/lsp/testdata/godef/b/e.go.golden
@@ -68,7 +68,7 @@
 \@Other
 -- Thing-definition --
 godef/a/d.go:5:6-11: defined here as ```go
-Thing struct {
+type Thing struct {
 	Member string //@Member
 }
 ```
@@ -89,12 +89,12 @@
 			"offset": 67
 		}
 	},
-	"description": "```go\nThing struct {\n\tMember string //@Member\n}\n```\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)"
+	"description": "```go\ntype Thing struct {\n\tMember string //@Member\n}\n```\n\n[`a.Thing` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)"
 }
 
 -- Thing-hover --
 ```go
-Thing struct {
+type Thing struct {
 	Member string //@Member
 }
 ```