1
0
mirror of https://github.com/golang/go synced 2024-09-30 18:18:32 -06:00

internal/lsp: fix VSCode's reordering of completion candidates

When VSCode applies its own fuzzy matching/filtering/ranking logic to
completion candidates, it can end up reordering and even omitting some
of our candidates. It is mainly a problem with deep completions (i.e.
VSCode downranks or completely hides deep completion candidates that
should be ranked at the top).

We now trick VSCode into not reordering our candidates by setting each
candidate's "filterText" to the completion prefix. This makes every
candidate look like an identically perfect match, so VSCode just
maintains the order specified by "sortText".

Note that we don't do this trick if server side fuzzy matching and
deep completions are disabled. In this case unimpeded client side
candidate filtering is necessary.

Change-Id: I677047bca12b9ce05a953016d0d89182f1fe44d6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/202717
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Muir Manders 2019-10-22 21:16:21 -07:00 committed by Rebecca Stambler
parent 9525425c6f
commit 79994da4ae

View File

@ -43,11 +43,29 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara
sort.SliceStable(candidates, func(i, j int) bool {
return candidates[i].Score > candidates[j].Score
})
// When using deep completions/fuzzy matching, report results as incomplete so
// client fetches updated completions after every key stroke.
incompleteResults := options.Completion.Deep || options.Completion.FuzzyMatching
items := toProtocolCompletionItems(candidates, rng, options)
if incompleteResults {
prefix := surrounding.Prefix()
for i := range items {
// We send the prefix as the filterText to trick VSCode into not
// reordering our candidates. All the candidates will appear to
// be a perfect match, so VSCode's fuzzy matching/ranking just
// maintains the natural "sortText" ordering. We can only do
// this in tandem with "incompleteResults" since otherwise
// client side filtering is important.
items[i].FilterText = prefix
}
}
return &protocol.CompletionList{
// When using deep completions/fuzzy matching, report results as incomplete so
// client fetches updated completions after every key stroke.
IsIncomplete: options.Completion.Deep || options.Completion.FuzzyMatching,
Items: toProtocolCompletionItems(candidates, rng, options),
IsIncomplete: incompleteResults,
Items: items,
}, nil
}