mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Improve sorting of completion results (#7727)
This is an attempt to fix #5013 by doing two things: 1. Rank "obvious" matches in completions higher (see the code comment) 2. When tied: rank keywords higher than variables Release Notes: - Improved sorting of completion results to prefer literal matches. ([#5013](https://github.com/zed-industries/zed/issues/5013)). ### Before ![screenshot-2024-02-13-13 08 13@2x](https://github.com/zed-industries/zed/assets/1185253/77decb0b-5b47-45de-ab69-f7b333072b45) ![screenshot-2024-02-13-13 10 42@2x](https://github.com/zed-industries/zed/assets/1185253/ae33d0fe-06f5-4fc1-84f8-ddf6dbe80ba5) ### After ![screenshot-2024-02-13-13 06 22@2x](https://github.com/zed-industries/zed/assets/1185253/3c526bab-6392-4eeb-a2f2-dd73ccf228e8) ![screenshot-2024-02-13-13 06 50@2x](https://github.com/zed-industries/zed/assets/1185253/b5b9d513-766d-4a53-94de-b46271f5978c) Co-authored-by: Antonio <antonio@zed.dev> Co-authored-by: bennetbo <bennetbo@gmx.de>
This commit is contained in:
parent
98fff014da
commit
798c9a7d8b
@ -1017,12 +1017,53 @@ impl CompletionsMenu {
|
||||
|
||||
let completions = self.completions.read();
|
||||
matches.sort_unstable_by_key(|mat| {
|
||||
// We do want to strike a balance here between what the language server tells us
|
||||
// to sort by (the sort_text) and what are "obvious" good matches (i.e. when you type
|
||||
// `Creat` and there is a local variable called `CreateComponent`).
|
||||
// So what we do is: we bucket all matches into two buckets
|
||||
// - Strong matches
|
||||
// - Weak matches
|
||||
// Strong matches are the ones with a high fuzzy-matcher score (the "obvious" matches)
|
||||
// and the Weak matches are the rest.
|
||||
//
|
||||
// For the strong matches, we sort by the language-servers score first and for the weak
|
||||
// matches, we prefer our fuzzy finder first.
|
||||
//
|
||||
// The thinking behind that: it's useless to take the sort_text the language-server gives
|
||||
// us into account when it's obviously a bad match.
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MatchScore<'a> {
|
||||
Strong {
|
||||
sort_text: Option<&'a str>,
|
||||
score: Reverse<OrderedFloat<f64>>,
|
||||
sort_key: (usize, &'a str),
|
||||
},
|
||||
Weak {
|
||||
score: Reverse<OrderedFloat<f64>>,
|
||||
sort_text: Option<&'a str>,
|
||||
sort_key: (usize, &'a str),
|
||||
},
|
||||
}
|
||||
|
||||
let completion = &completions[mat.candidate_id];
|
||||
(
|
||||
completion.lsp_completion.sort_text.as_ref(),
|
||||
Reverse(OrderedFloat(mat.score)),
|
||||
completion.sort_key(),
|
||||
)
|
||||
let sort_key = completion.sort_key();
|
||||
let sort_text = completion.lsp_completion.sort_text.as_deref();
|
||||
let score = Reverse(OrderedFloat(mat.score));
|
||||
|
||||
if mat.score >= 0.2 {
|
||||
MatchScore::Strong {
|
||||
sort_text,
|
||||
score,
|
||||
sort_key,
|
||||
}
|
||||
} else {
|
||||
MatchScore::Weak {
|
||||
score,
|
||||
sort_text,
|
||||
sort_key,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for mat in &mut matches {
|
||||
|
@ -3441,8 +3441,9 @@ impl Completion {
|
||||
/// them to the user.
|
||||
pub fn sort_key(&self) -> (usize, &str) {
|
||||
let kind_key = match self.lsp_completion.kind {
|
||||
Some(lsp::CompletionItemKind::VARIABLE) => 0,
|
||||
_ => 1,
|
||||
Some(lsp::CompletionItemKind::KEYWORD) => 0,
|
||||
Some(lsp::CompletionItemKind::VARIABLE) => 1,
|
||||
_ => 2,
|
||||
};
|
||||
(kind_key, &self.label.text[self.label.filter_range.clone()])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user