1
0
mirror of https://github.com/golang/go synced 2024-11-18 14:14:46 -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 is a type that must be assertable to our candidate type.
assertableFrom types.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 // 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 { func expectTypeName(c *completer) typeNameInference {
var ( var (
wantTypeName bool wantTypeName bool
wantComparable bool
modifiers []typeModifier modifiers []typeModifier
assertableFrom types.Type assertableFrom types.Type
) )
@ -1280,6 +1284,16 @@ Nodes:
break 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: default:
if breaksExpectedTypeInference(p) { if breaksExpectedTypeInference(p) {
return typeNameInference{} return typeNameInference{}
@ -1289,6 +1303,7 @@ Nodes:
return typeNameInference{ return typeNameInference{
wantTypeName: wantTypeName, wantTypeName: wantTypeName,
wantComparable: wantComparable,
modifiers: modifiers, modifiers: modifiers,
assertableFrom: assertableFrom, 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: // We can expect a type name and have an expected type in cases like:
// //
// var foo []int // 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) fuzzyMatcher := fuzzy.NewMatcher(prefix)
var got []protocol.CompletionItem var got []protocol.CompletionItem
for _, item := range list { for _, item := range list {
if fuzzyMatcher.Score(item.Label) < 0 { if fuzzyMatcher.Score(item.Label) <= 0 {
continue continue
} }
got = append(got, item) 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 var got []protocol.CompletionItem
for _, item := range list { for _, item := range list {
if fuzzyMatcher != nil && fuzzyMatcher.Score(item.Label) < 0 { if fuzzyMatcher != nil && fuzzyMatcher.Score(item.Label) <= 0 {
continue continue
} }
got = append(got, item) got = append(got, item)
@ -222,13 +222,10 @@ func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completi
Deep: true, Deep: true,
Budget: 5 * time.Second, Budget: 5 * time.Second,
}) })
if !strings.Contains(string(src.URI()), "builtins") {
list = tests.FilterBuiltins(list)
}
fuzzyMatcher := fuzzy.NewMatcher(prefix) fuzzyMatcher := fuzzy.NewMatcher(prefix)
var got []protocol.CompletionItem var got []protocol.CompletionItem
for _, item := range list { for _, item := range list {
if fuzzyMatcher.Score(item.Label) < 0 { if fuzzyMatcher.Score(item.Label) <= 0 {
continue continue
} }
got = append(got, item) 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 -- -- summary --
CompletionsCount = 216 CompletionsCount = 219
CompletionSnippetCount = 39 CompletionSnippetCount = 39
UnimportedCompletionsCount = 1 UnimportedCompletionsCount = 1
DeepCompletionsCount = 5 DeepCompletionsCount = 5
FuzzyCompletionsCount = 7 FuzzyCompletionsCount = 7
RankedCompletionsCount = 1 RankedCompletionsCount = 2
CaseSensitiveCompletionsCount = 4 CaseSensitiveCompletionsCount = 4
DiagnosticsCount = 22 DiagnosticsCount = 22
FoldingRangesCount = 2 FoldingRangesCount = 2