Skip to content

Commit adcfb65

Browse files
committed
internal/lsp/source: use the object as the hover source for type params
Use the type name object as the signature source for type parametes, as it it efficiently formatted as "type parameter <name> <constraint>". Fixes golang/go#51116 Change-Id: I3042ff248402dae833e3197c6ac320c2bd103c07 Reviewed-on: https://go-review.googlesource.com/c/tools/+/385018 Trust: Robert Findley <[email protected]> Run-TryBot: Robert Findley <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 411d040 commit adcfb65

File tree

5 files changed

+53
-31
lines changed

5 files changed

+53
-31
lines changed

internal/lsp/source/hover.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,13 @@ func objectString(obj types.Object, qf types.Qualifier, inferred *types.Signatur
477477
func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Object, pkgNode ast.Node, fullDecl ast.Decl) (*HoverContext, error) {
478478
var info *HoverContext
479479

480+
// Type parameters get their signature from their declaration object.
481+
if _, isTypeName := obj.(*types.TypeName); isTypeName {
482+
if _, isTypeParam := obj.Type().(*typeparams.TypeParam); isTypeParam {
483+
return &HoverContext{signatureSource: obj}, nil
484+
}
485+
}
486+
480487
// This is problematic for a number of reasons. We really need to have a more
481488
// general mechanism to validate the coherency of AST with type information,
482489
// but absent that we must do our best to ensure that we don't use fullNode
@@ -555,15 +562,15 @@ func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Ob
555562
}
556563
}
557564

558-
info, err = formatGenDecl(node, spec, fullPos, obj)
565+
info, err = hoverGenDecl(node, spec, fullPos, obj)
559566
if err != nil {
560567
return nil, err
561568
}
562569
}
563570
case *ast.TypeSpec:
564571
if obj.Parent() == types.Universe {
565572
if genDecl, ok := fullDecl.(*ast.GenDecl); ok {
566-
info = formatTypeSpec(node, genDecl)
573+
info = hoverTypeSpec(node, genDecl)
567574
}
568575
}
569576
case *ast.FuncDecl:
@@ -620,24 +627,24 @@ func isFunctionParam(obj types.Object, node *ast.FuncDecl) bool {
620627
return false
621628
}
622629

