1
0
mirror of https://github.com/golang/go synced 2024-11-05 11:36:10 -07:00

internal/lsp: improve completions in *ast.MapType

We now expect a type name when in the key or value of a *ast.MapType.
I also added an extra filter to expect a comparable type for the key.

Change-Id: I647cf4d791b2c0960ad3b12702b91b9bc168599b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/197439
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Muir Manders 2019-09-17 14:59:27 -07:00 committed by Rebecca Stambler
parent b24f3822ec
commit 5228f4b59c
4 changed files with 42 additions and 8 deletions

View File

@ -989,6 +989,9 @@ type typeNameInference struct {
// assertableFrom is a type that must be assertable to our candidate type.
assertableFrom types.Type
// wantComparable is true if we want a comparable type.
wantComparable bool
}
// expectedType returns information about the expected type for an expression at
@ -1205,6 +1208,7 @@ func breaksExpectedTypeInference(n ast.Node) bool {
func expectTypeName(c *completer) typeNameInference {
var (
wantTypeName bool
wantComparable bool
modifiers []typeModifier
assertableFrom types.Type
)
@ -1280,6 +1284,16 @@ Nodes:
break Nodes
}
case *ast.MapType:
wantTypeName = true
if n.Key != nil {
wantComparable = n.Key.Pos() <= c.pos && c.pos <= n.Key.End()
} else {
// If the key is empty, assume we are completing the key if
// pos is directly after the "map[".
wantComparable = c.pos == n.Pos()+token.Pos(len("map["))
}
break Nodes
default:
if breaksExpectedTypeInference(p) {
return typeNameInference{}
@ -1289,6 +1303,7 @@ Nodes:
return typeNameInference{
wantTypeName: wantTypeName,
wantComparable: wantComparable,
modifiers: modifiers,
assertableFrom: assertableFrom,
}
@ -1389,6 +1404,10 @@ func (c *completer) matchingTypeName(cand *candidate) bool {
}
}
if c.expectedType.typeName.wantComparable && !types.Comparable(actual) {
return false
}
// We can expect a type name and have an expected type in cases like:
//
// var foo []int

View File

@ -157,7 +157,7 @@ func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completi
fuzzyMatcher := fuzzy.NewMatcher(prefix)
var got []protocol.CompletionItem
for _, item := range list {
if fuzzyMatcher.Score(item.Label) < 0 {
if fuzzyMatcher.Score(item.Label) <= 0 {
continue
}
got = append(got, item)
@ -186,7 +186,7 @@ func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Complet
}
var got []protocol.CompletionItem
for _, item := range list {
if fuzzyMatcher != nil && fuzzyMatcher.Score(item.Label) < 0 {
if fuzzyMatcher != nil && fuzzyMatcher.Score(item.Label) <= 0 {
continue
}
got = append(got, item)
@ -222,13 +222,10 @@ func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completi
Deep: true,
Budget: 5 * time.Second,
})
if !strings.Contains(string(src.URI()), "builtins") {
list = tests.FilterBuiltins(list)
}
fuzzyMatcher := fuzzy.NewMatcher(prefix)
var got []protocol.CompletionItem
for _, item := range list {
if fuzzyMatcher.Score(item.Label) < 0 {
if fuzzyMatcher.Score(item.Label) <= 0 {
continue
}
got = append(got, item)

18
internal/lsp/testdata/maps/maps.go.in vendored Normal file
View File

@ -0,0 +1,18 @@
package maps
func _() {
var aVar int //@item(mapVar, "aVar", "int", "var")
// not comparabale
type aSlice []int //@item(mapSliceType, "aSlice", "[]int", "type")
// comparable
type aStruct struct{} //@item(mapStructType, "aStruct", "struct{...}", "struct")
map[]a{} //@complete("]", mapStructType, mapSliceType, mapVar)
map[a]a{} //@complete("]", mapStructType, mapSliceType, mapVar)
map[a]a{} //@complete("{", mapSliceType, mapStructType, mapVar)
map[]a{} //@rank("]", int, mapSliceType)
}

View File

@ -1,10 +1,10 @@
-- summary --
CompletionsCount = 216
CompletionsCount = 219
CompletionSnippetCount = 39
UnimportedCompletionsCount = 1
DeepCompletionsCount = 5
FuzzyCompletionsCount = 7
RankedCompletionsCount = 1
RankedCompletionsCount = 2
CaseSensitiveCompletionsCount = 4
DiagnosticsCount = 22
FoldingRangesCount = 2