From 212fb13d595e5faf79425c78ae101012873a81a1 Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Thu, 27 Jun 2019 16:28:22 -0400 Subject: [PATCH] internal/lsp: match completions case-insensitively Change-Id: I31f2ea338ae3e2ec2837a444705f990e140ebc77 Reviewed-on: https://go-review.googlesource.com/c/tools/+/184159 Run-TryBot: Rebecca Stambler TryBot-Result: Gobot Gobot Reviewed-by: Ian Cottrell --- internal/lsp/completion.go | 9 +++++++-- internal/lsp/source/source_test.go | 10 +++++----- internal/lsp/testdata/errors/errors.go | 5 +++++ internal/lsp/tests/tests.go | 2 +- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index 3fc75b53..affa8da4 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -67,16 +67,21 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara const maxDeepCompletions = 3 func toProtocolCompletionItems(candidates []source.CompletionItem, prefix string, rng protocol.Range, insertTextFormat protocol.InsertTextFormat, usePlaceholders bool, useDeepCompletions bool) []protocol.CompletionItem { + // Sort the candidates by score, since that is not supported by LSP yet. sort.SliceStable(candidates, func(i, j int) bool { return candidates[i].Score > candidates[j].Score }) + + // Matching against the prefix should be case insensitive. + prefix = strings.ToLower(prefix) + var ( items = make([]protocol.CompletionItem, 0, len(candidates)) numDeepCompletionsSeen int ) for i, candidate := range candidates { - // Match against the label. - if !strings.HasPrefix(candidate.Label, prefix) { + // Match against the label (case-insensitive). + if !strings.HasPrefix(strings.ToLower(candidate.Label), prefix) { continue } diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index 9d212021..1f82eeda 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -152,19 +152,19 @@ func (r *runner) Completion(t *testing.T, data tests.Completions, snippets tests if err != nil { t.Fatalf("failed for %v: %v", src, err) } + var prefix string + if surrounding != nil { + prefix = strings.ToLower(surrounding.Prefix()) + } wantBuiltins := strings.Contains(string(src.URI()), "builtins") var got []source.CompletionItem for _, item := range list { if !wantBuiltins && isBuiltin(item) { continue } - var prefix string - if surrounding != nil { - prefix = surrounding.Prefix() - } // We let the client do fuzzy matching, so we return all possible candidates. // To simplify testing, filter results with prefixes that don't match exactly. - if !strings.HasPrefix(item.Label, prefix) { + if !strings.HasPrefix(strings.ToLower(item.Label), prefix) { continue } got = append(got, item) diff --git a/internal/lsp/testdata/errors/errors.go b/internal/lsp/testdata/errors/errors.go index 3de1f632..42105629 100644 --- a/internal/lsp/testdata/errors/errors.go +++ b/internal/lsp/testdata/errors/errors.go @@ -1,5 +1,10 @@ package errors +import ( + "golang.org/x/tools/internal/lsp/types" +) + func _() { bob.Bob() //@complete(".") + types.b //@complete(" //", Bob_interface) } diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index da06a384..34a581ba 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -25,7 +25,7 @@ import ( // We hardcode the expected number of test cases to ensure that all tests // are being executed. If a test is added, this number must be changed. const ( - ExpectedCompletionsCount = 136 + ExpectedCompletionsCount = 137 ExpectedCompletionSnippetCount = 15 ExpectedDiagnosticsCount = 17 ExpectedFormatCount = 5