1
0
mirror of https://github.com/golang/go synced 2024-11-18 14:14:46 -07:00

internal/lsp: expose godoc or pkg.go.dev link on hover

This adds a link to documentation to the hover contents for the
current symbol if it is exported.

Updates golang/go#34240

Change-Id: I19c66e91e46f79284bfd0006c53f518eda4edef7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/200604
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Barnaby Keene 2019-10-11 16:03:23 +01:00 committed by Rebecca Stambler
parent 61fa4dffed
commit 69111344d4
13 changed files with 92 additions and 20 deletions

View File

@ -21,6 +21,6 @@ func (r *runner) Import(t *testing.T, spn span.Span) {
return out, nil
}))
if want != got {
t.Errorf("imports failed for %s, expected:\n%v\ngot:\n%v", filename, want, got)
t.Errorf("imports failed for %s, expected:\n%q\ngot:\n%q", filename, want, got)
}
}

View File

@ -73,6 +73,7 @@ func (s *Server) toProtocolHoverContents(ctx context.Context, h *source.HoverInf
} else {
content.Value = signature
}
content.Value += "\n" + h.DocumentationLink(options)
case source.FullDocumentation:
if h.FullDocumentation != "" {
doc := h.FullDocumentation
@ -83,6 +84,7 @@ func (s *Server) toProtocolHoverContents(ctx context.Context, h *source.HoverInf
} else {
content.Value = signature
}
content.Value += "\n" + h.DocumentationLink(options)
case source.Structured:
b, err := json.Marshal(h)
if err != nil {

View File

@ -31,10 +31,23 @@ type HoverInformation struct {
// FullDocumentation is the symbol's full documentation.
FullDocumentation string `json:"fullDocumentation"`
// pkgPath holds the package path of the hovered symbol.
pkgPath string
// symbolName holds the symbol name without any package prefix.
symbolName string
source interface{}
comment *ast.CommentGroup
}
func (h *HoverInformation) DocumentationLink(options Options) string {
if h.symbolName == "" || h.pkgPath == "" || options.LinkTarget == "" {
return ""
}
return fmt.Sprintf("[%s on %s](https://%s/%s#%s)", h.symbolName, options.LinkTarget, options.LinkTarget, h.pkgPath, h.symbolName)
}
func (i *IdentifierInfo) Hover(ctx context.Context) (*HoverInformation, error) {
ctx, done := trace.StartSpan(ctx, "source.Hover")
defer done()
@ -54,11 +67,17 @@ func (i *IdentifierInfo) Hover(ctx context.Context) (*HoverInformation, error) {
case types.Object:
h.Signature = objectString(x, i.qf)
}
// Set the documentation.
if i.Declaration.obj != nil {
h.SingleLine = objectString(i.Declaration.obj, i.qf)
if obj := i.Declaration.obj; obj != nil {
// Only show the documentation links for symbols in the package scope.
// TODO(https://golang.org/issue/34240): Handle other symbols.
if obj.Exported() && obj.Parent() == obj.Pkg().Scope() {
h.pkgPath = obj.Pkg().Path()
h.symbolName = obj.Name()
}
// Set the documentation.
h.SingleLine = objectString(obj, i.qf)
}
if h.comment != nil {
h.FullDocumentation = h.comment.Text()
h.Synopsis = doc.Synopsis(h.FullDocumentation)

View File

@ -512,6 +512,7 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) {
hover += h.Synopsis + "\n"
}
hover += h.Signature
hover += "\n" + h.DocumentationLink(r.view.Options())
rng, err := ident.Declaration.Range()
if err != nil {
t.Fatal(err)

View File

@ -1,5 +1,6 @@
-- funccgoexample-definition --
cgo/declarecgo.go:17:6-13: defined here as func cgo.Example()
[Example on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/cgo#Example)
-- funccgoexample-definition-json --
{
"span": {
@ -15,8 +16,9 @@ cgo/declarecgo.go:17:6-13: defined here as func cgo.Example()
"offset": 160
}
},
"description": "func cgo.Example()"
"description": "func cgo.Example()\n[Example on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/cgo#Example)"
}
-- funccgoexample-hover --
func cgo.Example()
[Example on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/cgo#Example)

View File

@ -1,5 +1,6 @@
-- Random-definition --
godef/a/random.go:3:6-12: defined here as func Random() int
[Random on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Random)
-- Random-definition-json --
{
"span": {
@ -15,13 +16,15 @@ godef/a/random.go:3:6-12: defined here as func Random() int
"offset": 22
}
},
"description": "func Random() int"
"description": "func Random() int\n[Random on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Random)"
}
-- Random-hover --
func Random() int
[Random on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Random)
-- Random2-definition --
godef/a/random.go:8:6-13: defined here as func Random2(y int) int
[Random2 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Random2)
-- Random2-definition-json --
{
"span": {
@ -37,11 +40,12 @@ godef/a/random.go:8:6-13: defined here as func Random2(y int) int
"offset": 78
}
},
"description": "func Random2(y int) int"
"description": "func Random2(y int) int\n[Random2 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Random2)"
}
-- Random2-hover --
func Random2(y int) int
[Random2 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Random2)
-- err-definition --
godef/a/a.go:14:6-9: defined here as var err error
-- err-definition-json --
@ -64,8 +68,11 @@ godef/a/a.go:14:6-9: defined here as var err error
-- err-hover --
var err error
-- make-hover --
The make built-in function allocates and initializes an object of type slice, map, or chan (only).
func(t Type, size ...IntegerType) Type
-- string-hover --
string

View File

@ -22,6 +22,7 @@ field Member string
-- Member-hover --
@Member
field Member string
-- Method-definition --
godef/a/d.go:15:16-22: defined here as func (Thing).Method(i int) string
-- Method-definition-json --
@ -44,8 +45,10 @@ godef/a/d.go:15:16-22: defined here as func (Thing).Method(i int) string
-- Method-hover --
func (Thing).Method(i int) string
-- Other-definition --
godef/a/d.go:9:5-10: defined here as var Other Thing
[Other on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)
-- Other-definition-json --
{
"span": {
@ -61,15 +64,17 @@ godef/a/d.go:9:5-10: defined here as var Other Thing
"offset": 91
}
},
"description": "var Other Thing"
"description": "var Other Thing\n[Other on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)"
}
-- Other-hover --
var Other Thing
[Other on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)
-- Thing-definition --
godef/a/d.go:5:6-11: defined here as Thing struct {
Member string //@Member
}
[Thing on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)
-- Thing-definition-json --
{
"span": {
@ -85,15 +90,17 @@ godef/a/d.go:5:6-11: defined here as Thing struct {
"offset": 35
}
},
"description": "Thing struct {\n\tMember string //@Member\n}"
"description": "Thing struct {\n\tMember string //@Member\n}\n[Thing on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)"
}
-- Thing-hover --
Thing struct {
Member string //@Member
}
[Thing on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)
-- Things-definition --
godef/a/d.go:11:6-12: defined here as func Things(val []string) []Thing
[Things on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)
-- Things-definition-json --
{
"span": {
@ -109,8 +116,9 @@ godef/a/d.go:11:6-12: defined here as func Things(val []string) []Thing
"offset": 119
}
},
"description": "func Things(val []string) []Thing"
"description": "func Things(val []string) []Thing\n[Things on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)"
}
-- Things-hover --
func Things(val []string) []Thing
[Things on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)

View File

@ -20,6 +20,7 @@ godef/a/f.go:8:9-10: defined here as var y string
-- switchStringY-hover --
var y string
-- switchY-definition --
godef/a/f.go:8:9-10: defined here as var y int
-- switchY-definition-json --
@ -42,3 +43,4 @@ godef/a/f.go:8:9-10: defined here as var y int
-- switchY-hover --
var y int

View File

@ -20,6 +20,7 @@ godef/a/random.go:16:15-18: defined here as func (*Pos).Sum() int
-- PosSum-hover --
func (*Pos).Sum() int
-- PosX-definition --
godef/a/random.go:13:2-3: defined here as @mark(PosX, "x"),mark(PosY, "y")
field x int
@ -44,6 +45,7 @@ field x int
-- PosX-hover --
@mark(PosX, "x"),mark(PosY, "y")
field x int
-- RandomParamY-definition --
godef/a/random.go:8:14-15: defined here as var y int
-- RandomParamY-definition-json --
@ -66,3 +68,4 @@ godef/a/random.go:8:14-15: defined here as var y int
-- RandomParamY-hover --
var y int

View File

@ -1,5 +1,7 @@
-- A-definition --
godef/a/a.go:7:6-7: defined here as A string //@A
[A on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)
-- A-definition-json --
{
"span": {
@ -15,12 +17,13 @@ godef/a/a.go:7:6-7: defined here as A string //@A
"offset": 76
}
},
"description": "A string //@A"
"description": "A string //@A\n\n[A on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)"
}
-- A-hover --
A string //@A
[A on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#A)
-- AImport-definition --
godef/b/b.go:5:2-43: defined here as package a ("golang.org/x/tools/internal/lsp/godef/a")
-- AImport-definition-json --
@ -43,8 +46,10 @@ godef/b/b.go:5:2-43: defined here as package a ("golang.org/x/tools/internal/lsp
-- AImport-hover --
package a ("golang.org/x/tools/internal/lsp/godef/a")
-- AStuff-definition --
godef/a/a.go:9:6-12: defined here as func a.AStuff()
[AStuff on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#AStuff)
-- AStuff-definition-json --
{
"span": {
@ -60,11 +65,12 @@ godef/a/a.go:9:6-12: defined here as func a.AStuff()
"offset": 101
}
},
"description": "func a.AStuff()"
"description": "func a.AStuff()\n[AStuff on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#AStuff)"
}
-- AStuff-hover --
func a.AStuff()
[AStuff on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#AStuff)
-- PackageFoo-definition --
foo/foo.go:1:1-30:16: defined here as myFoo "golang.org/x/tools/internal/lsp/foo" //@mark(myFoo, "myFoo"),godef("foo", PackageFoo),godef("myFoo", myFoo)
-- PackageFoo-definition-json --
@ -94,6 +100,7 @@ godef/b/b.go:8:6-8: defined here as S1 struct {
S2 //@godef("S2", S2), mark(S1S2, "S2")
a.A //@godef("A", A)
}
[S1 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)
-- S1-definition-json --
{
"span": {
@ -109,7 +116,7 @@ godef/b/b.go:8:6-8: defined here as S1 struct {
"offset": 195
}
},
"description": "S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2), mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", A)\n}"
"description": "S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2), mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", A)\n}\n[S1 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)"
}
-- S1-hover --
@ -118,6 +125,7 @@ S1 struct {
S2 //@godef("S2", S2), mark(S1S2, "S2")
a.A //@godef("A", A)
}
[S1 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)
-- S1F1-definition --
godef/b/b.go:9:2-4: defined here as @mark(S1F1, "F1")
field F1 int
@ -142,6 +150,7 @@ field F1 int
-- S1F1-hover --
@mark(S1F1, "F1")
field F1 int
-- S1S2-definition --
godef/b/b.go:10:2-4: defined here as @godef("S2", S2), mark(S1S2, "S2")
field S2 S2
@ -166,12 +175,14 @@ field S2 S2
-- S1S2-hover --
@godef("S2", S2), mark(S1S2, "S2")
field S2 S2
-- S2-definition --
godef/b/b.go:14:6-8: defined here as S2 struct {
F1 string //@mark(S2F1, "F1")
F2 int //@mark(S2F2, "F2")
*a.A //@godef("A", A),godef("a",AImport)
}
[S2 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2)
-- S2-definition-json --
{
"span": {
@ -187,7 +198,7 @@ godef/b/b.go:14:6-8: defined here as S2 struct {
"offset": 322
}
},
"description": "S2 struct {\n\tF1 string //@mark(S2F1, \"F1\")\n\tF2 int //@mark(S2F2, \"F2\")\n\t*a.A //@godef(\"A\", A),godef(\"a\",AImport)\n}"
"description": "S2 struct {\n\tF1 string //@mark(S2F1, \"F1\")\n\tF2 int //@mark(S2F2, \"F2\")\n\t*a.A //@godef(\"A\", A),godef(\"a\",AImport)\n}\n[S2 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2)"
}
-- S2-hover --
@ -196,6 +207,7 @@ S2 struct {
F2 int //@mark(S2F2, "F2")
*a.A //@godef("A", A),godef("a",AImport)
}
[S2 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S2)
-- S2F1-definition --
godef/b/b.go:15:2-4: defined here as @mark(S2F1, "F1")
field F1 string
@ -220,6 +232,7 @@ field F1 string
-- S2F1-hover --
@mark(S2F1, "F1")
field F1 string
-- S2F2-definition --
godef/b/b.go:16:2-4: defined here as @mark(S2F2, "F2")
field F2 int
@ -244,6 +257,7 @@ field F2 int
-- S2F2-hover --
@mark(S2F2, "F2")
field F2 int
-- Stuff-definition --
godef/a/a.go:9:6-11: defined here as func a.Stuff()
-- Stuff-definition-json --
@ -268,6 +282,7 @@ godef/a/a.go:9:6-11: defined here as func a.Stuff()
func a.Stuff()
-- X-definition --
godef/b/b.go:37:7-8: defined here as const X untyped int = 0
[X on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)
-- X-definition-json --
{
"span": {
@ -283,11 +298,12 @@ godef/b/b.go:37:7-8: defined here as const X untyped int = 0
"offset": 796
}
},
"description": "const X untyped int = 0"
"description": "const X untyped int = 0\n[X on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)"
}
-- X-hover --
const X untyped int = 0
[X on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#X)
-- myFoo-definition --
godef/b/b.go:4:2-7: defined here as package myFoo ("golang.org/x/tools/internal/lsp/foo")
-- myFoo-definition-json --
@ -310,3 +326,4 @@ godef/b/b.go:4:2-7: defined here as package myFoo ("golang.org/x/tools/internal/
-- myFoo-hover --
package myFoo ("golang.org/x/tools/internal/lsp/foo")

View File

@ -4,6 +4,7 @@ godef/b/b.go:8:6-8: defined here as S1 struct {
S2 //@godef("S2", S2), mark(S1S2, "S2")
a.A //@godef("A", A)
}
[S1 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)
-- S1-definition-json --
{
"span": {
@ -19,7 +20,7 @@ godef/b/b.go:8:6-8: defined here as S1 struct {
"offset": 195
}
},
"description": "S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2), mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", A)\n}"
"description": "S1 struct {\n\tF1 int //@mark(S1F1, \"F1\")\n\tS2 //@godef(\"S2\", S2), mark(S1S2, \"S2\")\n\ta.A //@godef(\"A\", A)\n}\n[S1 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)"
}
-- S1-hover --
@ -28,6 +29,7 @@ S1 struct {
S2 //@godef("S2", S2), mark(S1S2, "S2")
a.A //@godef("A", A)
}
[S1 on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/b#S1)
-- S1F1-definition --
godef/b/b.go:9:2-4: defined here as @mark(S1F1, "F1")
field F1 int
@ -52,3 +54,4 @@ field F1 int
-- S1F1-hover --
@mark(S1F1, "F1")
field F1 int

View File

@ -22,8 +22,10 @@ field Member string
-- Member-hover --
@Member
field Member string
-- Other-definition --
godef/a/d.go:9:5-10: defined here as var a.Other a.Thing
[Other on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)
-- Other-definition-json --
{
"span": {
@ -39,15 +41,17 @@ godef/a/d.go:9:5-10: defined here as var a.Other a.Thing
"offset": 91
}
},
"description": "var a.Other a.Thing"
"description": "var a.Other a.Thing\n[Other on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)"
}
-- Other-hover --
var a.Other a.Thing
[Other on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Other)
-- Thing-definition --
godef/a/d.go:5:6-11: defined here as Thing struct {
Member string //@Member
}
[Thing on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)
-- Thing-definition-json --
{
"span": {
@ -63,15 +67,17 @@ godef/a/d.go:5:6-11: defined here as Thing struct {
"offset": 35
}
},
"description": "Thing struct {\n\tMember string //@Member\n}"
"description": "Thing struct {\n\tMember string //@Member\n}\n[Thing on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)"
}
-- Thing-hover --
Thing struct {
Member string //@Member
}
[Thing on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Thing)
-- Things-definition --
godef/a/d.go:11:6-12: defined here as func a.Things(val []string) []a.Thing
[Things on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)
-- Things-definition-json --
{
"span": {
@ -87,8 +93,9 @@ godef/a/d.go:11:6-12: defined here as func a.Things(val []string) []a.Thing
"offset": 119
}
},
"description": "func a.Things(val []string) []a.Thing"
"description": "func a.Things(val []string) []a.Thing\n[Things on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)"
}
-- Things-hover --
func a.Things(val []string) []a.Thing
[Things on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a#Things)

View File

@ -20,3 +20,4 @@ godef/broken/unclosedIf.go:7:7-19: defined here as var myUnclosedIf string
-- myUnclosedIf-hover --
var myUnclosedIf string