Skip to content

Implement server-side completion sorting and filtering #7935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
matklad opened this issue Mar 9, 2021 · 12 comments
Closed

Implement server-side completion sorting and filtering #7935

matklad opened this issue Mar 9, 2021 · 12 comments
Assignees
Labels
A-completion autocompletion C-enhancement Category: enhancement E-hard fun A technically challenging issue with high impact S-actionable Someone could pick this issue up and work on it right now

Comments

@matklad
Copy link
Member

matklad commented Mar 9, 2021

At the moment, we rely entirely on client-side sorting of completions. That's bad, and we should implement server side sorting. The big steps here are:

  • Design the API for composable completion item ordering
  • Implement the base version of this API
  • Hack LSP into accepting serve-provided completion order
  • Polish specific completion routines until the sort order is acceptable

Design

Each completion item should have a CompletionScore object. Scores are partially comparable. Score should record, precisely why we think this variant may be better than average and should return facts like "do the types align exactly?", "are we looking for a non-static function here", etc. I think it should be a bunch of bools. It currently is

pub enum CompletionScore { TypeMatch, TypeAndNameMatch }

I don't think that's the right repr.

After scores, we should implement fuzzy matching. We should look at the identifier being completed, and comput, for each CompletionItem, how good the match is, throwing away the completions which are not relevant.

Then, we should sort the final list, taking into account both the fuzzy score and CompletionScore (does it need a better name? MatchBits?)

Implementation

Fuzzy scoring needs to be implemented from scratch I think. Scores are partially there

LSP Hacking

LSP actually insists that the client does sorting&filtering, so we need to hack around that, see microsoft/language-server-protocol#898 for details. I believe we need to:

  • set isIncomplete to true
  • set sort text to format!("{04}", i) where i is our final order

Polishing

We produce a ton of garbage completions at the moment, so we should take care to actually design and use the appropriate scores.

@matklad matklad added E-hard fun A technically challenging issue with high impact S-actionable Someone could pick this issue up and work on it right now labels Mar 9, 2021
@matklad
Copy link
Member Author

matklad commented Mar 9, 2021

cc @SomeoneToIgnore

@SomeoneToIgnore
Copy link
Contributor

I was thinking on making a few benchmarks and maybe a few more path-handling improvements before even starting to think about this myself.

Should we also close #4544 ?

@matklad
Copy link
Member Author

matklad commented Mar 9, 2021

#7945 refactors some code, renaming CompletionScore to Relevance

@JoshMcguigan
Copy link
Contributor

Thanks for writing this up! I'll give this a shot 👍

It seems #7945 doesn't change that we don't sort type+name matches above just type matches. In the short term, is there a downside to taking the approach I proposed in #7904, which is to set the sortText for all items to some value [1, 3]?

I think long term we plan to be setting the value for sortText for all items anyway. So I think my question is partly, can this work be rolled out to users in stages, where stage 1 is the sorting and stage 2 is the filtering.

In stage 1 we could be building out lots of Relevance criteria, and it would be nice if during stage 1 we were setting sortText in such a way that users could see the improved sorting right away.

Then stage 2 would be filtering, where we'd do fuzzy matching and have to deal with the LSP Hacking you've described above (I'm still reading through the github issue linked there). Basically I can see the fuzzy matching and lsp hacking bringing on a whole other set of challenges, and it would be nice if we could avoid blocking the benefits of stage 1 behind the release of stage 2.

Does this seem feasible?

@matklad
Copy link
Member Author

matklad commented Mar 9, 2021 via email

@JoshMcguigan
Copy link
Contributor

I've updated #7904 (rebased since #7945 merged), which will fix the current sorting so type+name matches are above just type matches. I believe it will also serve as a reasonable base for continued work on building out improved relevance scoring.

bors bot added a commit that referenced this issue Mar 14, 2021
8014: increase completion relevance for items in local scope r=matklad a=JoshMcguigan

This PR provides a small completion relevance score bonus for items in local scope. The changes here are relatively minimal, since `coc` by default pre-sorts by position in file. But as we move toward fully server side sorting #7935 I think we'll want some relevance score bump for items in local scope. 

### Before

Note `let~` and `syntax` are both ahead of locals. Ultimately we may decide that `let~` is a high relevance completion given my cursor position here, but that should be done with some explicit scoring on the server side, rather than being caused by (I think) `coc` preferring shorter completions. 

![pre-local-score](https://user-images.githubusercontent.com/22216761/111073414-c97ad600-849b-11eb-84e7-fcee130536f0.png)

### After

![post-local-score](https://user-images.githubusercontent.com/22216761/111073422-d0094d80-849b-11eb-92ec-7ae5ec3b190d.png)


Co-authored-by: Josh Mcguigan <[email protected]>
@JoshMcguigan
Copy link
Contributor

See #7686 for an example of less than ideal sorting.

bors bot added a commit that referenced this issue Mar 15, 2021
7992: improved completion sorting for functions and methods r=JoshMcguigan a=JoshMcguigan

This PR improves completion sorting for functions and methods. Related to #7935.

### Before

The methods are being sorted by `coc` by closeness in file. 

![pre-fn-relevance](https://user-images.githubusercontent.com/22216761/111018669-fe3d3f00-836e-11eb-9607-cc05af080a6a.png)

### After

Notice `bbb()` on top (type + name match), followed by `ddd()` (type match).

![image](https://user-images.githubusercontent.com/22216761/111018680-0e551e80-836f-11eb-94b1-c88336ecbc6e.png)


Co-authored-by: Josh Mcguigan <[email protected]>
@fannheyward
Copy link
Contributor

Each completion item should have a CompletionScore object

clangd has this: https://clangd.llvm.org/extensions.html#code-completion-scores

@jonas-schievink
Copy link
Contributor

Triage: We now have a CompletionRelevance struct, compute a score from that, and set the LSP sortText accordingly. Is there anything left to do or can this be closed?

@matklad
Copy link
Member Author

matklad commented Apr 11, 2022

I think the crucial think we still don't do is the fuzzy matching of what the user has typed with the identifier we want to complete. That is, I belive current scorring completley ignores edit distance (double check me). Makes sense to open a separate issue for that maybe?

@matklad
Copy link
Member Author

matklad commented Sep 18, 2022

#13124 shows an interesting use-case for this: sometimes (bindgen mostly) the amount of symbols we want to complete is humongous, which actually creates performance problems. So, ideally, we include a pre-filtering step: not only we want to sort & cull completions after we build the whole list, but, even while we are producing completions, we should keep only the 1000s best according to fuzzy matching (computing just the label for fuzzy matching is much cheaper than rendering the whole completion item).

@Veykril
Copy link
Member

Veykril commented Feb 15, 2023

Closing this in favor of #14158 and #14159

@Veykril Veykril closed this as completed Feb 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-completion autocompletion C-enhancement Category: enhancement E-hard fun A technically challenging issue with high impact S-actionable Someone could pick this issue up and work on it right now
Projects
None yet
Development

No branches or pull requests

6 participants