mirror of
https://github.com/golang/go
synced 2024-11-19 02:04:42 -07:00
1b668f2091
If a client doesn't support the snippet format in completion insert text, they can't take full advantage of the literal completion candidates. Disable it in those cases, and remove the setting in internal/lsp/source/options.go. Fixes golang/go#36655. Change-Id: Ibc045a0f2945aab753b0187194a03d0c0398dba5 Reviewed-on: https://go-review.googlesource.com/c/tools/+/216299 Run-TryBot: Rebecca Stambler <rstambler@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
163 lines
5.0 KiB
Go
163 lines
5.0 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.PlainTextTextFormat
|
|
// Only enable literal completions if in the completion literals tests.
|
|
// TODO(rstambler): Separate out literal completion tests.
|
|
if strings.Contains(string(src.URI()), "literal") {
|
|
opts.InsertTextFormat = protocol.SnippetTextFormat
|
|
}
|
|
|
|
})
|
|
if !strings.Contains(string(src.URI()), "builtins") {
|
|
got = tests.FilterBuiltins(got)
|
|
}
|
|
want := expected(t, test, items)
|
|
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
|
t.Errorf("%s: %s", src, 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: %v", src, 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) {})
|
|
if !strings.Contains(string(src.URI()), "builtins") {
|
|
got = tests.FilterBuiltins(got)
|
|
}
|
|
want := expected(t, test, items)
|
|
if diff := tests.CheckCompletionOrder(want, got, false); diff != "" {
|
|
t.Errorf("%s: %s", src, 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
|
|
})
|
|
if !strings.Contains(string(src.URI()), "builtins") {
|
|
got = tests.FilterBuiltins(got)
|
|
}
|
|
want := expected(t, test, items)
|
|
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
|
t.Errorf("%s: %s", src, 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
|
|
})
|
|
if !strings.Contains(string(src.URI()), "builtins") {
|
|
got = tests.FilterBuiltins(got)
|
|
}
|
|
want := expected(t, test, items)
|
|
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
|
t.Errorf("%s: %s", src, 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
|
|
})
|
|
if !strings.Contains(string(src.URI()), "builtins") {
|
|
got = tests.FilterBuiltins(got)
|
|
}
|
|
want := expected(t, test, items)
|
|
if msg := tests.DiffCompletionItems(want, got); msg != "" {
|
|
t.Errorf("%s: %s", src, 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
|
|
})
|
|
want := expected(t, test, items)
|
|
if msg := tests.CheckCompletionOrder(want, got, true); msg != "" {
|
|
t.Errorf("%s: %s", src, 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.NewURI(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
|
|
}
|