lsp/completion: improve completion for func type params

Now when instantiating a generic function, we prefer type names that
are assignable to the corresponding constraint. For example:

    func foo[A int|string]() {}

    foo[<>]()

At <> we prefer the type names "int" and "string". Previously we had
no preference at all.

Updates golang/go#51782.

Change-Id: I7ed39ffa2bc4c63e9d320f47a58e139251712bb3
Reviewed-on: https://go-review.googlesource.com/c/tools/+/394014
Run-TryBot: Muir Manders <muir@mnd.rs>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Muir Manders 2022-03-18 20:41:49 -07:00 committed by Robert Findley
parent c717623e31
commit 3a6cbd67dd
3 changed files with 34 additions and 1 deletions

View File

@ -29,6 +29,7 @@ import (
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/snippet"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/typeparams"
errors "golang.org/x/xerrors"
)
@ -2093,6 +2094,25 @@ Nodes:
inf.objType = t.Key()
case *types.Slice, *types.Array:
inf.objType = types.Typ[types.UntypedInt]
case *types.Signature:
if tp := typeparams.ForSignature(t); tp.Len() > 0 {
inf.objType = tp.At(0).Constraint()
inf.typeName.wantTypeName = true
}
}
}
}
return inf
case *typeparams.IndexListExpr:
if node.Lbrack < c.pos && c.pos <= node.Rbrack {
if tv, ok := c.pkg.GetTypesInfo().Types[node.X]; ok {
switch t := tv.Type.Underlying().(type) {
case *types.Signature:
paramIdx := exprAtPos(c.pos, node.Indices)
if tp := typeparams.ForSignature(t); paramIdx < tp.Len() {
inf.objType = tp.At(paramIdx).Constraint()
inf.typeName.wantTypeName = true
}
}
}
}

View File

@ -6,7 +6,7 @@ CompletionSnippetCount = 109
UnimportedCompletionsCount = 5
DeepCompletionsCount = 5
FuzzyCompletionsCount = 8
RankedCompletionsCount = 163
RankedCompletionsCount = 166
CaseSensitiveCompletionsCount = 4
DiagnosticsCount = 37
FoldingRangesCount = 2

View File

@ -0,0 +1,13 @@
//go:build go1.18
// +build go1.18
package typeparams
func one[a int | string]() {}
func two[a int | string, b float64 | int]() {}
func _() {
one[]() //@rank("]", string, float64)
two[]() //@rank("]", int, float64)
two[int, f]() //@rank("]", float64, float32)
}