|  | 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 | 
|  | } | 
|  |  | 
|  | }) | 
|  | got = tests.FilterBuiltins(src, 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) {}) | 
|  | got = tests.FilterBuiltins(src, 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 | 
|  | }) | 
|  | got = tests.FilterBuiltins(src, 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 | 
|  | }) | 
|  | got = tests.FilterBuiltins(src, 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 | 
|  | }) | 
|  | got = tests.FilterBuiltins(src, 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.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 | 
|  | } |