editor: Handle more completion sort cases (#30690)
Adds 3 more test cases where local variable should be preferred over method, and local method over library methods. Before / After: <img height="280" alt="before-rust" src="https://github.com/user-attachments/assets/72b34ce8-89ff-4c2b-87dc-9e63f855d31e" /> <img height="280" alt="after-rust" src="https://github.com/user-attachments/assets/8e23c9ca-576c-4dc5-8946-fa37554a19e0" /> Before / After: <img height="280" alt="before-react" src="https://github.com/user-attachments/assets/f7070413-e397-441a-a0c1-16d8ce25aa12" /> <img height="280" alt="after-react" src="https://github.com/user-attachments/assets/7a095954-7844-4a3e-bf59-5420b7ffdb03" /> Release Notes: - N/A
This commit is contained in:
parent
d01559f9bc
commit
78d3ce4090
3 changed files with 552 additions and 166 deletions
File diff suppressed because it is too large
Load diff
|
@ -664,12 +664,13 @@ impl CompletionsMenu {
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
enum MatchTier<'a> {
|
enum MatchTier<'a> {
|
||||||
WordStartMatch {
|
WordStartMatch {
|
||||||
sort_prefix: Reverse<usize>,
|
sort_mixed_case_prefix_length: Reverse<usize>,
|
||||||
sort_fuzzy_bracket: Reverse<usize>,
|
|
||||||
sort_snippet: Reverse<i32>,
|
sort_snippet: Reverse<i32>,
|
||||||
|
sort_kind: usize,
|
||||||
|
sort_fuzzy_bracket: Reverse<usize>,
|
||||||
sort_text: Option<&'a str>,
|
sort_text: Option<&'a str>,
|
||||||
sort_score: Reverse<OrderedFloat<f64>>,
|
sort_score: Reverse<OrderedFloat<f64>>,
|
||||||
sort_key: (usize, &'a str),
|
sort_label: &'a str,
|
||||||
},
|
},
|
||||||
OtherMatch {
|
OtherMatch {
|
||||||
sort_score: Reverse<OrderedFloat<f64>>,
|
sort_score: Reverse<OrderedFloat<f64>>,
|
||||||
|
@ -680,12 +681,12 @@ impl CompletionsMenu {
|
||||||
// balance the raw fuzzy match score with hints from the language server
|
// balance the raw fuzzy match score with hints from the language server
|
||||||
|
|
||||||
// In a fuzzy bracket, matches with a score of 1.0 are prioritized.
|
// In a fuzzy bracket, matches with a score of 1.0 are prioritized.
|
||||||
// The remaining matches are partitioned into two groups at 2/3 of the max_score.
|
// The remaining matches are partitioned into two groups at 3/5 of the max_score.
|
||||||
let max_score = matches
|
let max_score = matches
|
||||||
.iter()
|
.iter()
|
||||||
.map(|mat| mat.string_match.score)
|
.map(|mat| mat.string_match.score)
|
||||||
.fold(0.0, f64::max);
|
.fold(0.0, f64::max);
|
||||||
let second_bracket_threshold = max_score * (2.0 / 3.0);
|
let fuzzy_bracket_threshold = max_score * (3.0 / 5.0);
|
||||||
|
|
||||||
let query_start_lower = query
|
let query_start_lower = query
|
||||||
.and_then(|q| q.chars().next())
|
.and_then(|q| q.chars().next())
|
||||||
|
@ -709,9 +710,7 @@ impl CompletionsMenu {
|
||||||
if query_start_doesnt_match_split_words {
|
if query_start_doesnt_match_split_words {
|
||||||
MatchTier::OtherMatch { sort_score }
|
MatchTier::OtherMatch { sort_score }
|
||||||
} else {
|
} else {
|
||||||
let sort_fuzzy_bracket = Reverse(if score == 1.0 {
|
let sort_fuzzy_bracket = Reverse(if score >= fuzzy_bracket_threshold {
|
||||||
2
|
|
||||||
} else if score >= second_bracket_threshold {
|
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -721,7 +720,7 @@ impl CompletionsMenu {
|
||||||
SnippetSortOrder::Bottom => Reverse(if mat.is_snippet { 0 } else { 1 }),
|
SnippetSortOrder::Bottom => Reverse(if mat.is_snippet { 0 } else { 1 }),
|
||||||
SnippetSortOrder::Inline => Reverse(0),
|
SnippetSortOrder::Inline => Reverse(0),
|
||||||
};
|
};
|
||||||
let mixed_case_prefix_length = Reverse(
|
let sort_mixed_case_prefix_length = Reverse(
|
||||||
query
|
query
|
||||||
.map(|q| {
|
.map(|q| {
|
||||||
q.chars()
|
q.chars()
|
||||||
|
@ -741,12 +740,13 @@ impl CompletionsMenu {
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
);
|
);
|
||||||
MatchTier::WordStartMatch {
|
MatchTier::WordStartMatch {
|
||||||
sort_prefix: mixed_case_prefix_length,
|
sort_mixed_case_prefix_length,
|
||||||
sort_fuzzy_bracket,
|
|
||||||
sort_snippet,
|
sort_snippet,
|
||||||
|
sort_kind: mat.sort_kind,
|
||||||
|
sort_fuzzy_bracket,
|
||||||
sort_text: mat.sort_text,
|
sort_text: mat.sort_text,
|
||||||
sort_score,
|
sort_score,
|
||||||
sort_key: mat.sort_key,
|
sort_label: mat.sort_label,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -797,13 +797,14 @@ impl CompletionsMenu {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let sort_key = completion.sort_key();
|
let (sort_kind, sort_label) = completion.sort_key();
|
||||||
|
|
||||||
SortableMatch {
|
SortableMatch {
|
||||||
string_match,
|
string_match,
|
||||||
is_snippet,
|
is_snippet,
|
||||||
sort_text,
|
sort_text,
|
||||||
sort_key,
|
sort_kind,
|
||||||
|
sort_label,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -828,7 +829,8 @@ pub struct SortableMatch<'a> {
|
||||||
pub string_match: StringMatch,
|
pub string_match: StringMatch,
|
||||||
pub is_snippet: bool,
|
pub is_snippet: bool,
|
||||||
pub sort_text: Option<&'a str>,
|
pub sort_text: Option<&'a str>,
|
||||||
pub sort_key: (usize, &'a str),
|
pub sort_kind: usize,
|
||||||
|
pub sort_label: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -47,7 +47,9 @@ extend-exclude = [
|
||||||
# Eval examples for prompts and criteria
|
# Eval examples for prompts and criteria
|
||||||
"crates/eval/src/examples/",
|
"crates/eval/src/examples/",
|
||||||
# typos-cli doesn't understand our `vˇariable` markup
|
# typos-cli doesn't understand our `vˇariable` markup
|
||||||
"crates/editor/src/hover_links.rs"
|
"crates/editor/src/hover_links.rs",
|
||||||
|
# typos-cli doesn't understand `setis` is intentional test case
|
||||||
|
"crates/editor/src/code_completion_tests.rs"
|
||||||
]
|
]
|
||||||
|
|
||||||
[default]
|
[default]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue