1
0
mirror of https://github.com/golang/go synced 2024-11-18 13:04:46 -07:00

internal/lsp: offer basic type conversion candidates

When the expected type is a basic type, we will now offer a
corresponding type conversion candidate. For example:

var foo int64
foo = // offer "int64(<>)" as a candidate

The type conversion candidate will be ranked below matching concrete
candidates but above the sea of non-matching candidates.

This change broke almost every completion test. I added a new
completion option for literal candidates so tests can selectively ask
for literal completions.

Updates golang/go#36015.

Change-Id: I63fbdb33436d662a666c1ffd3b2d918d840dccc7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/210288
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Muir Manders 2019-12-06 14:29:09 -08:00 committed by Rebecca Stambler
parent cfcbc7796e
commit 0f69de236b
7 changed files with 35 additions and 5 deletions

View File

@ -15,6 +15,7 @@ func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion,
Deep: false,
FuzzyMatching: false,
Documentation: true,
Literal: strings.Contains(string(src.URI()), "literal"),
})
if !strings.Contains(string(src.URI()), "builtins") {
got = tests.FilterBuiltins(got)
@ -30,6 +31,7 @@ func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.C
Placeholders: placeholders,
Deep: true,
FuzzyMatching: true,
Literal: true,
})
got := tests.FindItem(list, *items[expected.CompletionItem])
want := expected.PlainSnippet
@ -99,6 +101,7 @@ func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completi
got := r.callCompletion(t, src, source.CompletionOptions{
FuzzyMatching: true,
Deep: true,
Literal: true,
})
want := expected(t, test, items)
if msg := tests.CheckCompletionOrder(want, got, true); msg != "" {

View File

@ -322,7 +322,11 @@ func (c *completer) found(obj types.Object, score float64, imp *importInfo) {
} else if isTypeName(obj) {
// If obj is a *types.TypeName that didn't otherwise match, check
// if a literal object of this type makes a good candidate.
c.literal(obj.Type(), imp)
// We only care about named types (i.e. don't want builtin types).
if _, isNamed := obj.Type().(*types.Named); isNamed {
c.literal(obj.Type(), imp)
}
}
// Favor shallow matches by lowering weight according to depth.

View File

@ -20,6 +20,10 @@ import (
// literal generates composite literal, function literal, and make()
// completion items.
func (c *completer) literal(literalType types.Type, imp *importInfo) {
if !c.opts.Literal {
return
}
expType := c.expectedType.objType
if c.expectedType.variadic {
@ -124,8 +128,9 @@ func (c *completer) literal(literalType types.Type, imp *importInfo) {
case *types.Basic, *types.Signature:
// Add a literal completion for basic types that implement our
// expected interface (e.g. named string type http.Dir
// implements http.FileSystem).
if isInterface(expType) {
// implements http.FileSystem), or are identical to our expected
// type (i.e. yielding a type conversion such as "float64()").
if isInterface(expType) || types.Identical(expType, literalType) {
c.basicLiteral(t, typeName, float64(score), addlEdits)
}
}

View File

@ -64,6 +64,7 @@ var (
Documentation: true,
Deep: true,
FuzzyMatching: true,
Literal: true,
Budget: 100 * time.Millisecond,
},
ComputeEdits: myers.ComputeEdits,
@ -123,6 +124,7 @@ type CompletionOptions struct {
Documentation bool
FullDocumentation bool
Placeholders bool
Literal bool
// Budget is the soft latency goal for completion requests. Most
// requests finish in a couple milliseconds, but in some cases deep

View File

@ -110,6 +110,7 @@ func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion,
prefix, list := r.callCompletion(t, src, source.CompletionOptions{
Documentation: true,
FuzzyMatching: true,
Literal: strings.Contains(string(src.URI()), "literal"),
})
if !strings.Contains(string(src.URI()), "builtins") {
list = tests.FilterBuiltins(list)
@ -130,6 +131,7 @@ func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.C
_, list := r.callCompletion(t, src, source.CompletionOptions{
Placeholders: placeholders,
Deep: true,
Literal: true,
})
got := tests.FindItem(list, *items[expected.CompletionItem])
want := expected.PlainSnippet
@ -234,6 +236,7 @@ func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completi
prefix, list := r.callCompletion(t, src, source.CompletionOptions{
FuzzyMatching: true,
Deep: true,
Literal: true,
})
fuzzyMatcher := fuzzy.NewMatcher(prefix)
var got []protocol.CompletionItem

View File

@ -160,3 +160,16 @@ func _() {
sf = foo.Str //@snippet(" //", litStructFoo, "StructFoo{$0\\}", "StructFoo{$0\\}")
sf = foo. //@snippet(" //", litStructFoo, "StructFoo{$0\\}", "StructFoo{$0\\}")
}
func _() {
float64() //@item(litFloat64, "float64()", "float64", "var")
var f float64
f = fl //@complete(" //", litFloat64),snippet(" //", litFloat64, "float64($0)", "float64($0)")
type myInt int
myInt() //@item(litMyInt, "myInt()", "", "var")
var mi myInt
mi = my //@snippet(" //", litMyInt, "myInt($0)", "myInt($0)")
}

View File

@ -1,6 +1,6 @@
-- summary --
CompletionsCount = 221
CompletionSnippetCount = 51
CompletionsCount = 222
CompletionSnippetCount = 53
UnimportedCompletionsCount = 4
DeepCompletionsCount = 5
FuzzyCompletionsCount = 7