mirror of https://github.com/golang/go.git
lsp/completion: fix func literals with type params
Give placeholders for type params in func literal completions. For
example:
func foo[T any](func(T) T) {}
foo(<>)
Will now give "func(<T>) <T> {}" where <> denotes a placeholder.
Change-Id: Iadde73ed6b88e1410c28dfa33a20ab6a51235c93
Reviewed-on: https://go-review.googlesource.com/c/tools/+/400616
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>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
5bb9a5ecb1
commit
b44fad8412
|
|
@ -186,12 +186,18 @@ func (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, m
|
|||
var (
|
||||
paramNames = make([]string, sig.Params().Len())
|
||||
paramNameCount = make(map[string]int)
|
||||
hasTypeParams bool
|
||||
)
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
var (
|
||||
p = sig.Params().At(i)
|
||||
name = p.Name()
|
||||
)
|
||||
|
||||
if tp, _ := p.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
|
||||
hasTypeParams = true
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
// If the param has no name in the signature, guess a name based
|
||||
// on the type. Use an empty qualifier to ignore the package.
|
||||
|
|
@ -219,6 +225,14 @@ func (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, m
|
|||
}
|
||||
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
if hasTypeParams && !c.opts.placeholders {
|
||||
// If there are type params in the args then the user must
|
||||
// choose the concrete types. If placeholders are disabled just
|
||||
// drop them between the parens and let them fill things in.
|
||||
snip.WritePlaceholder(nil)
|
||||
break
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
snip.WriteText(", ")
|
||||
}
|
||||
|
|
@ -254,7 +268,14 @@ func (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, m
|
|||
if sig.Variadic() && i == sig.Params().Len()-1 {
|
||||
typeStr = strings.Replace(typeStr, "[]", "...", 1)
|
||||
}
|
||||
snip.WriteText(typeStr)
|
||||
|
||||
if tp, _ := p.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
|
||||
snip.WritePlaceholder(func(snip *snippet.Builder) {
|
||||
snip.WriteText(typeStr)
|
||||
})
|
||||
} else {
|
||||
snip.WriteText(typeStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
snip.WriteText(")")
|
||||
|
|
@ -267,10 +288,24 @@ func (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, m
|
|||
resultsNeedParens := results.Len() > 1 ||
|
||||
results.Len() == 1 && results.At(0).Name() != ""
|
||||
|
||||
var resultHasTypeParams bool
|
||||
for i := 0; i < results.Len(); i++ {
|
||||
if tp, _ := results.At(i).Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
|
||||
resultHasTypeParams = true
|
||||
}
|
||||
}
|
||||
|
||||
if resultsNeedParens {
|
||||
snip.WriteText("(")
|
||||
}
|
||||
for i := 0; i < results.Len(); i++ {
|
||||
if resultHasTypeParams && !c.opts.placeholders {
|
||||
// Leave an empty tabstop if placeholders are disabled and there
|
||||
// are type args that need specificying.
|
||||
snip.WritePlaceholder(nil)
|
||||
break
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
snip.WriteText(", ")
|
||||
}
|
||||
|
|
@ -278,7 +313,15 @@ func (c *completer) functionLiteral(ctx context.Context, sig *types.Signature, m
|
|||
if name := r.Name(); name != "" {
|
||||
snip.WriteText(name + " ")
|
||||
}
|
||||
snip.WriteText(source.FormatVarType(ctx, c.snapshot, c.pkg, r, c.qf))
|
||||
|
||||
text := source.FormatVarType(ctx, c.snapshot, c.pkg, r, c.qf)
|
||||
if tp, _ := r.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
|
||||
snip.WritePlaceholder(func(snip *snippet.Builder) {
|
||||
snip.WriteText(text)
|
||||
})
|
||||
} else {
|
||||
snip.WriteText(text)
|
||||
}
|
||||
}
|
||||
if resultsNeedParens {
|
||||
snip.WriteText(")")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
CallHierarchyCount = 2
|
||||
CodeLensCount = 5
|
||||
CompletionsCount = 266
|
||||
CompletionSnippetCount = 113
|
||||
CompletionSnippetCount = 116
|
||||
UnimportedCompletionsCount = 5
|
||||
DeepCompletionsCount = 5
|
||||
FuzzyCompletionsCount = 8
|
||||
|
|
|
|||
|
|
@ -48,3 +48,13 @@ func _() {
|
|||
var ab float64 //@item(tpFloat, "ab", "float64", "var")
|
||||
returnTP[int](a) //@rank(")", tpInt, tpFloat)
|
||||
}
|
||||
|
||||
func takesFunc[T any](func(T) T) {
|
||||
var _ func(t T) T = f //@snippet(" //", tpLitFunc, "func(t T) T {$0\\}", "func(t T) T {$0\\}")
|
||||
}
|
||||
|
||||
func _() {
|
||||
_ = "func(...) {}" //@item(tpLitFunc, "func(...) {}", "", "var")
|
||||
takesFunc() //@snippet(")", tpLitFunc, "func(${1:}) ${2:} {$0\\}", "func(${1:t} ${2:T}) ${3:T} {$0\\}")
|
||||
takesFunc[int]() //@snippet(")", tpLitFunc, "func(i int) int {$0\\}", "func(${1:i} int) int {$0\\}")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue