From cd7c003cd38984ebf592aa8e4755c832a8d632bf Mon Sep 17 00:00:00 2001 From: Jean-Hadrien Chabran Date: Fri, 30 Apr 2021 21:34:57 +0200 Subject: [PATCH] internal/lsp: add support for hovering runes Enable to hover runes found in basic literals in various forms. When a rune is found, the hover message provides a summary composed of a printable version (if it exists) of the rune, its codepoint and its name. Behaviour varies slightly depending on the basic literal: rune literals always display the summary when hovered, string literals only display it when an escaped rune sequence is found to avoid providing unnecessary information, and finally number literals only when expressed as a hexadecimal number whose size ranges from one to eight bytes. Fixes golang/go#38239 Change-Id: I024fdd5c511a45c7c285e200ce1eda0669a45491 Reviewed-on: https://go-review.googlesource.com/c/tools/+/321810 Reviewed-by: Rebecca Stambler Trust: Rebecca Stambler Trust: Robert Findley Run-TryBot: Rebecca Stambler gopls-CI: kokoro TryBot-Result: Go Bot --- go.mod | 1 + go.sum | 3 + internal/lsp/cmd/test/cmdtest.go | 4 + internal/lsp/lsp_test.go | 39 ++++- internal/lsp/source/hover.go | 155 ++++++++++++++++++ internal/lsp/source/source_test.go | 35 +++- internal/lsp/testdata/basiclit/basiclit.go | 43 +++++ .../lsp/testdata/cgo/declarecgo.go.golden | 2 +- .../lsp/testdata/cgoimport/usecgo.go.golden | 2 +- internal/lsp/testdata/godef/a/a.go | 30 ++-- internal/lsp/testdata/godef/a/a.go.golden | 40 ++--- .../lsp/testdata/godef/a/a_test.go.golden | 2 +- .../lsp/testdata/godef/a/a_x_test.go.golden | 2 +- internal/lsp/testdata/godef/a/d.go | 2 +- internal/lsp/testdata/godef/a/d.go.golden | 32 ++-- internal/lsp/testdata/godef/a/f.go | 4 +- internal/lsp/testdata/godef/a/f.go.golden | 6 +- internal/lsp/testdata/godef/a/g.go | 2 +- internal/lsp/testdata/godef/a/g.go.golden | 2 +- internal/lsp/testdata/godef/a/h.go | 46 +++--- internal/lsp/testdata/godef/a/h.go.golden | 46 +++--- .../lsp/testdata/godef/a/random.go.golden | 8 +- internal/lsp/testdata/godef/b/b.go | 14 +- internal/lsp/testdata/godef/b/b.go.golden | 78 ++++----- internal/lsp/testdata/godef/b/c.go.golden | 12 +- internal/lsp/testdata/godef/b/e.go | 6 +- internal/lsp/testdata/godef/b/e.go.golden | 30 ++-- internal/lsp/testdata/godef/b/h.go | 4 +- internal/lsp/testdata/godef/b/h.go.golden | 4 +- .../godef/broken/unclosedIf.go.golden | 2 +- .../godef/infer_generics/inferred.go.golden | 10 +- internal/lsp/tests/tests.go | 23 ++- 32 files changed, 491 insertions(+), 198 deletions(-) diff --git a/go.mod b/go.mod index 1c1dad410..ff8184fac 100644 --- a/go.mod +++ b/go.mod @@ -8,5 +8,6 @@ require ( golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e + golang.org/x/text v0.3.6 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 ) diff --git a/go.sum b/go.sum index a56a1307a..b4edbe6be 100644 --- a/go.sum +++ b/go.sum @@ -18,7 +18,10 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/internal/lsp/cmd/test/cmdtest.go b/internal/lsp/cmd/test/cmdtest.go index 2e9272611..832d794c7 100644 --- a/internal/lsp/cmd/test/cmdtest.go +++ b/internal/lsp/cmd/test/cmdtest.go @@ -108,6 +108,10 @@ func (r *runner) AddImport(t *testing.T, uri span.URI, expectedImport string) { //TODO: import addition not supported on command line } +func (r *runner) Hover(t *testing.T, spn span.Span, info string) { + //TODO: hovering not supported on command line +} + func (r *runner) runGoplsCmd(t testing.TB, args ...string) (string, string) { rStdout, wStdout, err := os.Pipe() if err != nil { diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index f095489c7..d21d71d66 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -718,7 +718,7 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) { didSomething := false if hover != nil { didSomething = true - tag := fmt.Sprintf("%s-hover", d.Name) + tag := fmt.Sprintf("%s-hoverdef", d.Name) expectHover := string(r.data.Golden(tag, d.Src.URI().Filename(), func() ([]byte, error) { return []byte(hover.Contents.Value), nil })) @@ -840,6 +840,43 @@ func (r *runner) Highlight(t *testing.T, src span.Span, locations []span.Span) { } } +func (r *runner) Hover(t *testing.T, src span.Span, text string) { + m, err := r.data.Mapper(src.URI()) + if err != nil { + t.Fatal(err) + } + loc, err := m.Location(src) + if err != nil { + t.Fatalf("failed for %v", err) + } + tdpp := protocol.TextDocumentPositionParams{ + TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI}, + Position: loc.Range.Start, + } + params := &protocol.HoverParams{ + TextDocumentPositionParams: tdpp, + } + hover, err := r.server.Hover(r.ctx, params) + if err != nil { + t.Fatal(err) + } + if text == "" { + if hover != nil { + t.Errorf("want nil, got %v\n", hover) + } + } else { + if hover == nil { + t.Fatalf("want hover result to include %s, but got nil", text) + } + if got := hover.Contents.Value; got != text { + t.Errorf("want %v, got %v\n", text, got) + } + if want, got := loc.Range, hover.Range; want != got { + t.Errorf("want range %v, got %v instead", want, got) + } + } +} + func (r *runner) References(t *testing.T, src span.Span, itemList []span.Span) { sm, err := r.data.Mapper(src.URI()) if err != nil { diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go index 0bc92d1fb..56666d352 100644 --- a/internal/lsp/source/hover.go +++ b/internal/lsp/source/hover.go @@ -14,9 +14,12 @@ import ( "go/format" "go/token" "go/types" + "strconv" "strings" "time" + "unicode/utf8" + "golang.org/x/text/unicode/runenames" "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/typeparams" @@ -66,6 +69,9 @@ type HoverInformation struct { func Hover(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*protocol.Hover, error) { ident, err := Identifier(ctx, snapshot, fh, position) if err != nil { + if hover, innerErr := hoverRune(ctx, snapshot, fh, position); innerErr == nil { + return hover, nil + } return nil, nil } h, err := HoverIdentifier(ctx, ident) @@ -93,6 +99,155 @@ func Hover(ctx context.Context, snapshot Snapshot, fh FileHandle, position proto }, nil } +func hoverRune(ctx context.Context, snapshot Snapshot, fh FileHandle, position protocol.Position) (*protocol.Hover, error) { + ctx, done := event.Start(ctx, "source.hoverRune") + defer done() + + r, mrng, err := findRune(ctx, snapshot, fh, position) + if err != nil { + return nil, err + } + rng, err := mrng.Range() + if err != nil { + return nil, err + } + + var desc string + runeName := runenames.Name(r) + if len(runeName) > 0 && runeName[0] == '<' { + // Check if the rune looks like an HTML tag. If so, trim the surrounding <> + // characters to work around https://github.com/microsoft/vscode/issues/124042. + runeName = strings.TrimRight(runeName[1:], ">") + } + if strconv.IsPrint(r) { + desc = fmt.Sprintf("'%s', U+%04X, %s", string(r), uint32(r), runeName) + } else { + desc = fmt.Sprintf("U+%04X, %s", uint32(r), runeName) + } + return &protocol.Hover{ + Contents: protocol.MarkupContent{ + Kind: snapshot.View().Options().PreferredContentFormat, + Value: desc, + }, + Range: rng, + }, nil +} + +// ErrNoRuneFound is the error returned when no rune is found at a particular position. +var ErrNoRuneFound = errors.New("no rune found") + +// findRune returns rune information for a position in a file. +func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (rune, MappedRange, error) { + pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage) + if err != nil { + return 0, MappedRange{}, err + } + spn, err := pgf.Mapper.PointSpan(pos) + if err != nil { + return 0, MappedRange{}, err + } + rng, err := spn.Range(pgf.Mapper.Converter) + if err != nil { + return 0, MappedRange{}, err + } + + // Find the basic literal enclosing the given position, if there is one. + var lit *ast.BasicLit + var found bool + ast.Inspect(pgf.File, func(n ast.Node) bool { + if found { + return false + } + if n, ok := n.(*ast.BasicLit); ok && rng.Start >= n.Pos() && rng.Start <= n.End() { + lit = n + found = true + } + return !found + }) + if !found { + return 0, MappedRange{}, ErrNoRuneFound + } + + var r rune + var start, end token.Pos + switch lit.Kind { + case token.CHAR: + s, err := strconv.Unquote(lit.Value) + if err != nil { + // If the conversion fails, it's because of an invalid syntax, therefore + // there is no rune to be found. + return 0, MappedRange{}, ErrNoRuneFound + } + r, _ = utf8.DecodeRuneInString(s) + if r == utf8.RuneError { + return 0, MappedRange{}, fmt.Errorf("rune error") + } + start, end = lit.Pos(), lit.End() + case token.INT: + // It's an integer, scan only if it is a hex litteral whose bitsize in + // ranging from 8 to 32. + if !(strings.HasPrefix(lit.Value, "0x") && len(lit.Value[2:]) >= 2 && len(lit.Value[2:]) <= 8) { + return 0, MappedRange{}, ErrNoRuneFound + } + v, err := strconv.ParseUint(lit.Value[2:], 16, 32) + if err != nil { + return 0, MappedRange{}, err + } + r = rune(v) + if r == utf8.RuneError { + return 0, MappedRange{}, fmt.Errorf("rune error") + } + start, end = lit.Pos(), lit.End() + case token.STRING: + // It's a string, scan only if it contains a unicode escape sequence under or before the + // current cursor position. + var found bool + strMappedRng, err := posToMappedRange(snapshot, pkg, lit.Pos(), lit.End()) + if err != nil { + return 0, MappedRange{}, err + } + strRng, err := strMappedRng.Range() + if err != nil { + return 0, MappedRange{}, err + } + offset := strRng.Start.Character + for i := pos.Character - offset; i > 0; i-- { + // Start at the cursor position and search backward for the beginning of a rune escape sequence. + rr, _ := utf8.DecodeRuneInString(lit.Value[i:]) + if rr == utf8.RuneError { + return 0, MappedRange{}, fmt.Errorf("rune error") + } + if rr == '\\' { + // Got the beginning, decode it. + var tail string + r, _, tail, err = strconv.UnquoteChar(lit.Value[i:], '"') + if err != nil { + // If the conversion fails, it's because of an invalid syntax, therefore is no rune to be found. + return 0, MappedRange{}, ErrNoRuneFound + } + // Only the rune escape sequence part of the string has to be highlighted, recompute the range. + runeLen := len(lit.Value) - (int(i) + len(tail)) + start = token.Pos(int(lit.Pos()) + int(i)) + end = token.Pos(int(start) + runeLen) + found = true + break + } + } + if !found { + // No escape sequence found + return 0, MappedRange{}, ErrNoRuneFound + } + default: + return 0, MappedRange{}, ErrNoRuneFound + } + + mappedRange, err := posToMappedRange(snapshot, pkg, start, end) + if err != nil { + return 0, MappedRange{}, err + } + return r, mappedRange, nil +} + func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverInformation, error) { ctx, done := event.Start(ctx, "source.Hover") defer done() diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index f1ab3ff4c..83ce712c8 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -576,12 +576,12 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) { didSomething := false if hover != "" { didSomething = true - tag := fmt.Sprintf("%s-hover", d.Name) + tag := fmt.Sprintf("%s-hoverdef", d.Name) expectHover := string(r.data.Golden(tag, d.Src.URI().Filename(), func() ([]byte, error) { return []byte(hover), nil })) if hover != expectHover { - t.Errorf("hover for %s failed:\n%s", d.Src, tests.Diff(t, expectHover, hover)) + t.Errorf("hoverdef for %s failed:\n%s", d.Src, tests.Diff(t, expectHover, hover)) } } if !d.OnlyHover { @@ -682,6 +682,37 @@ func (r *runner) Highlight(t *testing.T, src span.Span, locations []span.Span) { } } +func (r *runner) Hover(t *testing.T, src span.Span, text string) { + ctx := r.ctx + _, srcRng, err := spanToRange(r.data, src) + if err != nil { + t.Fatal(err) + } + fh, err := r.snapshot.GetFile(r.ctx, src.URI()) + if err != nil { + t.Fatal(err) + } + hover, err := source.Hover(ctx, r.snapshot, fh, srcRng.Start) + if err != nil { + t.Errorf("hover failed for %s: %v", src.URI(), err) + } + if text == "" { + if hover != nil { + t.Errorf("want nil, got %v\n", hover) + } + } else { + if hover == nil { + t.Fatalf("want hover result to not be nil") + } + if got := hover.Contents.Value; got != text { + t.Errorf("want %v, got %v\n", got, text) + } + if want, got := srcRng, hover.Range; want != got { + t.Errorf("want range %v, got %v instead", want, got) + } + } +} + func (r *runner) References(t *testing.T, src span.Span, itemList []span.Span) { ctx := r.ctx _, srcRng, err := spanToRange(r.data, src) diff --git a/internal/lsp/testdata/basiclit/basiclit.go b/internal/lsp/testdata/basiclit/basiclit.go index ab895dc01..9829003d3 100644 --- a/internal/lsp/testdata/basiclit/basiclit.go +++ b/internal/lsp/testdata/basiclit/basiclit.go @@ -10,4 +10,47 @@ func _() { _ = 1. //@complete(".") _ = 'a' //@complete("' ") + + _ = 'a' //@hover("'a'", "'a', U+0061, LATIN SMALL LETTER A") + _ = 0x61 //@hover("0x61", "'a', U+0061, LATIN SMALL LETTER A") + + _ = '\u2211' //@hover("'\\u2211'", "'āˆ‘', U+2211, N-ARY SUMMATION") + _ = 0x2211 //@hover("0x2211", "'āˆ‘', U+2211, N-ARY SUMMATION") + _ = "foo \u2211 bar" //@hover("\\u2211", "'āˆ‘', U+2211, N-ARY SUMMATION") + + _ = '\a' //@hover("'\\a'", "U+0007, control") + _ = "foo \a bar" //@hover("\\a", "U+0007, control") + + _ = '\U0001F30A' //@hover("'\\U0001F30A'", "'šŸŒŠ', U+1F30A, WATER WAVE") + _ = 0x0001F30A //@hover("0x0001F30A", "'šŸŒŠ', U+1F30A, WATER WAVE") + _ = "foo \U0001F30A bar" //@hover("\\U0001F30A", "'šŸŒŠ', U+1F30A, WATER WAVE") + + _ = '\x7E' //@hover("'\\x7E'", "'~', U+007E, TILDE") + _ = "foo \x7E bar" //@hover("\\x7E", "'~', U+007E, TILDE") + _ = "foo \a bar" //@hover("\\a", "U+0007, control") + + _ = '\173' //@hover("'\\173'", "'{', U+007B, LEFT CURLY BRACKET") + _ = "foo \173 bar" //@hover("\\173", "'{', U+007B, LEFT CURLY BRACKET") + _ = "foo \173 bar \u2211 baz" //@hover("\\173", "'{', U+007B, LEFT CURLY BRACKET") + _ = "foo \173 bar \u2211 baz" //@hover("\\u2211", "'āˆ‘', U+2211, N-ARY SUMMATION") + _ = "foo\173bar\u2211baz" //@hover("\\173", "'{', U+007B, LEFT CURLY BRACKET") + _ = "foo\173bar\u2211baz" //@hover("\\u2211", "'āˆ‘', U+2211, N-ARY SUMMATION") + + // search for runes in string only if there is an escaped sequence + _ = "hello" //@hover("\"hello\"", "") + + // incorrect escaped rune sequences + _ = '\0' //@hover("'\\0'", "") + _ = '\u22111' //@hover("'\\u22111'", "") + _ = '\U00110000' //@hover("'\\U00110000'", "") + _ = '\u12e45'//@hover("'\\u12e45'", "") + _ = '\xa' //@hover("'\\xa'", "") + _ = 'aa' //@hover("'aa'", "") + + // other basic lits + _ = 1 //@hover("1", "") + _ = 1.2 //@hover("1.2", "") + _ = 1.2i //@hover("1.2i", "") + _ = 0123 //@hover("0123", "") + _ = 0x1234567890 //@hover("0x1234567890", "") } diff --git a/internal/lsp/testdata/cgo/declarecgo.go.golden b/internal/lsp/testdata/cgo/declarecgo.go.golden index 773f3b7d3..b6d94d0c6 100644 --- a/internal/lsp/testdata/cgo/declarecgo.go.golden +++ b/internal/lsp/testdata/cgo/declarecgo.go.golden @@ -22,7 +22,7 @@ func Example() "description": "```go\nfunc Example()\n```\n\n[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/cgo?utm_source=gopls#Example)" } --- funccgoexample-hover -- +-- funccgoexample-hoverdef -- ```go func Example() ``` diff --git a/internal/lsp/testdata/cgoimport/usecgo.go.golden b/internal/lsp/testdata/cgoimport/usecgo.go.golden index 8f7518a15..f33f94f84 100644 --- a/internal/lsp/testdata/cgoimport/usecgo.go.golden +++ b/internal/lsp/testdata/cgoimport/usecgo.go.golden @@ -22,7 +22,7 @@ func cgo.Example() "description": "```go\nfunc cgo.Example()\n```\n\n[`cgo.Example` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/cgo?utm_source=gopls#Example)" } --- funccgoexample-hover -- +-- funccgoexample-hoverdef -- ```go func cgo.Example() ``` diff --git a/internal/lsp/testdata/godef/a/a.go b/internal/lsp/testdata/godef/a/a.go index 993fd86b4..5cc85527a 100644 --- a/internal/lsp/testdata/godef/a/a.go +++ b/internal/lsp/testdata/godef/a/a.go @@ -1,5 +1,5 @@ // Package a is a package for testing go to definition. -package a //@mark(aPackage, "a "),hover("a ", aPackage) +package a //@mark(aPackage, "a "),hoverdef("a ", aPackage) import ( "fmt" @@ -9,19 +9,19 @@ import ( var ( // x is a variable. - x string //@x,hover("x", x) + x string //@x,hoverdef("x", x) ) // Constant block. When I hover on h, I should see this comment. const ( // When I hover on g, I should see this comment. - g = 1 //@g,hover("g", g) + g = 1 //@g,hoverdef("g", g) - h = 2 //@h,hover("h", h) + h = 2 //@h,hoverdef("h", h) ) // z is a variable too. -var z string //@z,hover("z", z) +var z string //@z,hoverdef("z", z) type A string //@mark(AString, "A") @@ -33,14 +33,14 @@ func AStuff() { //@AStuff var err error //@err fmt.Printf("%v", err) //@godef("err", err) - var y string //@string,hover("string", string) - _ = make([]int, 0) //@make,hover("make", make) + var y string //@string,hoverdef("string", string) + _ = make([]int, 0) //@make,hoverdef("make", make) var mu sync.Mutex - mu.Lock() //@Lock,hover("Lock", Lock) + mu.Lock() //@Lock,hoverdef("Lock", Lock) - var typ *types.Named //@mark(typesImport, "types"),hover("types", typesImport) - typ.Obj().Name() //@Name,hover("Name", Name) + var typ *types.Named //@mark(typesImport, "types"),hoverdef("types", typesImport) + typ.Obj().Name() //@Name,hoverdef("Name", Name) } type A struct { @@ -76,7 +76,7 @@ type J interface { func _() { // 1st type declaration block type ( - a struct { //@mark(declBlockA, "a"),hover("a", declBlockA) + a struct { //@mark(declBlockA, "a"),hoverdef("a", declBlockA) x string } ) @@ -84,21 +84,21 @@ func _() { // 2nd type declaration block type ( // b has a comment - b struct{} //@mark(declBlockB, "b"),hover("b", declBlockB) + b struct{} //@mark(declBlockB, "b"),hoverdef("b", declBlockB) ) // 3rd type declaration block type ( // c is a struct - c struct { //@mark(declBlockC, "c"),hover("c", declBlockC) + c struct { //@mark(declBlockC, "c"),hoverdef("c", declBlockC) f string } - d string //@mark(declBlockD, "d"),hover("d", declBlockD) + d string //@mark(declBlockD, "d"),hoverdef("d", declBlockD) ) type ( - e struct { //@mark(declBlockE, "e"),hover("e", declBlockE) + e struct { //@mark(declBlockE, "e"),hoverdef("e", declBlockE) f float64 } // e has a comment ) diff --git a/internal/lsp/testdata/godef/a/a.go.golden b/internal/lsp/testdata/godef/a/a.go.golden index c26829350..182928eeb 100644 --- a/internal/lsp/testdata/godef/a/a.go.golden +++ b/internal/lsp/testdata/godef/a/a.go.golden @@ -1,4 +1,4 @@ --- Lock-hover -- +-- Lock-hoverdef -- ```go func (*sync.Mutex).Lock() ``` @@ -6,7 +6,7 @@ func (*sync.Mutex).Lock() [`(sync.Mutex).Lock` on pkg.go.dev](https://pkg.go.dev/sync?utm_source=gopls#Mutex.Lock) Lock locks m\. --- Name-hover -- +-- Name-hoverdef -- ```go func (*types.object).Name() string ``` @@ -38,7 +38,7 @@ func Random() int "description": "```go\nfunc Random() int\n```\n\n[`a.Random` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Random)" } --- Random-hover -- +-- Random-hoverdef -- ```go func Random() int ``` @@ -68,15 +68,15 @@ func Random2(y int) int "description": "```go\nfunc Random2(y int) int\n```\n\n[`a.Random2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Random2)" } --- Random2-hover -- +-- Random2-hoverdef -- ```go func Random2(y int) int ``` [`a.Random2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Random2) --- aPackage-hover -- +-- aPackage-hoverdef -- Package a is a package for testing go to definition\. --- declBlockA-hover -- +-- declBlockA-hoverdef -- ```go type a struct { x string @@ -84,13 +84,13 @@ type a struct { ``` 1st type declaration block --- declBlockB-hover -- +-- declBlockB-hoverdef -- ```go type b struct{} ``` b has a comment --- declBlockC-hover -- +-- declBlockC-hoverdef -- ```go type c struct { f string @@ -98,13 +98,13 @@ type c struct { ``` c is a struct --- declBlockD-hover -- +-- declBlockD-hoverdef -- ```go type d string ``` 3rd type declaration block --- declBlockE-hover -- +-- declBlockE-hoverdef -- ```go type e struct { f float64 @@ -125,36 +125,36 @@ var err error "start": { "line": 33, "column": 6, - "offset": 597 + "offset": 612 }, "end": { "line": 33, "column": 9, - "offset": 600 + "offset": 615 } }, "description": "```go\nvar err error\n```\n\n\\@err" } --- err-hover -- +-- err-hoverdef -- ```go var err error ``` \@err --- g-hover -- +-- g-hoverdef -- ```go const g untyped int = 1 ``` When I hover on g, I should see this comment\. --- h-hover -- +-- h-hoverdef -- ```go const h untyped int = 2 ``` Constant block\. --- make-hover -- +-- make-hoverdef -- ```go func(t Type, size ...IntegerType) Type ``` @@ -162,23 +162,23 @@ func(t Type, size ...IntegerType) Type [`make` on pkg.go.dev](https://pkg.go.dev/builtin?utm_source=gopls#make) The make built\-in function allocates and initializes an object of type slice, map, or chan \(only\)\. --- string-hover -- +-- string-hoverdef -- ```go string ``` --- typesImport-hover -- +-- typesImport-hoverdef -- ```go package types ("go/types") ``` [`types` on pkg.go.dev](https://pkg.go.dev/go/types?utm_source=gopls) --- x-hover -- +-- x-hoverdef -- ```go var x string ``` x is a variable\. --- z-hover -- +-- z-hoverdef -- ```go var z string ``` diff --git a/internal/lsp/testdata/godef/a/a_test.go.golden b/internal/lsp/testdata/godef/a/a_test.go.golden index ac50b90b9..e5cb3d799 100644 --- a/internal/lsp/testdata/godef/a/a_test.go.golden +++ b/internal/lsp/testdata/godef/a/a_test.go.golden @@ -20,7 +20,7 @@ func TestA(t *testing.T) "description": "```go\nfunc TestA(t *testing.T)\n```" } --- TestA-hover -- +-- TestA-hoverdef -- ```go func TestA(t *testing.T) ``` diff --git a/internal/lsp/testdata/godef/a/a_x_test.go.golden b/internal/lsp/testdata/godef/a/a_x_test.go.golden index dd1d74016..2e3064794 100644 --- a/internal/lsp/testdata/godef/a/a_x_test.go.golden +++ b/internal/lsp/testdata/godef/a/a_x_test.go.golden @@ -20,7 +20,7 @@ func TestA2(t *testing.T) "description": "```go\nfunc TestA2(t *testing.T)\n```" } --- TestA2-hover -- +-- TestA2-hoverdef -- ```go func TestA2(t *testing.T) ``` diff --git a/internal/lsp/testdata/godef/a/d.go b/internal/lsp/testdata/godef/a/d.go index d20bdad98..2da8d058e 100644 --- a/internal/lsp/testdata/godef/a/d.go +++ b/internal/lsp/testdata/godef/a/d.go @@ -1,4 +1,4 @@ -package a //@mark(a, "a "),hover("a ", a) +package a //@mark(a, "a "),hoverdef("a ", a) import "fmt" diff --git a/internal/lsp/testdata/godef/a/d.go.golden b/internal/lsp/testdata/godef/a/d.go.golden index d80c14a9d..23c7da1ec 100644 --- a/internal/lsp/testdata/godef/a/d.go.golden +++ b/internal/lsp/testdata/godef/a/d.go.golden @@ -13,18 +13,18 @@ field Member string "start": { "line": 6, "column": 2, - "offset": 87 + "offset": 90 }, "end": { "line": 6, "column": 8, - "offset": 93 + "offset": 96 } }, "description": "```go\nfield Member string\n```\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Thing.Member)\n\n\\@Member" } --- Member-hover -- +-- Member-hoverdef -- ```go field Member string ``` @@ -45,18 +45,18 @@ func (Thing).Method(i int) string "start": { "line": 15, "column": 16, - "offset": 216 + "offset": 219 }, "end": { "line": 15, "column": 22, - "offset": 222 + "offset": 225 } }, "description": "```go\nfunc (Thing).Method(i int) string\n```\n\n[`(a.Thing).Method` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Thing.Method)" } --- Method-hover -- +-- Method-hoverdef -- ```go func (Thing).Method(i int) string ``` @@ -77,18 +77,18 @@ var Other Thing "start": { "line": 9, "column": 5, - "offset": 118 + "offset": 121 }, "end": { "line": 9, "column": 10, - "offset": 123 + "offset": 126 } }, "description": "```go\nvar Other Thing\n```\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Other)\n\n\\@Other" } --- Other-hover -- +-- Other-hoverdef -- ```go var Other Thing ``` @@ -111,18 +111,18 @@ type Thing struct { "start": { "line": 5, "column": 6, - "offset": 62 + "offset": 65 }, "end": { "line": 5, "column": 11, - "offset": 67 + "offset": 70 } }, "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?utm_source=gopls#Thing)" } --- Thing-hover -- +-- Thing-hoverdef -- ```go type Thing struct { Member string //@Member @@ -143,22 +143,22 @@ func Things(val []string) []Thing "start": { "line": 11, "column": 6, - "offset": 145 + "offset": 148 }, "end": { "line": 11, "column": 12, - "offset": 151 + "offset": 154 } }, "description": "```go\nfunc Things(val []string) []Thing\n```\n\n[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Things)" } --- Things-hover -- +-- Things-hoverdef -- ```go func Things(val []string) []Thing ``` [`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Things) --- a-hover -- +-- a-hoverdef -- Package a is a package for testing go to definition\. diff --git a/internal/lsp/testdata/godef/a/f.go b/internal/lsp/testdata/godef/a/f.go index 2d3eefcfb..589c45fc1 100644 --- a/internal/lsp/testdata/godef/a/f.go +++ b/internal/lsp/testdata/godef/a/f.go @@ -7,9 +7,9 @@ func TypeStuff() { //@Stuff switch y := interface{}(x).(type) { //@mark(switchY, "y"),godef("y", switchY) case int: //@mark(intY, "int") - fmt.Printf("%v", y) //@hover("y", intY) + fmt.Printf("%v", y) //@hoverdef("y", intY) case string: //@mark(stringY, "string") - fmt.Printf("%v", y) //@hover("y", stringY) + fmt.Printf("%v", y) //@hoverdef("y", stringY) } } diff --git a/internal/lsp/testdata/godef/a/f.go.golden b/internal/lsp/testdata/godef/a/f.go.golden index 6c84b4d5f..a084356c0 100644 --- a/internal/lsp/testdata/godef/a/f.go.golden +++ b/internal/lsp/testdata/godef/a/f.go.golden @@ -1,8 +1,8 @@ --- intY-hover -- +-- intY-hoverdef -- ```go var y int ``` --- stringY-hover -- +-- stringY-hoverdef -- ```go var y string ``` @@ -28,7 +28,7 @@ var y interface{} "description": "```go\nvar y interface{}\n```" } --- switchY-hover -- +-- switchY-hoverdef -- ```go var y interface{} ``` diff --git a/internal/lsp/testdata/godef/a/g.go b/internal/lsp/testdata/godef/a/g.go index 4f31857e3..dfef2fb80 100644 --- a/internal/lsp/testdata/godef/a/g.go +++ b/internal/lsp/testdata/godef/a/g.go @@ -3,4 +3,4 @@ package a import "time" // dur is a constant of type time.Duration. -const dur = 15*time.Minute + 10*time.Second + 350*time.Millisecond //@dur,hover("dur", dur) +const dur = 15*time.Minute + 10*time.Second + 350*time.Millisecond //@dur,hoverdef("dur", dur) diff --git a/internal/lsp/testdata/godef/a/g.go.golden b/internal/lsp/testdata/godef/a/g.go.golden index d46ff048b..b7ed73928 100644 --- a/internal/lsp/testdata/godef/a/g.go.golden +++ b/internal/lsp/testdata/godef/a/g.go.golden @@ -1,4 +1,4 @@ --- dur-hover -- +-- dur-hoverdef -- ```go const dur time.Duration = 910350000000 // 15m10.35s ``` diff --git a/internal/lsp/testdata/godef/a/h.go b/internal/lsp/testdata/godef/a/h.go index efe7d4ec1..5a5dcc678 100644 --- a/internal/lsp/testdata/godef/a/h.go +++ b/internal/lsp/testdata/godef/a/h.go @@ -25,9 +25,9 @@ func _() { } var t s - _ = t.nested.number //@hover("number", nestedNumber) - _ = t.nested2[0].str //@hover("str", nestedString) - _ = t.x.x.x.x.x.m //@hover("m", nestedMap) + _ = t.nested.number //@hoverdef("number", nestedNumber) + _ = t.nested2[0].str //@hoverdef("str", nestedString) + _ = t.x.x.x.x.x.m //@hoverdef("m", nestedMap) } func _() { @@ -40,9 +40,9 @@ func _() { c int //@mark(structC, "c") } } - _ = s.a //@hover("a", structA) - _ = s.b //@hover("b", structB) - _ = s.b.c //@hover("c", structC) + _ = s.a //@hoverdef("a", structA) + _ = s.b //@hoverdef("b", structB) + _ = s.b.c //@hoverdef("c", structC) var arr []struct { // d field @@ -53,9 +53,9 @@ func _() { f int //@mark(arrF, "f") } } - _ = arr[0].d //@hover("d", arrD) - _ = arr[0].e //@hover("e", arrE) - _ = arr[0].e.f //@hover("f", arrF) + _ = arr[0].d //@hoverdef("d", arrD) + _ = arr[0].e //@hoverdef("e", arrE) + _ = arr[0].e.f //@hoverdef("f", arrF) var complex []struct { c <-chan map[string][]struct { @@ -68,16 +68,16 @@ func _() { } } } - _ = (<-complex[0].c)["0"][0].h //@hover("h", complexH) - _ = (<-complex[0].c)["0"][0].i //@hover("i", complexI) - _ = (<-complex[0].c)["0"][0].i.j //@hover("j", complexJ) + _ = (<-complex[0].c)["0"][0].h //@hoverdef("h", complexH) + _ = (<-complex[0].c)["0"][0].i //@hoverdef("i", complexI) + _ = (<-complex[0].c)["0"][0].i.j //@hoverdef("j", complexJ) var mapWithStructKey map[struct { // X key field x []string //@mark(mapStructKeyX, "x") }]int for k := range mapWithStructKey { - _ = k.x //@hover("x", mapStructKeyX) + _ = k.x //@hoverdef("x", mapStructKeyX) } var mapWithStructKeyAndValue map[struct { @@ -90,15 +90,15 @@ func _() { for k, v := range mapWithStructKeyAndValue { // TODO: we don't show docs for y field because both map key and value // are structs. And in this case, we parse only map value - _ = k.y //@hover("y", mapStructKeyY) - _ = v.x //@hover("x", mapStructValueX) + _ = k.y //@hoverdef("y", mapStructKeyY) + _ = v.x //@hoverdef("x", mapStructValueX) } var i []map[string]interface { // open method comment open() error //@mark(openMethod, "open") } - i[0]["1"].open() //@hover("open", openMethod) + i[0]["1"].open() //@hoverdef("open", openMethod) } func _() { @@ -106,7 +106,7 @@ func _() { // test description desc string //@mark(testDescription, "desc") }{} - _ = test.desc //@hover("desc", testDescription) + _ = test.desc //@hoverdef("desc", testDescription) for _, tt := range []struct { // test input @@ -123,11 +123,11 @@ func _() { } } }{} { - _ = tt.in //@hover("in", testInput) - _ = tt.in["0"][0].key //@hover("key", testInputKey) - _ = tt.in["0"][0].value //@hover("value", testInputValue) + _ = tt.in //@hoverdef("in", testInput) + _ = tt.in["0"][0].key //@hoverdef("key", testInputKey) + _ = tt.in["0"][0].value //@hoverdef("value", testInputValue) - _ = (<-tt.result.v).value //@hover("value", testResultValue) + _ = (<-tt.result.v).value //@hoverdef("value", testResultValue) } } @@ -142,6 +142,6 @@ func _() { } r := getPoints() - r[0].x //@hover("x", returnX) - r[0].y //@hover("y", returnY) + r[0].x //@hoverdef("x", returnX) + r[0].y //@hoverdef("y", returnY) } diff --git a/internal/lsp/testdata/godef/a/h.go.golden b/internal/lsp/testdata/godef/a/h.go.golden index 3525d4cfd..4b27211e9 100644 --- a/internal/lsp/testdata/godef/a/h.go.golden +++ b/internal/lsp/testdata/godef/a/h.go.golden @@ -1,134 +1,134 @@ --- arrD-hover -- +-- arrD-hoverdef -- ```go field d int ``` d field --- arrE-hover -- +-- arrE-hoverdef -- ```go field e struct{f int} ``` e nested struct --- arrF-hover -- +-- arrF-hoverdef -- ```go field f int ``` f field of nested struct --- complexH-hover -- +-- complexH-hoverdef -- ```go field h int ``` h field --- complexI-hover -- +-- complexI-hoverdef -- ```go field i struct{j int} ``` i nested struct --- complexJ-hover -- +-- complexJ-hoverdef -- ```go field j int ``` j field of nested struct --- mapStructKeyX-hover -- +-- mapStructKeyX-hoverdef -- ```go field x []string ``` X key field --- mapStructKeyY-hover -- +-- mapStructKeyY-hoverdef -- ```go field y string ``` --- mapStructValueX-hover -- +-- mapStructValueX-hoverdef -- ```go field x string ``` X value field --- nestedMap-hover -- +-- nestedMap-hoverdef -- ```go field m map[string]float64 ``` nested map --- nestedNumber-hover -- +-- nestedNumber-hoverdef -- ```go field number int64 ``` nested number --- nestedString-hover -- +-- nestedString-hoverdef -- ```go field str string ``` nested string --- openMethod-hover -- +-- openMethod-hoverdef -- ```go func (interface).open() error ``` open method comment --- returnX-hover -- +-- returnX-hoverdef -- ```go field x int ``` X coord --- returnY-hover -- +-- returnY-hoverdef -- ```go field y int ``` Y coord --- structA-hover -- +-- structA-hoverdef -- ```go field a int ``` a field --- structB-hover -- +-- structB-hoverdef -- ```go field b struct{c int} ``` b nested struct --- structC-hover -- +-- structC-hoverdef -- ```go field c int ``` c field of nested struct --- testDescription-hover -- +-- testDescription-hoverdef -- ```go field desc string ``` test description --- testInput-hover -- +-- testInput-hoverdef -- ```go field in map[string][]struct{key string; value interface{}} ``` test input --- testInputKey-hover -- +-- testInputKey-hoverdef -- ```go field key string ``` test key --- testInputValue-hover -- +-- testInputValue-hoverdef -- ```go field value interface{} ``` test value --- testResultValue-hover -- +-- testResultValue-hoverdef -- ```go field value int ``` diff --git a/internal/lsp/testdata/godef/a/random.go.golden b/internal/lsp/testdata/godef/a/random.go.golden index 0f99a52f3..381a11ace 100644 --- a/internal/lsp/testdata/godef/a/random.go.golden +++ b/internal/lsp/testdata/godef/a/random.go.golden @@ -22,7 +22,7 @@ func (*Pos).Sum() int "description": "```go\nfunc (*Pos).Sum() int\n```\n\n[`(a.Pos).Sum` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Pos.Sum)" } --- PosSum-hover -- +-- PosSum-hoverdef -- ```go func (*Pos).Sum() int ``` @@ -52,7 +52,7 @@ field x int "description": "```go\nfield x int\n```\n\n\\@mark\\(PosX, \\\"x\\\"\\),mark\\(PosY, \\\"y\\\"\\)" } --- PosX-hover -- +-- PosX-hoverdef -- ```go field x int ``` @@ -80,7 +80,7 @@ var y int "description": "```go\nvar y int\n```" } --- RandomParamY-hover -- +-- RandomParamY-hoverdef -- ```go var y int ``` @@ -106,7 +106,7 @@ field field string "description": "```go\nfield field string\n```" } --- TypField-hover -- +-- TypField-hoverdef -- ```go field field string ``` diff --git a/internal/lsp/testdata/godef/b/b.go b/internal/lsp/testdata/godef/b/b.go index 23d908f1f..f9c1d6402 100644 --- a/internal/lsp/testdata/godef/b/b.go +++ b/internal/lsp/testdata/godef/b/b.go @@ -13,13 +13,13 @@ type Embed struct { func _() { e := Embed{} - e.Hi() //@hover("Hi", AHi) - e.B() //@hover("B", AB) - e.Field //@hover("Field", AField) - e.Field2 //@hover("Field2", AField2) - e.Hello() //@hover("Hello", AHello) - e.Hey() //@hover("Hey", AHey) - e.Goodbye() //@hover("Goodbye", AGoodbye) + e.Hi() //@hoverdef("Hi", AHi) + e.B() //@hoverdef("B", AB) + e.Field //@hoverdef("Field", AField) + e.Field2 //@hoverdef("Field2", AField2) + e.Hello() //@hoverdef("Hello", AHello) + e.Hey() //@hoverdef("Hey", AHey) + e.Goodbye() //@hoverdef("Goodbye", AGoodbye) } type aAlias = a.A //@mark(aAlias, "aAlias") diff --git a/internal/lsp/testdata/godef/b/b.go.golden b/internal/lsp/testdata/godef/b/b.go.golden index 553718075..7f05a70ce 100644 --- a/internal/lsp/testdata/godef/b/b.go.golden +++ b/internal/lsp/testdata/godef/b/b.go.golden @@ -1,4 +1,4 @@ --- AB-hover -- +-- AB-hoverdef -- ```go func (a.I).B() ``` @@ -6,7 +6,7 @@ func (a.I).B() [`(a.I).B` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#I.B) \@mark\(AB, \"B\"\) --- AField-hover -- +-- AField-hoverdef -- ```go field Field int ``` @@ -14,7 +14,7 @@ field Field int [`(a.S).Field` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#S.Field) \@mark\(AField, \"Field\"\) --- AField2-hover -- +-- AField2-hoverdef -- ```go field Field2 int ``` @@ -22,7 +22,7 @@ field Field2 int [`(a.R).Field2` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#R.Field2) \@mark\(AField2, \"Field2\"\) --- AGoodbye-hover -- +-- AGoodbye-hoverdef -- ```go func (a.H).Goodbye() ``` @@ -30,7 +30,7 @@ func (a.H).Goodbye() [`(a.H).Goodbye` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#H.Goodbye) \@mark\(AGoodbye, \"Goodbye\"\) --- AHello-hover -- +-- AHello-hoverdef -- ```go func (a.J).Hello() ``` @@ -38,13 +38,13 @@ func (a.J).Hello() [`(a.J).Hello` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#J.Hello) \@mark\(AHello, \"Hello\"\) --- AHey-hover -- +-- AHey-hoverdef -- ```go func (a.R).Hey() ``` [`(a.R).Hey` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#R.Hey) --- AHi-hover -- +-- AHi-hoverdef -- ```go func (a.A).Hi() ``` @@ -74,7 +74,7 @@ package a ("golang.org/x/tools/internal/lsp/godef/a") "description": "```go\npackage a (\"golang.org/x/tools/internal/lsp/godef/a\")\n```\n\n[`a` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls)" } --- AImport-hover -- +-- AImport-hoverdef -- ```go package a ("golang.org/x/tools/internal/lsp/godef/a") ``` @@ -95,18 +95,18 @@ type A string "start": { "line": 26, "column": 6, - "offset": 452 + "offset": 467 }, "end": { "line": 26, "column": 7, - "offset": 453 + "offset": 468 } }, "description": "```go\ntype A string\n```\n\n[`a.A` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#A)\n\n\\@mark\\(AString, \\\"A\\\"\\)" } --- AString-hover -- +-- AString-hoverdef -- ```go type A string ``` @@ -127,18 +127,18 @@ func a.AStuff() "start": { "line": 28, "column": 6, - "offset": 489 + "offset": 504 }, "end": { "line": 28, "column": 12, - "offset": 495 + "offset": 510 } }, "description": "```go\nfunc a.AStuff()\n```\n\n[`a.AStuff` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#AStuff)" } --- AStuff-hover -- +-- AStuff-hoverdef -- ```go func a.AStuff() ``` @@ -162,18 +162,18 @@ type S1 struct { "start": { "line": 27, "column": 6, - "offset": 566 + "offset": 587 }, "end": { "line": 27, "column": 8, - "offset": 568 + "offset": 589 } }, "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 -- +-- S1-hoverdef -- ```go type S1 struct { F1 int //@mark(S1F1, "F1") @@ -199,18 +199,18 @@ field F1 int "start": { "line": 28, "column": 2, - "offset": 585 + "offset": 606 }, "end": { "line": 28, "column": 4, - "offset": 587 + "offset": 608 } }, "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\\\"\\)" } --- S1F1-hover -- +-- S1F1-hoverdef -- ```go field F1 int ``` @@ -233,18 +233,18 @@ field S2 S2 "start": { "line": 29, "column": 2, - "offset": 617 + "offset": 638 }, "end": { "line": 29, "column": 4, - "offset": 619 + "offset": 640 } }, "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\\\"\\)" } --- S1S2-hover -- +-- S1S2-hoverdef -- ```go field S2 S2 ``` @@ -269,18 +269,18 @@ type S2 struct { "start": { "line": 34, "column": 6, - "offset": 741 + "offset": 762 }, "end": { "line": 34, "column": 8, - "offset": 743 + "offset": 764 } }, "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)" } --- S2-hover -- +-- S2-hoverdef -- ```go type S2 struct { F1 string //@mark(S2F1, "F1") @@ -305,18 +305,18 @@ field F1 string "start": { "line": 35, "column": 2, - "offset": 760 + "offset": 781 }, "end": { "line": 35, "column": 4, - "offset": 762 + "offset": 783 } }, "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\\\"\\)" } --- S2F1-hover -- +-- S2F1-hoverdef -- ```go field F1 string ``` @@ -339,18 +339,18 @@ field F2 int "start": { "line": 36, "column": 2, - "offset": 793 + "offset": 814 }, "end": { "line": 36, "column": 4, - "offset": 795 + "offset": 816 } }, "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\\\"\\)" } --- S2F2-hover -- +-- S2F2-hoverdef -- ```go field F2 int ``` @@ -371,18 +371,18 @@ type aAlias = a.A "start": { "line": 25, "column": 6, - "offset": 521 + "offset": 542 }, "end": { "line": 25, "column": 12, - "offset": 527 + "offset": 548 } }, "description": "```go\ntype aAlias = a.A\n```\n\n\\@mark\\(aAlias, \\\"aAlias\\\"\\)" } --- aAlias-hover -- +-- aAlias-hoverdef -- ```go type aAlias = a.A ``` @@ -403,18 +403,18 @@ const X untyped int = 0 "start": { "line": 57, "column": 7, - "offset": 1228 + "offset": 1249 }, "end": { "line": 57, "column": 8, - "offset": 1229 + "offset": 1250 } }, "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\\)" } --- bX-hover -- +-- bX-hoverdef -- ```go const X untyped int = 0 ``` @@ -446,7 +446,7 @@ package myFoo ("golang.org/x/tools/internal/lsp/foo") "description": "```go\npackage myFoo (\"golang.org/x/tools/internal/lsp/foo\")\n```\n\n[`myFoo` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/foo?utm_source=gopls)" } --- myFoo-hover -- +-- myFoo-hoverdef -- ```go package myFoo ("golang.org/x/tools/internal/lsp/foo") ``` diff --git a/internal/lsp/testdata/godef/b/c.go.golden b/internal/lsp/testdata/godef/b/c.go.golden index 9554c0d43..3ae3e2d0a 100644 --- a/internal/lsp/testdata/godef/b/c.go.golden +++ b/internal/lsp/testdata/godef/b/c.go.golden @@ -16,18 +16,18 @@ type S1 struct { "start": { "line": 27, "column": 6, - "offset": 566 + "offset": 587 }, "end": { "line": 27, "column": 8, - "offset": 568 + "offset": 589 } }, "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 -- +-- S1-hoverdef -- ```go type S1 struct { F1 int //@mark(S1F1, "F1") @@ -53,18 +53,18 @@ field F1 int "start": { "line": 28, "column": 2, - "offset": 585 + "offset": 606 }, "end": { "line": 28, "column": 4, - "offset": 587 + "offset": 608 } }, "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\\\"\\)" } --- S1F1-hover -- +-- S1F1-hoverdef -- ```go field F1 int ``` diff --git a/internal/lsp/testdata/godef/b/e.go b/internal/lsp/testdata/godef/b/e.go index 92037ed33..7b96cd7e8 100644 --- a/internal/lsp/testdata/godef/b/e.go +++ b/internal/lsp/testdata/godef/b/e.go @@ -22,10 +22,10 @@ godef(bFunc, Things) func _() { var x interface{} //@mark(eInterface, "interface{}") - switch x := x.(type) { //@hover("x", eInterface) + switch x := x.(type) { //@hoverdef("x", eInterface) case string: //@mark(eString, "string") - fmt.Println(x) //@hover("x", eString) + fmt.Println(x) //@hoverdef("x", eString) case int: //@mark(eInt, "int") - fmt.Println(x) //@hover("x", eInt) + fmt.Println(x) //@hoverdef("x", eInt) } } diff --git a/internal/lsp/testdata/godef/b/e.go.golden b/internal/lsp/testdata/godef/b/e.go.golden index 13c2e0eb5..079ed7923 100644 --- a/internal/lsp/testdata/godef/b/e.go.golden +++ b/internal/lsp/testdata/godef/b/e.go.golden @@ -13,18 +13,18 @@ field Member string "start": { "line": 6, "column": 2, - "offset": 87 + "offset": 90 }, "end": { "line": 6, "column": 8, - "offset": 93 + "offset": 96 } }, "description": "```go\nfield Member string\n```\n\n[`(a.Thing).Member` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Thing.Member)\n\n\\@Member" } --- Member-hover -- +-- Member-hoverdef -- ```go field Member string ``` @@ -47,18 +47,18 @@ var a.Other a.Thing "start": { "line": 9, "column": 5, - "offset": 118 + "offset": 121 }, "end": { "line": 9, "column": 10, - "offset": 123 + "offset": 126 } }, "description": "```go\nvar a.Other a.Thing\n```\n\n[`a.Other` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Other)\n\n\\@Other" } --- Other-hover -- +-- Other-hoverdef -- ```go var a.Other a.Thing ``` @@ -81,18 +81,18 @@ type Thing struct { "start": { "line": 5, "column": 6, - "offset": 62 + "offset": 65 }, "end": { "line": 5, "column": 11, - "offset": 67 + "offset": 70 } }, "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?utm_source=gopls#Thing)" } --- Thing-hover -- +-- Thing-hoverdef -- ```go type Thing struct { Member string //@Member @@ -113,32 +113,32 @@ func a.Things(val []string) []a.Thing "start": { "line": 11, "column": 6, - "offset": 145 + "offset": 148 }, "end": { "line": 11, "column": 12, - "offset": 151 + "offset": 154 } }, "description": "```go\nfunc a.Things(val []string) []a.Thing\n```\n\n[`a.Things` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#Things)" } --- Things-hover -- +-- Things-hoverdef -- ```go 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?utm_source=gopls#Things) --- eInt-hover -- +-- eInt-hoverdef -- ```go var x int ``` --- eInterface-hover -- +-- eInterface-hoverdef -- ```go var x interface{} ``` --- eString-hover -- +-- eString-hoverdef -- ```go var x string ``` diff --git a/internal/lsp/testdata/godef/b/h.go b/internal/lsp/testdata/godef/b/h.go index c2776a03a..c8cbe850f 100644 --- a/internal/lsp/testdata/godef/b/h.go +++ b/internal/lsp/testdata/godef/b/h.go @@ -4,7 +4,7 @@ import . "golang.org/x/tools/internal/lsp/godef/a" func _() { // variable of type a.A - var _ A //@mark(AVariable, "_"),hover("_", AVariable) + var _ A //@mark(AVariable, "_"),hoverdef("_", AVariable) - AStuff() //@hover("AStuff", AStuff) + AStuff() //@hoverdef("AStuff", AStuff) } diff --git a/internal/lsp/testdata/godef/b/h.go.golden b/internal/lsp/testdata/godef/b/h.go.golden index b854dd4ab..f32f0264f 100644 --- a/internal/lsp/testdata/godef/b/h.go.golden +++ b/internal/lsp/testdata/godef/b/h.go.golden @@ -1,10 +1,10 @@ --- AStuff-hover -- +-- AStuff-hoverdef -- ```go func AStuff() ``` [`a.AStuff` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/a?utm_source=gopls#AStuff) --- AVariable-hover -- +-- AVariable-hoverdef -- ```go var _ A ``` diff --git a/internal/lsp/testdata/godef/broken/unclosedIf.go.golden b/internal/lsp/testdata/godef/broken/unclosedIf.go.golden index eac033923..5c3329d8b 100644 --- a/internal/lsp/testdata/godef/broken/unclosedIf.go.golden +++ b/internal/lsp/testdata/godef/broken/unclosedIf.go.golden @@ -22,7 +22,7 @@ var myUnclosedIf string "description": "```go\nvar myUnclosedIf string\n```\n\n\\@myUnclosedIf" } --- myUnclosedIf-hover -- +-- myUnclosedIf-hoverdef -- ```go var myUnclosedIf string ``` diff --git a/internal/lsp/testdata/godef/infer_generics/inferred.go.golden b/internal/lsp/testdata/godef/infer_generics/inferred.go.golden index 2dd97d9b6..081ea53dc 100644 --- a/internal/lsp/testdata/godef/infer_generics/inferred.go.golden +++ b/internal/lsp/testdata/godef/infer_generics/inferred.go.golden @@ -1,20 +1,20 @@ --- argInfer-hover -- +-- argInfer-hoverdef -- ```go func app(s []int, e int) []int // func[Sā‚ interface{~[]Eā‚‚}, Eā‚‚ interface{}](s Sā‚, e Eā‚‚) Sā‚ ``` --- constrInf-hover -- +-- constrInf-hoverdef -- ```go func app(s []int, e int) []int // func[Sā‚ interface{~[]Eā‚‚}, Eā‚‚ interface{}](s Sā‚, e Eā‚‚) Sā‚ ``` --- constrInfer-hover -- +-- constrInfer-hoverdef -- ```go func app(s []int, e int) []int // func[Sā‚ interface{~[]Eā‚‚}, Eā‚‚ interface{}](s Sā‚, e Eā‚‚) Sā‚ ``` --- instance-hover -- +-- instance-hoverdef -- ```go func app(s []int, e int) []int // func[Sā‚ interface{~[]Eā‚‚}, Eā‚‚ interface{}](s Sā‚, e Eā‚‚) Sā‚ ``` --- partialInfer-hover -- +-- partialInfer-hoverdef -- ```go func app(s []int, e int) []int // func[Sā‚ interface{~[]Eā‚‚}, Eā‚‚ interface{}](s Sā‚, e Eā‚‚) Sā‚ ``` diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index d5db454b7..5d6af9ed1 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -84,6 +84,7 @@ type WorkspaceSymbols map[WorkspaceSymbolsTestType]map[span.URI][]string type Signatures map[span.Span]*protocol.SignatureHelp type Links map[span.URI][]Link type AddImport map[span.URI]string +type Hovers map[span.Span]string type Data struct { Config packages.Config @@ -119,6 +120,7 @@ type Data struct { Signatures Signatures Links Links AddImport AddImport + Hovers Hovers t testing.TB fragments map[string]string @@ -161,6 +163,7 @@ type Tests interface { SignatureHelp(*testing.T, span.Span, *protocol.SignatureHelp) Link(*testing.T, span.URI, []Link) AddImport(*testing.T, span.URI, string) + Hover(*testing.T, span.Span, string) } type Definition struct { @@ -309,6 +312,7 @@ func load(t testing.TB, mode string, dir string) *Data { Signatures: make(Signatures), Links: make(Links), AddImport: make(AddImport), + Hovers: make(Hovers), t: t, dir: dir, @@ -459,7 +463,8 @@ func load(t testing.TB, mode string, dir string) *Data { "godef": datum.collectDefinitions, "implementations": datum.collectImplementations, "typdef": datum.collectTypeDefinitions, - "hover": datum.collectHoverDefinitions, + "hoverdef": datum.collectHoverDefinitions, + "hover": datum.collectHovers, "highlight": datum.collectHighlights, "refs": datum.collectReferences, "rename": datum.collectRenames, @@ -485,7 +490,7 @@ func load(t testing.TB, mode string, dir string) *Data { // Collect names for the entries that require golden files. if err := datum.Exported.Expect(map[string]interface{}{ "godef": datum.collectDefinitionNames, - "hover": datum.collectDefinitionNames, + "hoverdef": datum.collectDefinitionNames, "workspacesymbol": datum.collectWorkspaceSymbols(WorkspaceSymbolsDefault), "workspacesymbolfuzzy": datum.collectWorkspaceSymbols(WorkspaceSymbolsFuzzy), "workspacesymbolcasesensitive": datum.collectWorkspaceSymbols(WorkspaceSymbolsCaseSensitive), @@ -730,6 +735,16 @@ func Run(t *testing.T, tests Tests, data *Data) { } }) + t.Run("Hover", func(t *testing.T) { + t.Helper() + for pos, info := range data.Hovers { + t.Run(SpanName(pos), func(t *testing.T) { + t.Helper() + tests.Hover(t, pos, info) + }) + } + }) + t.Run("References", func(t *testing.T) { t.Helper() for src, itemList := range data.References { @@ -1222,6 +1237,10 @@ func (data *Data) collectHoverDefinitions(src, target span.Span) { } } +func (data *Data) collectHovers(src span.Span, expected string) { + data.Hovers[src] = expected +} + func (data *Data) collectTypeDefinitions(src, target span.Span) { data.Definitions[src] = Definition{ Src: src,