github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/internal/lsp/completion_test.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package lsp
     6  
     7  import (
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/jhump/golang-x-tools/internal/lsp/protocol"
    12  	"github.com/jhump/golang-x-tools/internal/lsp/source"
    13  	"github.com/jhump/golang-x-tools/internal/lsp/tests"
    14  	"github.com/jhump/golang-x-tools/internal/span"
    15  )
    16  
    17  func (r *runner) Completion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
    18  	got := r.callCompletion(t, src, func(opts *source.Options) {
    19  		opts.DeepCompletion = false
    20  		opts.Matcher = source.CaseInsensitive
    21  		opts.CompleteUnimported = false
    22  		opts.InsertTextFormat = protocol.SnippetTextFormat
    23  		opts.LiteralCompletions = strings.Contains(string(src.URI()), "literal")
    24  		opts.ExperimentalPostfixCompletions = strings.Contains(string(src.URI()), "postfix")
    25  	})
    26  	got = tests.FilterBuiltins(src, got)
    27  	want := expected(t, test, items)
    28  	if diff := tests.DiffCompletionItems(want, got); diff != "" {
    29  		t.Errorf("%s", diff)
    30  	}
    31  }
    32  
    33  func (r *runner) CompletionSnippet(t *testing.T, src span.Span, expected tests.CompletionSnippet, placeholders bool, items tests.CompletionItems) {
    34  	list := r.callCompletion(t, src, func(opts *source.Options) {
    35  		opts.UsePlaceholders = placeholders
    36  		opts.DeepCompletion = true
    37  		opts.Matcher = source.Fuzzy
    38  		opts.CompleteUnimported = false
    39  	})
    40  	got := tests.FindItem(list, *items[expected.CompletionItem])
    41  	want := expected.PlainSnippet
    42  	if placeholders {
    43  		want = expected.PlaceholderSnippet
    44  	}
    45  	if diff := tests.DiffSnippets(want, got); diff != "" {
    46  		t.Errorf("%s", diff)
    47  	}
    48  }
    49  
    50  func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
    51  	got := r.callCompletion(t, src, func(opts *source.Options) {})
    52  	got = tests.FilterBuiltins(src, got)
    53  	want := expected(t, test, items)
    54  	if diff := tests.CheckCompletionOrder(want, got, false); diff != "" {
    55  		t.Errorf("%s", diff)
    56  	}
    57  }
    58  
    59  func (r *runner) DeepCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
    60  	got := r.callCompletion(t, src, func(opts *source.Options) {
    61  		opts.DeepCompletion = true
    62  		opts.Matcher = source.CaseInsensitive
    63  		opts.CompleteUnimported = false
    64  	})
    65  	got = tests.FilterBuiltins(src, got)
    66  	want := expected(t, test, items)
    67  	if msg := tests.DiffCompletionItems(want, got); msg != "" {
    68  		t.Errorf("%s", msg)
    69  	}
    70  }
    71  
    72  func (r *runner) FuzzyCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
    73  	got := r.callCompletion(t, src, func(opts *source.Options) {
    74  		opts.DeepCompletion = true
    75  		opts.Matcher = source.Fuzzy
    76  		opts.CompleteUnimported = false
    77  	})
    78  	got = tests.FilterBuiltins(src, got)
    79  	want := expected(t, test, items)
    80  	if msg := tests.DiffCompletionItems(want, got); msg != "" {
    81  		t.Errorf("%s", msg)
    82  	}
    83  }
    84  
    85  func (r *runner) CaseSensitiveCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
    86  	got := r.callCompletion(t, src, func(opts *source.Options) {
    87  		opts.Matcher = source.CaseSensitive
    88  		opts.CompleteUnimported = false
    89  	})
    90  	got = tests.FilterBuiltins(src, got)
    91  	want := expected(t, test, items)
    92  	if msg := tests.DiffCompletionItems(want, got); msg != "" {
    93  		t.Errorf("%s", msg)
    94  	}
    95  }
    96  
    97  func (r *runner) RankCompletion(t *testing.T, src span.Span, test tests.Completion, items tests.CompletionItems) {
    98  	got := r.callCompletion(t, src, func(opts *source.Options) {
    99  		opts.DeepCompletion = true
   100  		opts.Matcher = source.Fuzzy
   101  		opts.CompleteUnimported = false
   102  		opts.LiteralCompletions = true
   103  		opts.ExperimentalPostfixCompletions = true
   104  	})
   105  	want := expected(t, test, items)
   106  	if msg := tests.CheckCompletionOrder(want, got, true); msg != "" {
   107  		t.Errorf("%s", msg)
   108  	}
   109  }
   110  
   111  func expected(t *testing.T, test tests.Completion, items tests.CompletionItems) []protocol.CompletionItem {
   112  	t.Helper()
   113  
   114  	var want []protocol.CompletionItem
   115  	for _, pos := range test.CompletionItems {
   116  		item := items[pos]
   117  		want = append(want, tests.ToProtocolCompletionItem(*item))
   118  	}
   119  	return want
   120  }
   121  
   122  func (r *runner) callCompletion(t *testing.T, src span.Span, options func(*source.Options)) []protocol.CompletionItem {
   123  	t.Helper()
   124  
   125  	view, err := r.server.session.ViewOf(src.URI())
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	original := view.Options()
   130  	modified := view.Options().Clone()
   131  	options(modified)
   132  	view, err = view.SetOptions(r.ctx, modified)
   133  	if err != nil {
   134  		t.Error(err)
   135  		return nil
   136  	}
   137  	defer view.SetOptions(r.ctx, original)
   138  
   139  	list, err := r.server.Completion(r.ctx, &protocol.CompletionParams{
   140  		TextDocumentPositionParams: protocol.TextDocumentPositionParams{
   141  			TextDocument: protocol.TextDocumentIdentifier{
   142  				URI: protocol.URIFromSpanURI(src.URI()),
   143  			},
   144  			Position: protocol.Position{
   145  				Line:      uint32(src.Start().Line() - 1),
   146  				Character: uint32(src.Start().Column() - 1),
   147  			},
   148  		},
   149  	})
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  	return list.Items
   154  }