1
0
mirror of https://github.com/golang/go synced 2024-11-18 10:54:40 -07:00
go/internal/lsp/completion_test.go
Heschi Kreinick 6a8222ee25 gopls/doc: generate settings JSON, docs
gopls has many settings. We want to automatically generate
documentation, and we want to allow clients to perform their own
validation if they so desire.

Using all three of AST, type information, and reflection, generate a
JSON description of the settings and their default values. Add a gopls
command that prints it. Add a documentation generator that uses it to
write settings.md.

I assumed that everything not explicitly documented was experimental,
and moved it into that section. I also moved expandWorkspaceToModule to
experimental; I hope it's not long for this world, personally.

Along the way, rename many fields, make the enum matching case
insensitive, and add a stringer call so that the defaults print nicely.

Fixes golang/go#33544.

Change-Id: Ibb652002933e355ed3c6038d6ca48345b39b3025
Reviewed-on: https://go-review.googlesource.com/c/tools/+/252322
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-09-09 20:53:33 +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.CompleteUnimported = 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.UsePlaceholders = placeholders
opts.DeepCompletion = true
opts.Matcher = source.Fuzzy
opts.CompleteUnimported = 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.CompleteUnimported = 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.CompleteUnimported = 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.CompleteUnimported = 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.CompleteUnimported = 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
}