increase completion relevance for items in local scope

This commit is contained in:
Josh Mcguigan 2021-03-13 06:13:30 -08:00
parent f57e2f5598
commit ba924d04b3
3 changed files with 88 additions and 32 deletions

View file

@ -144,6 +144,21 @@ pub struct CompletionRelevance {
/// } /// }
/// ``` /// ```
pub exact_type_match: bool, pub exact_type_match: bool,
/// This is set in cases like these:
///
/// ```
/// fn foo(bar: u32) {
/// $0 // `bar` is local
/// }
/// ```
///
/// ```
/// fn foo() {
/// let bar = 0;
/// $0 // `bar` is local
/// }
/// ```
pub is_local: bool,
} }
impl CompletionRelevance { impl CompletionRelevance {
@ -163,6 +178,9 @@ impl CompletionRelevance {
score += 1; score += 1;
} }
if self.exact_type_match { if self.exact_type_match {
score += 3;
}
if self.is_local {
score += 1; score += 1;
} }
@ -551,9 +569,24 @@ mod tests {
vec![CompletionRelevance::default()], vec![CompletionRelevance::default()],
vec![ vec![
CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() }, CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() },
CompletionRelevance { exact_type_match: true, ..CompletionRelevance::default() }, CompletionRelevance { is_local: true, ..CompletionRelevance::default() },
], ],
vec![CompletionRelevance { exact_name_match: true, exact_type_match: true }], vec![CompletionRelevance {
exact_name_match: true,
is_local: true,
..CompletionRelevance::default()
}],
vec![CompletionRelevance { exact_type_match: true, ..CompletionRelevance::default() }],
vec![CompletionRelevance {
exact_name_match: true,
exact_type_match: true,
..CompletionRelevance::default()
}],
vec![CompletionRelevance {
exact_name_match: true,
exact_type_match: true,
is_local: true,
}],
]; ];
check_relevance_score_ordered(expected_relevance_order); check_relevance_score_ordered(expected_relevance_order);

View file

@ -157,9 +157,7 @@ impl<'a> Render<'a> {
.set_documentation(field.docs(self.ctx.db())) .set_documentation(field.docs(self.ctx.db()))
.set_deprecated(is_deprecated); .set_deprecated(is_deprecated);
if let Some(relevance) = compute_relevance(&self.ctx, &ty, &name.to_string()) { item.set_relevance(compute_relevance(&self.ctx, &ty, &name.to_string()));
item.set_relevance(relevance);
}
item.build() item.build()
} }
@ -254,9 +252,9 @@ impl<'a> Render<'a> {
if let ScopeDef::Local(local) = resolution { if let ScopeDef::Local(local) = resolution {
let ty = local.ty(self.ctx.db()); let ty = local.ty(self.ctx.db());
if let Some(relevance) = compute_relevance(&self.ctx, &ty, &local_name) { let mut relevance = compute_relevance(&self.ctx, &ty, &local_name);
relevance.is_local = true;
item.set_relevance(relevance); item.set_relevance(relevance);
}
if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() { if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() {
if ty != expected_type { if ty != expected_type {
@ -328,12 +326,15 @@ impl<'a> Render<'a> {
} }
} }
fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> Option<CompletionRelevance> { fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> CompletionRelevance {
let (expected_name, expected_type) = ctx.expected_name_and_type()?;
let mut res = CompletionRelevance::default(); let mut res = CompletionRelevance::default();
if let Some((expected_name, expected_type)) = ctx.expected_name_and_type() {
res.exact_type_match = ty == &expected_type; res.exact_type_match = ty == &expected_type;
res.exact_name_match = name == &expected_name; res.exact_name_match = name == &expected_name;
Some(res) }
res
} }
fn relevance_type_match(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -> bool { fn relevance_type_match(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -> bool {
@ -343,6 +344,7 @@ fn relevance_type_match(db: &dyn HirDatabase, ty: &Type, expected_type: &Type) -
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use expect_test::{expect, Expect}; use expect_test::{expect, Expect};
use itertools::Itertools;
use crate::{ use crate::{
test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG}, test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
@ -355,15 +357,17 @@ mod tests {
} }
fn check_relevance(ra_fixture: &str, expect: Expect) { fn check_relevance(ra_fixture: &str, expect: Expect) {
fn display_relevance(relevance: CompletionRelevance) -> &'static str { fn display_relevance(relevance: CompletionRelevance) -> String {
match relevance { let relevance_factors = vec![
CompletionRelevance { exact_type_match: true, exact_name_match: true } => { (relevance.exact_type_match, "type"),
"[type+name]" (relevance.exact_name_match, "name"),
} (relevance.is_local, "local"),
CompletionRelevance { exact_type_match: true, exact_name_match: false } => "[type]", ]
CompletionRelevance { exact_type_match: false, exact_name_match: true } => "[name]", .into_iter()
CompletionRelevance { exact_type_match: false, exact_name_match: false } => "[]", .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
} .join("+");
format!("[{}]", relevance_factors)
} }
let actual = get_all_items(TEST_CONFIG, ra_fixture) let actual = get_all_items(TEST_CONFIG, ra_fixture)
@ -918,7 +922,7 @@ struct WorldSnapshot { _f: () };
fn go(world: &WorldSnapshot) { go(w$0) } fn go(world: &WorldSnapshot) { go(w$0) }
"#, "#,
expect![[r#" expect![[r#"
lc world [type+name] lc world [type+name+local]
st WorldSnapshot [] st WorldSnapshot []
fn go() [] fn go() []
"#]], "#]],
@ -933,7 +937,7 @@ struct Foo;
fn f(foo: &Foo) { f(foo, w$0) } fn f(foo: &Foo) { f(foo, w$0) }
"#, "#,
expect![[r#" expect![[r#"
lc foo [] lc foo [local]
st Foo [] st Foo []
fn f() [] fn f() []
"#]], "#]],
@ -998,6 +1002,7 @@ fn main() {
relevance: CompletionRelevance { relevance: CompletionRelevance {
exact_name_match: true, exact_name_match: true,
exact_type_match: false, exact_type_match: false,
is_local: true,
}, },
ref_match: "&mut ", ref_match: "&mut ",
}, },
@ -1037,9 +1042,9 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
lc m [] lc m [local]
lc t [] lc t [local]
lc &t [type] lc &t [type+local]
st T [] st T []
st S [] st S []
fn main() [] fn main() []
@ -1091,9 +1096,9 @@ fn main() {
} }
"#, "#,
expect![[r#" expect![[r#"
lc m [] lc m [local]
lc t [] lc t [local]
lc &mut t [type] lc &mut t [type+local]
tt DerefMut [] tt DerefMut []
tt Deref [] tt Deref []
fn foo() [] fn foo() []
@ -1103,4 +1108,22 @@ fn main() {
"#]], "#]],
) )
} }
#[test]
fn locals() {
check_relevance(
r#"
fn foo(bar: u32) {
let baz = 0;
f$0
}
"#,
expect![[r#"
lc baz [local]
lc bar [local]
fn foo() []
"#]],
);
}
} }

View file

@ -1117,13 +1117,13 @@ mod tests {
( (
"&arg", "&arg",
Some( Some(
"fffffffd", "fffffffa",
), ),
), ),
( (
"arg", "arg",
Some( Some(
"fffffffe", "fffffffd",
), ),
), ),
] ]