mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
increase completion relevance for items in local scope
This commit is contained in:
parent
f57e2f5598
commit
ba924d04b3
3 changed files with 88 additions and 32 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
item.set_relevance(relevance);
|
relevance.is_local = true;
|
||||||
}
|
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();
|
||||||
res.exact_type_match = ty == &expected_type;
|
|
||||||
res.exact_name_match = name == &expected_name;
|
if let Some((expected_name, expected_type)) = ctx.expected_name_and_type() {
|
||||||
Some(res)
|
res.exact_type_match = ty == &expected_type;
|
||||||
|
res.exact_name_match = name == &expected_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(…) []
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1117,13 +1117,13 @@ mod tests {
|
||||||
(
|
(
|
||||||
"&arg",
|
"&arg",
|
||||||
Some(
|
Some(
|
||||||
"fffffffd",
|
"fffffffa",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"arg",
|
"arg",
|
||||||
Some(
|
Some(
|
||||||
"fffffffe",
|
"fffffffd",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue