--- /dev/null
+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 := view.Options().Clone()
+ 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
+}