1
0
mirror of https://github.com/golang/go synced 2024-11-18 10:04:43 -07:00
go/internal/lsp/completion_test.go
Muir Manders 6fbe43b70d internal/lsp/source: improve completion in append()
In the following example:

    var foo []someStruct
    foo = append(foo, <>)

we now downrank "foo" as a candidate at "<>". You very rarely append a
slice to itself, so having "foo" ranked highly was counterproductive.

Fixes golang/go#40535.

Change-Id: Ic01366aeded4ba2b6b64bfddd33415499b35a323
Reviewed-on: https://go-review.googlesource.com/c/tools/+/247519
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-08-15 16:31:36 +00:00

151 lines
4.5 KiB
Go

package lsp
import (
"strings"
"testing"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/lsp/tests"
"golang.org/x/tools/internal/span"
)
func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
got := r.callCompletion(t, src, func(opts *source.Options) {
opts.DeepCompletion = false
opts.Matcher = source.CaseInsensitive
opts.UnimportedCompletion = false
opts.InsertTextFormat = protocol.SnippetTextFormat
if !strings.Contains(string(src.URI()), "literal") {
opts.LiteralCompletions = false
}
})
got = tests.FilterBuiltins(src, got)
want := expected(t, test, items)
if diff := tests.DiffCompletionItems(want, got); diff != "" {
t.Errorf("%s", diff)
}
}
func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.CompletionSnippet, placeholders bool, items tests.CompletionItems) {
list := r.callCompletion(t, src, func(opts *source.Options) {
opts.Placeholders = placeholders
opts.DeepCompletion = true
opts.Matcher = source.Fuzzy
opts.UnimportedCompletion = false
})
got := tests.FindItem(list, *items[expected.CompletionItem])
want := expected.PlainSnippet
if placeholders {
want = expected.PlaceholderSnippet
}
if diff := tests.DiffSnippets(want, got); diff != "" {
t.Errorf("%s", diff)
}
}
func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
got := r.callCompletion(t, src, func(opts *source.Options) {})
got = tests.FilterBuiltins(src, got)
want := expected(t, test, items)
if diff := tests.CheckCompletionOrder(want, got, false); diff != "" {
t.Errorf("%s", diff)
}
}
func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
got := r.callCompletion(t, src, func(opts *source.Options) {
opts.DeepCompletion = true
opts.Matcher = source.CaseInsensitive
opts.UnimportedCompletion = false
})
got = tests.FilterBuiltins(src, got)
want := expected(t, test, items)
if msg := tests.DiffCompletionItems(want, got); msg != "" {
t.Errorf("%s", msg)
}
}
func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
got := r.callCompletion(t, src, func(opts *source.Options) {
opts.DeepCompletion = true
opts.Matcher = source.Fuzzy
opts.UnimportedCompletion = false
})
got = tests.FilterBuiltins(src, got)
want := expected(t, test, items)
if msg := tests.DiffCompletionItems(want, got); msg != "" {
t.Errorf("%s", msg)
}
}
func (r *runner) CaseSensitiveCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
got := r.callCompletion(t, src, func(opts *source.Options) {
opts.Matcher = source.CaseSensitive
opts.UnimportedCompletion = false
})
got = tests.FilterBuiltins(src, got)
want := expected(t, test, items)
if msg := tests.DiffCompletionItems(want, got); msg != "" {
t.Errorf("%s", msg)
}
}
func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
got := r.callCompletion(t, src, func(opts *source.Options) {
opts.DeepCompletion = true
opts.Matcher = source.Fuzzy
opts.UnimportedCompletion = false
opts.LiteralCompletions = true
})
want := expected(t, test, items)
if msg := tests.CheckCompletionOrder(want, got, true); msg != "" {
t.Errorf("%s", msg)
}
}
func expected(t *testing.T, test tests.Completion, items tests.CompletionItems) []protocol.CompletionItem {
t.Helper()
var want []protocol.CompletionItem
for _, pos := range test.CompletionItems {
item := items[pos]
want = append(want, tests.ToProtocolCompletionItem(*item))
}
return want
}
func (r *runner) callCompletion(t *testing.T, src span.Span, options func(*source.Options)) []protocol.CompletionItem {
t.Helper()
view, err := r.server.session.ViewOf(src.URI())
if err != nil {
t.Fatal(err)
}
original := view.Options()
modified := original
options(&modified)
view, err = view.SetOptions(r.ctx, modified)
if err != nil {
t.Error(err)
return nil
}
defer view.SetOptions(r.ctx, original)
list, err := r.server.Completion(r.ctx, &protocol.CompletionParams{
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
TextDocument: protocol.TextDocumentIdentifier{
URI: protocol.URIFromSpanURI(src.URI()),
},
Position: protocol.Position{
Line: float64(src.Start().Line() - 1),
Character: float64(src.Start().Column() - 1),
},
},
})
if err != nil {
t.Fatal(err)
}
return list.Items
}