aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion
diff options
context:
space:
mode:
authorJosh Mcguigan <[email protected]>2021-03-12 03:11:14 +0000
committerJosh Mcguigan <[email protected]>2021-03-12 14:16:01 +0000
commit3679821eea94f30f2582ea7bca7569dad3ca31be (patch)
tree99edbd24d1d5da54af0e3f177cb18719b7880bda /crates/ide_completion
parentc0e9530fd095317563532c20f13959619515c9b2 (diff)
add completion relevance score
Diffstat (limited to 'crates/ide_completion')
-rw-r--r--crates/ide_completion/src/item.rs55
-rw-r--r--crates/ide_completion/src/lib.rs4
-rw-r--r--crates/ide_completion/src/render.rs22
3 files changed, 58 insertions, 23 deletions
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index cf1aaa131..9a4dc915c 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -70,7 +70,7 @@ pub struct CompletionItem {
70 /// Note that Relevance ignores fuzzy match score. We compute Relevance for 70 /// Note that Relevance ignores fuzzy match score. We compute Relevance for
71 /// all possible items, and then separately build an ordered completion list 71 /// all possible items, and then separately build an ordered completion list
72 /// based on relevance and fuzzy matching with the already typed identifier. 72 /// based on relevance and fuzzy matching with the already typed identifier.
73 relevance: Relevance, 73 relevance: CompletionRelevance,
74 74
75 /// Indicates that a reference or mutable reference to this variable is a 75 /// Indicates that a reference or mutable reference to this variable is a
76 /// possible match. 76 /// possible match.
@@ -107,9 +107,11 @@ impl fmt::Debug for CompletionItem {
107 if self.deprecated { 107 if self.deprecated {
108 s.field("deprecated", &true); 108 s.field("deprecated", &true);
109 } 109 }
110 if self.relevance.is_relevant() { 110
111 if self.relevance != CompletionRelevance::default() {
111 s.field("relevance", &self.relevance); 112 s.field("relevance", &self.relevance);
112 } 113 }
114
113 if let Some(mutability) = &self.ref_match { 115 if let Some(mutability) = &self.ref_match {
114 s.field("ref_match", &format!("&{}", mutability.as_keyword_for_ref())); 116 s.field("ref_match", &format!("&{}", mutability.as_keyword_for_ref()));
115 } 117 }
@@ -129,7 +131,7 @@ pub enum CompletionScore {
129} 131}
130 132
131#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)] 133#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)]
132pub struct Relevance { 134pub struct CompletionRelevance {
133 /// This is set in cases like these: 135 /// This is set in cases like these:
134 /// 136 ///
135 /// ``` 137 /// ```
@@ -152,9 +154,34 @@ pub struct Relevance {
152 pub exact_type_match: bool, 154 pub exact_type_match: bool,
153} 155}
154 156
155impl Relevance { 157impl CompletionRelevance {
158 /// Provides a relevance score. Higher values are more relevant.
159 ///
160 /// The absolute value of the relevance score is not meaningful, for
161 /// example a value of 0 doesn't mean "not relevant", rather
162 /// it means "least relevant". The score value should only be used
163 /// for relative ordering.
164 ///
165 /// See is_relevant if you need to make some judgement about score
166 /// in an absolute sense.
167 pub fn score(&self) -> u8 {
168 let mut score = 0;
169
170 if self.exact_name_match {
171 score += 1;
172 }
173 if self.exact_type_match {
174 score += 1;
175 }
176
177 score
178 }
179
180 /// Returns true when the score for this threshold is above
181 /// some threshold such that we think it is especially likely
182 /// to be relevant.
156 pub fn is_relevant(&self) -> bool { 183 pub fn is_relevant(&self) -> bool {
157 self != &Relevance::default() 184 self.score() > 0
158 } 185 }
159} 186}
160 187
@@ -249,7 +276,7 @@ impl CompletionItem {
249 text_edit: None, 276 text_edit: None,
250 deprecated: false, 277 deprecated: false,
251 trigger_call_info: None, 278 trigger_call_info: None,
252 relevance: Relevance::default(), 279 relevance: CompletionRelevance::default(),
253 ref_match: None, 280 ref_match: None,
254 import_to_add: None, 281 import_to_add: None,
255 } 282 }
@@ -292,7 +319,7 @@ impl CompletionItem {
292 self.deprecated 319 self.deprecated
293 } 320 }
294 321
295 pub fn relevance(&self) -> Relevance { 322 pub fn relevance(&self) -> CompletionRelevance {
296 self.relevance 323 self.relevance
297 } 324 }
298 325
@@ -300,8 +327,14 @@ impl CompletionItem {
300 self.trigger_call_info 327 self.trigger_call_info
301 } 328 }
302 329
303 pub fn ref_match(&self) -> Option<Mutability> { 330 pub fn ref_match(&self) -> Option<(Mutability, CompletionRelevance)> {
304 self.ref_match 331 // Relevance of the ref match should be the same as the original
332 // match, but with exact type match set because self.ref_match
333 // is only set if there is an exact type match.
334 let mut relevance = self.relevance;
335 relevance.exact_type_match = true;
336
337 self.ref_match.map(|mutability| (mutability, relevance))
305 } 338 }
306 339
307 pub fn import_to_add(&self) -> Option<&ImportEdit> { 340 pub fn import_to_add(&self) -> Option<&ImportEdit> {
@@ -349,7 +382,7 @@ pub(crate) struct Builder {
349 text_edit: Option<TextEdit>, 382 text_edit: Option<TextEdit>,
350 deprecated: bool, 383 deprecated: bool,
351 trigger_call_info: Option<bool>, 384 trigger_call_info: Option<bool>,
352 relevance: Relevance, 385 relevance: CompletionRelevance,
353 ref_match: Option<Mutability>, 386 ref_match: Option<Mutability>,
354} 387}
355 388
@@ -457,7 +490,7 @@ impl Builder {
457 self.deprecated = deprecated; 490 self.deprecated = deprecated;
458 self 491 self
459 } 492 }
460 pub(crate) fn set_relevance(&mut self, relevance: Relevance) -> &mut Builder { 493 pub(crate) fn set_relevance(&mut self, relevance: CompletionRelevance) -> &mut Builder {
461 self.relevance = relevance; 494 self.relevance = relevance;
462 self 495 self
463 } 496 }
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index d46f521a0..21e489755 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -24,8 +24,8 @@ use crate::{completions::Completions, context::CompletionContext, item::Completi
24pub use crate::{ 24pub use crate::{
25 config::CompletionConfig, 25 config::CompletionConfig,
26 item::{ 26 item::{
27 CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat, 27 CompletionItem, CompletionItemKind, CompletionRelevance, CompletionScore, ImportEdit,
28 Relevance, 28 InsertTextFormat,
29 }, 29 },
30}; 30};
31 31
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index f7f9084d9..db31896e5 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -20,7 +20,7 @@ use ide_db::{
20use syntax::TextRange; 20use syntax::TextRange;
21 21
22use crate::{ 22use crate::{
23 item::{ImportEdit, Relevance}, 23 item::{CompletionRelevance, ImportEdit},
24 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, 24 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
25}; 25};
26 26
@@ -322,9 +322,9 @@ impl<'a> Render<'a> {
322 } 322 }
323} 323}
324 324
325fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<Relevance> { 325fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionRelevance> {
326 let (expected_name, expected_type) = ctx.expected_name_and_type()?; 326 let (expected_name, expected_type) = ctx.expected_name_and_type()?;
327 let mut res = Relevance::default(); 327 let mut res = CompletionRelevance::default();
328 res.exact_type_match = ty == &expected_type; 328 res.exact_type_match = ty == &expected_type;
329 res.exact_name_match = name == &expected_name; 329 res.exact_name_match = name == &expected_name;
330 Some(res) 330 Some(res)
@@ -338,7 +338,7 @@ mod tests {
338 338
339 use crate::{ 339 use crate::{
340 test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG}, 340 test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
341 CompletionKind, Relevance, 341 CompletionKind, CompletionRelevance,
342 }; 342 };
343 343
344 fn check(ra_fixture: &str, expect: Expect) { 344 fn check(ra_fixture: &str, expect: Expect) {
@@ -347,12 +347,14 @@ mod tests {
347 } 347 }
348 348
349 fn check_relevance(ra_fixture: &str, expect: Expect) { 349 fn check_relevance(ra_fixture: &str, expect: Expect) {
350 fn display_relevance(relevance: Relevance) -> &'static str { 350 fn display_relevance(relevance: CompletionRelevance) -> &'static str {
351 match relevance { 351 match relevance {
352 Relevance { exact_type_match: true, exact_name_match: true } => "[type+name]", 352 CompletionRelevance { exact_type_match: true, exact_name_match: true } => {
353 Relevance { exact_type_match: true, exact_name_match: false } => "[type]", 353 "[type+name]"
354 Relevance { exact_type_match: false, exact_name_match: true } => "[name]", 354 }
355 Relevance { exact_type_match: false, exact_name_match: false } => "[]", 355 CompletionRelevance { exact_type_match: true, exact_name_match: false } => "[type]",
356 CompletionRelevance { exact_type_match: false, exact_name_match: true } => "[name]",
357 CompletionRelevance { exact_type_match: false, exact_name_match: false } => "[]",
356 } 358 }
357 } 359 }
358 360
@@ -975,7 +977,7 @@ fn main() {
975 Local, 977 Local,
976 ), 978 ),
977 detail: "S", 979 detail: "S",
978 relevance: Relevance { 980 relevance: CompletionRelevance {
979 exact_name_match: true, 981 exact_name_match: true,
980 exact_type_match: false, 982 exact_type_match: false,
981 }, 983 },