623-
// formatGenDecl returns hover information an object declared via spec inside
630+
// hoverGenDecl returns hover information an object declared via spec inside
624631
// of the GenDecl node. obj is the type-checked object corresponding to the
625632
// declaration, but may have been type-checked using a different AST than the
626633
// given nodes; fullPos is the position of obj in node's AST.
627-
func formatGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj types.Object) (*HoverContext, error) {
634+
func hoverGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj types.Object) (*HoverContext, error) {
628635
if spec == nil {
629636
return nil, errors.Errorf("no spec for node %v at position %v", node, fullPos)
630637
}
631638

632639
// If we have a field or method.
633640
switch obj.(type) {
634641
case *types.Var, *types.Const, *types.Func:
635-
return formatVar(spec, fullPos, obj, node), nil
642+
return hoverVar(spec, fullPos, obj, node), nil
636643
}
637644
// Handle types.
638645
switch spec := spec.(type) {
639646
case *ast.TypeSpec:
640-
return formatTypeSpec(spec, node), nil
647+
return hoverTypeSpec(spec, node), nil
641648
case *ast.ValueSpec:
642649
return &HoverContext{signatureSource: spec, Comment: spec.Doc}, nil
643650
case *ast.ImportSpec:
@@ -646,7 +653,8 @@ func formatGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj type
646653
return nil, errors.Errorf("unable to format spec %v (%T)", spec, spec)
647654
}
648655

649-
func formatTypeSpec(spec *ast.TypeSpec, decl *ast.GenDecl) *HoverContext {
656+
// TODO(rfindley): rename this function.
657+
func hoverTypeSpec(spec *ast.TypeSpec, decl *ast.GenDecl) *HoverContext {
650658
comment := spec.Doc
651659
if comment == nil && decl != nil {
652660
comment = decl.Doc
@@ -660,7 +668,7 @@ func formatTypeSpec(spec *ast.TypeSpec, decl *ast.GenDecl) *HoverContext {
660668
}
661669
}
662670

663-
func formatVar(node ast.Spec, fullPos token.Pos, obj types.Object, decl *ast.GenDecl) *HoverContext {
671+
func hoverVar(node ast.Spec, fullPos token.Pos, obj types.Object, decl *ast.GenDecl) *HoverContext {
664672
var fieldList *ast.FieldList
665673
switch spec := node.(type) {
666674
case *ast.TypeSpec:
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package hover
22

3-
type value[T any] struct { //@mark(value, "value"),hoverdef("value", value)
3+
type value[T any] struct { //@mark(value, "value"),hoverdef("value", value),mark(valueTdecl, "T"),hoverdef("T",valueTdecl)
44
val T //@mark(valueTparam, "T"),hoverdef("T", valueTparam)
55
Q int //@mark(valueQfield, "Q"),hoverdef("Q", valueQfield)
66
}
77

8-
type Value[T any] struct {
8+
type Value[T any] struct { //@mark(ValueTdecl, "T"),hoverdef("T",ValueTdecl)
99
val T //@mark(ValueTparam, "T"),hoverdef("T", ValueTparam)
1010
Q int //@mark(ValueQfield, "Q"),hoverdef("Q", ValueQfield)
1111
}
12+
13+
func F[P interface{ ~int | string }]() { //@mark(Pparam, "P"),hoverdef("P",Pparam)
14+
var _ P //@mark(Pvar, "P"),hoverdef("P",Pvar)
15+
}

internal/lsp/testdata/godef/hover_generics/hover.go.golden

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,41 @@ type value[T any] struct {
55
Q int //@mark(valueQfield, "Q"),hoverdef("Q", valueQfield)
66
}
77
```
8-
-- valueTparam-hoverdef --
8+
-- ValueQfield-hoverdef --
99
```go
10-
type value[T any] struct {
11-
val T //@mark(valueTparam, "T"),hoverdef("T", valueTparam)
12-
Q int //@mark(valueQfield, "Q"),hoverdef("Q", valueQfield)
13-
}
10+
field Q int
11+
```
12+
13+
[`(hover.Value).Q` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/hover_generics?utm_source=gopls#Value.Q)
14+
15+
\@mark\(ValueQfield, \"Q\"\),hoverdef\(\"Q\", ValueQfield\)
16+
-- ValueTdecl-hoverdef --
17+
```go
18+
type parameter T any
19+
```
20+
-- ValueTparam-hoverdef --
21+
```go
22+
type parameter T any
1423
```
1524
-- valueQfield-hoverdef --
1625
```go
1726
field Q int
1827
```
1928

2029
\@mark\(valueQfield, \"Q\"\),hoverdef\(\"Q\", valueQfield\)
21-
-- ValueTparam-hoverdef --
30+
-- valueTdecl-hoverdef --
2231
```go
23-
type Value[T any] struct {
24-
val T //@mark(ValueTparam, "T"),hoverdef("T", ValueTparam)
25-
Q int //@mark(ValueQfield, "Q"),hoverdef("Q", ValueQfield)
26-
}
32+
type parameter T any
2733
```
28-
-- ValueQfield-hoverdef --
34+
-- valueTparam-hoverdef --
2935
```go
30-
field Q int
36+
type parameter T any
37+
```
38+
-- Pparam-hoverdef --
39+
```go
40+
type parameter P interface{~int|string}
41+
```
42+
-- Pvar-hoverdef --
43+
```go
44+
type parameter P interface{~int|string}
3145
```
32-
33-
[`(hover.Value).Q` on pkg.go.dev](https://pkg.go.dev/golang.org/x/tools/internal/lsp/godef/hover_generics?utm_source=gopls#Value.Q)
34-
35-
\@mark\(ValueQfield, \"Q\"\),hoverdef\(\"Q\", ValueQfield\)
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
-- argInfer-hoverdef --
22
```go
3-
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
3+
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
44
```
55
-- constrInf-hoverdef --
66
```go
77
func app(s []int, e int) []int // func[S₁ interface{~[]E₂}, E₂ interface{}](s S₁, e E₂) S₁
88
```
99
-- constrInfer-hoverdef --
1010
```go
11-
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
11+
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
1212
```
1313
-- instance-hoverdef --
1414
```go
15-
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
15+
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
1616
```
1717
-- partialInfer-hoverdef --
1818
```go
19-
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
19+
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
2020
```

internal/lsp/testdata/summary_go1.18.txt.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ SemanticTokenCount = 3
1616
SuggestedFixCount = 61
1717
FunctionExtractionCount = 25
1818
MethodExtractionCount = 6
19-
DefinitionsCount = 104
19+
DefinitionsCount = 108
2020
TypeDefinitionsCount = 18
2121
HighlightsCount = 69
2222
ReferencesCount = 27

0 commit comments

Comments
 (0)