mirror of https://github.com/golang/go.git
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 <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> Reviewed-by: Heschi Kreinick <heschi@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
411d04022e
commit
adcfb65266
|
|
@ -477,6 +477,13 @@ func objectString(obj types.Object, qf types.Qualifier, inferred *types.Signatur
|
|||
func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Object, pkgNode ast.Node, fullDecl ast.Decl) (*HoverContext, error) {
|
||||
var info *HoverContext
|
||||
|
||||
// Type parameters get their signature from their declaration object.
|
||||
if _, isTypeName := obj.(*types.TypeName); isTypeName {
|
||||
if _, isTypeParam := obj.Type().(*typeparams.TypeParam); isTypeParam {
|
||||
return &HoverContext{signatureSource: obj}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// This is problematic for a number of reasons. We really need to have a more
|
||||
// general mechanism to validate the coherency of AST with type information,
|
||||
// but absent that we must do our best to ensure that we don't use fullNode
|
||||
|
|
@ -555,7 +562,7 @@ func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Ob
|
|||
}
|
||||
}
|
||||
|
||||
info, err = formatGenDecl(node, spec, fullPos, obj)
|
||||
info, err = hoverGenDecl(node, spec, fullPos, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -563,7 +570,7 @@ func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Ob
|
|||
case *ast.TypeSpec:
|
||||
if obj.Parent() == types.Universe {
|
||||
if genDecl, ok := fullDecl.(*ast.GenDecl); ok {
|
||||
info = formatTypeSpec(node, genDecl)
|
||||
info = hoverTypeSpec(node, genDecl)
|
||||
}
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
|
|
@ -620,11 +627,11 @@ func isFunctionParam(obj types.Object, node *ast.FuncDecl) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// formatGenDecl returns hover information an object declared via spec inside
|
||||
// hoverGenDecl returns hover information an object declared via spec inside
|
||||
// of the GenDecl node. obj is the type-checked object corresponding to the
|
||||
// declaration, but may have been type-checked using a different AST than the
|
||||
// given nodes; fullPos is the position of obj in node's AST.
|
||||
func formatGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj types.Object) (*HoverContext, error) {
|
||||
func hoverGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj types.Object) (*HoverContext, error) {
|
||||
if spec == nil {
|
||||
return nil, errors.Errorf("no spec for node %v at position %v", node, fullPos)
|
||||
}
|
||||
|
|
@ -632,12 +639,12 @@ func formatGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj type
|
|||
// If we have a field or method.
|
||||
switch obj.(type) {
|
||||
case *types.Var, *types.Const, *types.Func:
|
||||
return formatVar(spec, fullPos, obj, node), nil
|
||||
return hoverVar(spec, fullPos, obj, node), nil
|
||||
}
|
||||
// Handle types.
|
||||
switch spec := spec.(type) {
|
||||
case *ast.TypeSpec:
|
||||
return formatTypeSpec(spec, node), nil
|
||||
return hoverTypeSpec(spec, node), nil
|
||||
case *ast.ValueSpec:
|
||||
return &HoverContext{signatureSource: spec, Comment: spec.Doc}, nil
|
||||
case *ast.ImportSpec:
|
||||
|
|
@ -646,7 +653,8 @@ func formatGenDecl(node *ast.GenDecl, spec ast.Spec, fullPos token.Pos, obj type
|
|||
return nil, errors.Errorf("unable to format spec %v (%T)", spec, spec)
|
||||
}
|
||||
|
||||
func formatTypeSpec(spec *ast.TypeSpec, decl *ast.GenDecl) *HoverContext {
|
||||
// TODO(rfindley): rename this function.
|
||||
func hoverTypeSpec(spec *ast.TypeSpec, decl *ast.GenDecl) *HoverContext {
|
||||
comment := spec.Doc
|
||||
if comment == nil && decl != nil {
|
||||
comment = decl.Doc
|
||||
|
|
@ -660,7 +668,7 @@ func formatTypeSpec(spec *ast.TypeSpec, decl *ast.GenDecl) *HoverContext {
|
|||
}
|
||||
}
|
||||
|
||||
func formatVar(node ast.Spec, fullPos token.Pos, obj types.Object, decl *ast.GenDecl) *HoverContext {
|
||||
func hoverVar(node ast.Spec, fullPos token.Pos, obj types.Object, decl *ast.GenDecl) *HoverContext {
|
||||
var fieldList *ast.FieldList
|
||||
switch spec := node.(type) {
|
||||
case *ast.TypeSpec:
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
package hover
|
||||
|
||||
type value[T any] struct { //@mark(value, "value"),hoverdef("value", value)
|
||||
type value[T any] struct { //@mark(value, "value"),hoverdef("value", value),mark(valueTdecl, "T"),hoverdef("T",valueTdecl)
|
||||
val T //@mark(valueTparam, "T"),hoverdef("T", valueTparam)
|
||||
Q int //@mark(valueQfield, "Q"),hoverdef("Q", valueQfield)
|
||||
}
|
||||
|
||||
type Value[T any] struct {
|
||||
type Value[T any] struct { //@mark(ValueTdecl, "T"),hoverdef("T",ValueTdecl)
|
||||
val T //@mark(ValueTparam, "T"),hoverdef("T", ValueTparam)
|
||||
Q int //@mark(ValueQfield, "Q"),hoverdef("Q", ValueQfield)
|
||||
}
|
||||
|
||||
func F[P interface{ ~int | string }]() { //@mark(Pparam, "P"),hoverdef("P",Pparam)
|
||||
var _ P //@mark(Pvar, "P"),hoverdef("P",Pvar)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,26 +5,6 @@ type value[T any] struct {
|
|||
Q int //@mark(valueQfield, "Q"),hoverdef("Q", valueQfield)
|
||||
}
|
||||
```
|
||||
-- valueTparam-hoverdef --
|
||||
```go
|
||||
type value[T any] struct {
|
||||
val T //@mark(valueTparam, "T"),hoverdef("T", valueTparam)
|
||||
Q int //@mark(valueQfield, "Q"),hoverdef("Q", valueQfield)
|
||||
}
|
||||
```
|
||||
-- valueQfield-hoverdef --
|
||||
```go
|
||||
field Q int
|
||||
```
|
||||
|
||||
\@mark\(valueQfield, \"Q\"\),hoverdef\(\"Q\", valueQfield\)
|
||||
-- ValueTparam-hoverdef --
|
||||
```go
|
||||
type Value[T any] struct {
|
||||
val T //@mark(ValueTparam, "T"),hoverdef("T", ValueTparam)
|
||||
Q int //@mark(ValueQfield, "Q"),hoverdef("Q", ValueQfield)
|
||||
}
|
||||
```
|
||||
-- ValueQfield-hoverdef --
|
||||
```go
|
||||
field Q int
|
||||
|
|
@ -33,3 +13,33 @@ field Q int
|
|||
[`(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)
|
||||
|
||||
\@mark\(ValueQfield, \"Q\"\),hoverdef\(\"Q\", ValueQfield\)
|
||||
-- ValueTdecl-hoverdef --
|
||||
```go
|
||||
type parameter T any
|
||||
```
|
||||
-- ValueTparam-hoverdef --
|
||||
```go
|
||||
type parameter T any
|
||||
```
|
||||
-- valueQfield-hoverdef --
|
||||
```go
|
||||
field Q int
|
||||
```
|
||||
|
||||
\@mark\(valueQfield, \"Q\"\),hoverdef\(\"Q\", valueQfield\)
|
||||
-- valueTdecl-hoverdef --
|
||||
```go
|
||||
type parameter T any
|
||||
```
|
||||
-- valueTparam-hoverdef --
|
||||
```go
|
||||
type parameter T any
|
||||
```
|
||||
-- Pparam-hoverdef --
|
||||
```go
|
||||
type parameter P interface{~int|string}
|
||||
```
|
||||
-- Pvar-hoverdef --
|
||||
```go
|
||||
type parameter P interface{~int|string}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
-- argInfer-hoverdef --
|
||||
```go
|
||||
func app(s []int, e int) []int // func[S₁ interface{~[]E₂}, E₂ interface{}](s S₁, e E₂) S₁
|
||||
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
|
||||
```
|
||||
-- constrInf-hoverdef --
|
||||
```go
|
||||
|
|
@ -8,13 +8,13 @@ func app(s []int, e int) []int // func[S₁ interface{~[]E₂}, E₂ interface{}
|
|||
```
|
||||
-- constrInfer-hoverdef --
|
||||
```go
|
||||
func app(s []int, e int) []int // func[S₁ interface{~[]E₂}, E₂ interface{}](s S₁, e E₂) S₁
|
||||
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
|
||||
```
|
||||
-- instance-hoverdef --
|
||||
```go
|
||||
func app(s []int, e int) []int // func[S₁ interface{~[]E₂}, E₂ interface{}](s S₁, e E₂) S₁
|
||||
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
|
||||
```
|
||||
-- partialInfer-hoverdef --
|
||||
```go
|
||||
func app(s []int, e int) []int // func[S₁ interface{~[]E₂}, E₂ interface{}](s S₁, e E₂) S₁
|
||||
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
|
||||
```
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ SemanticTokenCount = 3
|
|||
SuggestedFixCount = 61
|
||||
FunctionExtractionCount = 25
|
||||
MethodExtractionCount = 6
|
||||
DefinitionsCount = 104
|
||||
DefinitionsCount = 108
|
||||
TypeDefinitionsCount = 18
|
||||
HighlightsCount = 69
|
||||
ReferencesCount = 27
|
||||
|
|
|
|||
Loading…
Reference in New Issue