editor: Improve fuzzy match bucket logic for code completions (#29442)

Add new test and improve fuzzy match bucket logic which results into far
better balance between LSP and fuzzy search.

Before:
<img width="500" alt="before"
src="https://github.com/user-attachments/assets/3e8900a6-c0ff-4f37-b88e-b0e3783b7e9a"
/>

After:
<img width="500" alt="after"
src="https://github.com/user-attachments/assets/738c074c-d446-4697-aac6-9814362e88db"
/>

Release Notes:

- N/A
This commit is contained in:
Smit Barmase 2025-04-26 02:14:18 +05:30 committed by GitHub
parent 8b910e1cd9
commit 3961d87ae0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 160 additions and 7 deletions

View file

@ -671,7 +671,7 @@ impl CompletionsMenu {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum MatchTier<'a> {
WordStartMatch {
sort_score_int: Reverse<i32>,
sort_bucket: Reverse<i32>,
sort_snippet: Reverse<i32>,
sort_text: Option<&'a str>,
sort_key: (usize, &'a str),
@ -684,11 +684,9 @@ impl CompletionsMenu {
// Our goal here is to intelligently sort completion suggestions. We want to
// balance the raw fuzzy match score with hints from the language server
//
// We first primary sort using fuzzy score by putting matches into two buckets
// strong one and weak one. Among these buckets matches are then compared by
// We first primary sort using fuzzy score by putting matches into multiple
// buckets. Among these buckets matches are then compared by
// various criteria like snippet, LSP hints, kind, label text etc.
//
const FUZZY_THRESHOLD: f64 = 0.1317;
let query_start_lower = query
.and_then(|q| q.chars().next())
@ -712,14 +710,20 @@ impl CompletionsMenu {
let sort_score = Reverse(OrderedFloat(score));
MatchTier::OtherMatch { sort_score }
} else {
let sort_score_int = Reverse(if score >= FUZZY_THRESHOLD { 1 } else { 0 });
// Convert fuzzy match score (0.0-1.0) to a priority bucket (0-3)
let sort_bucket = Reverse(match (score * 10.0).floor() as i32 {
s if s >= 7 => 3,
s if s >= 1 => 2,
s if s > 0 => 1,
_ => 0,
});
let sort_snippet = match snippet_sort_order {
SnippetSortOrder::Top => Reverse(if mat.is_snippet { 1 } else { 0 }),
SnippetSortOrder::Bottom => Reverse(if mat.is_snippet { 0 } else { 1 }),
SnippetSortOrder::Inline => Reverse(0),
};
MatchTier::WordStartMatch {
sort_score_int,
sort_bucket,
sort_snippet,
sort_text: mat.sort_text,
sort_key: mat.sort_key,