mirror of
https://github.com/golang/go
synced 2024-11-18 14:04:45 -07:00
internal/lsp/source: handle completing into variadic params
For example: func foo(string, ...int) func a() string func b() (string, int) func c() (string, int, int) // Prefer "a()" and "b()" and "c()". Previously we didn't prefer any of // them. foo(<>) Fixes golang/go#36540. Change-Id: I144b3f63942b7699d3034efcc9ad8535a7fa3165 Reviewed-on: https://go-review.googlesource.com/c/tools/+/215538 Run-TryBot: Muir Manders <muir@mnd.rs> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
c229649527
commit
ea829e2eb2
@ -1311,6 +1311,17 @@ type candidateInference struct {
|
||||
//
|
||||
// at "<>", the assignees are [int, <invalid>].
|
||||
assignees []types.Type
|
||||
|
||||
// variadicAssignees is true if we could be completing an inner
|
||||
// function call that fills out an outer function call's variadic
|
||||
// params. For example:
|
||||
//
|
||||
// func foo(int, ...string) {}
|
||||
//
|
||||
// foo(<>) // variadicAssignees=true
|
||||
// foo(bar<>) // variadicAssignees=true
|
||||
// foo(bar, baz<>) // variadicAssignees=false
|
||||
variadicAssignees bool
|
||||
}
|
||||
|
||||
// typeNameInference holds information about the expected type name at
|
||||
@ -1415,6 +1426,9 @@ Nodes:
|
||||
for i := 0; i < sig.Params().Len(); i++ {
|
||||
inf.assignees = append(inf.assignees, sig.Params().At(i).Type())
|
||||
}
|
||||
|
||||
// Record that we may be completing into variadic parameters.
|
||||
inf.variadicAssignees = sig.Variadic()
|
||||
}
|
||||
|
||||
if sig.Variadic() {
|
||||
@ -1899,15 +1913,19 @@ func (ci *candidateInference) signatureMatches(cand *candidate, sig *types.Signa
|
||||
return false
|
||||
}
|
||||
|
||||
var numberOfResultsCouldMatch bool
|
||||
if ci.variadicAssignees {
|
||||
numberOfResultsCouldMatch = sig.Results().Len() >= len(ci.assignees)-1
|
||||
} else {
|
||||
numberOfResultsCouldMatch = sig.Results().Len() == len(ci.assignees)
|
||||
}
|
||||
|
||||
// If our signature doesn't return the right number of values, it's
|
||||
// not a match, so downrank it. For example:
|
||||
//
|
||||
// var foo func() (int, int)
|
||||
// a, b, c := <> // downrank "foo()" since it only returns two values
|
||||
//
|
||||
// TODO: handle the case when we are completing the parameters to a
|
||||
// variadic function call.
|
||||
if sig.Results().Len() != len(ci.assignees) {
|
||||
if !numberOfResultsCouldMatch {
|
||||
cand.score /= 2
|
||||
return false
|
||||
}
|
||||
@ -1916,11 +1934,21 @@ func (ci *candidateInference) signatureMatches(cand *candidate, sig *types.Signa
|
||||
// assignees match the corresponding sig result value, the signature
|
||||
// is a match.
|
||||
allMatch := false
|
||||
for i, a := range ci.assignees {
|
||||
if a == nil || a.Underlying() == types.Typ[types.Invalid] {
|
||||
continue
|
||||
for i := 0; i < sig.Results().Len(); i++ {
|
||||
var assignee types.Type
|
||||
|
||||
// If we are completing into variadic parameters, deslice the
|
||||
// expected variadic type.
|
||||
if ci.variadicAssignees && i >= len(ci.assignees)-1 {
|
||||
assignee = ci.assignees[len(ci.assignees)-1]
|
||||
if slice, ok := assignee.Underlying().(*types.Slice); ok {
|
||||
assignee = slice.Elem()
|
||||
}
|
||||
} else {
|
||||
assignee = ci.assignees[i]
|
||||
}
|
||||
allMatch = ci.typeMatches(cand, a, sig.Results().At(i).Type())
|
||||
|
||||
allMatch = ci.typeMatches(cand, assignee, sig.Results().At(i).Type())
|
||||
if !allMatch {
|
||||
break
|
||||
}
|
||||
|
@ -30,4 +30,7 @@ func _() {
|
||||
|
||||
var s string
|
||||
_, s := f //@rank(" //", multiF2Str, multiF2)
|
||||
|
||||
var variadic func(int, ...int)
|
||||
variadic() //@rank(")", multiF1, multiF0),rank(")", multiF2, multiF0),rank(")", multiF3, multiF0)
|
||||
}
|
||||
|
2
internal/lsp/testdata/lsp/summary.txt.golden
vendored
2
internal/lsp/testdata/lsp/summary.txt.golden
vendored
@ -5,7 +5,7 @@ CompletionSnippetCount = 67
|
||||
UnimportedCompletionsCount = 11
|
||||
DeepCompletionsCount = 5
|
||||
FuzzyCompletionsCount = 8
|
||||
RankedCompletionsCount = 99
|
||||
RankedCompletionsCount = 102
|
||||
CaseSensitiveCompletionsCount = 4
|
||||
DiagnosticsCount = 38
|
||||
FoldingRangesCount = 2
|
||||
|
Loading…
Reference in New Issue
Block a user