Skip to content

Commit

Permalink
completion relevance distinguish between exact type match and could u…
Browse files Browse the repository at this point in the history
…nify
  • Loading branch information
JoshMcguigan committed Mar 23, 2021
1 parent 546f8bc commit e80e58c
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 41 deletions.
47 changes: 28 additions & 19 deletions crates/ide_completion/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl fmt::Debug for CompletionItem {
}
}

#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Default)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub struct CompletionRelevance {
/// This is set in cases like these:
///
Expand All @@ -143,24 +143,24 @@ pub struct CompletionRelevance {
/// f($0) // type of local matches the type of param
/// }
/// ```
pub exact_type_match: bool,
pub type_match: Option<CompletionRelevanceTypeMatch>,
/// This is set in cases like these:
///
/// ```
/// fn foo(bar: u32) {
/// $0 // `bar` is local
/// }
/// ```
///
/// ```
/// fn foo() {
/// let bar = 0;
/// $0 // `bar` is local
/// fn foo(a: u32) {
/// let b = 0;
/// $0 // `a` and `b` are local
/// }
/// ```
pub is_local: bool,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CompletionRelevanceTypeMatch {
CouldUnify,
Exact,
}

impl CompletionRelevance {
/// Provides a relevance score. Higher values are more relevant.
///
Expand All @@ -177,9 +177,11 @@ impl CompletionRelevance {
if self.exact_name_match {
score += 1;
}
if self.exact_type_match {
score += 3;
}
score += match self.type_match {
Some(CompletionRelevanceTypeMatch::Exact) => 4,
Some(CompletionRelevanceTypeMatch::CouldUnify) => 3,
None => 0,
};
if self.is_local {
score += 1;
}
Expand Down Expand Up @@ -342,7 +344,7 @@ impl CompletionItem {
// match, but with exact type match set because self.ref_match
// is only set if there is an exact type match.
let mut relevance = self.relevance;
relevance.exact_type_match = true;
relevance.type_match = Some(CompletionRelevanceTypeMatch::Exact);

self.ref_match.map(|mutability| (mutability, relevance))
}
Expand Down Expand Up @@ -523,7 +525,7 @@ mod tests {
use itertools::Itertools;
use test_utils::assert_eq_text;

use super::CompletionRelevance;
use super::{CompletionRelevance, CompletionRelevanceTypeMatch};

/// Check that these are CompletionRelevance are sorted in ascending order
/// by their relevance score.
Expand Down Expand Up @@ -576,15 +578,22 @@ mod tests {
is_local: true,
..CompletionRelevance::default()
}],
vec![CompletionRelevance { exact_type_match: true, ..CompletionRelevance::default() }],
vec![CompletionRelevance {
type_match: Some(CompletionRelevanceTypeMatch::CouldUnify),
..CompletionRelevance::default()
}],
vec![CompletionRelevance {
type_match: Some(CompletionRelevanceTypeMatch::Exact),
..CompletionRelevance::default()
}],
vec![CompletionRelevance {
exact_name_match: true,
exact_type_match: true,
type_match: Some(CompletionRelevanceTypeMatch::Exact),
..CompletionRelevance::default()
}],
vec![CompletionRelevance {
exact_name_match: true,
exact_type_match: true,
type_match: Some(CompletionRelevanceTypeMatch::Exact),
is_local: true,
}],
];
Expand Down
56 changes: 37 additions & 19 deletions crates/ide_completion/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use ide_db::{
use syntax::TextRange;

use crate::{
item::ImportEdit, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
CompletionRelevance,
item::{CompletionRelevanceTypeMatch, ImportEdit},
CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance,
};

use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro};
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a> Render<'a> {
.set_deprecated(is_deprecated);

item.set_relevance(CompletionRelevance {
exact_type_match: compute_exact_type_match(self.ctx.completion, ty),
type_match: compute_exact_type_match(self.ctx.completion, ty),
exact_name_match: compute_exact_name_match(self.ctx.completion, name.to_string()),
..CompletionRelevance::default()
});
Expand Down Expand Up @@ -243,7 +243,7 @@ impl<'a> Render<'a> {
}

item.set_relevance(CompletionRelevance {
exact_type_match: compute_exact_type_match(self.ctx.completion, &ty),
type_match: compute_exact_type_match(self.ctx.completion, &ty),
exact_name_match: compute_exact_name_match(self.ctx.completion, &local_name),
is_local: true,
..CompletionRelevance::default()
Expand Down Expand Up @@ -307,15 +307,24 @@ impl<'a> Render<'a> {
}
}

fn compute_exact_type_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> bool {
match ctx.expected_type.as_ref() {
Some(expected_type) => {
// We don't ever consider unit type to be an exact type match, since
// nearly always this is not meaningful to the user.
(completion_ty == expected_type || expected_type.could_unify_with(completion_ty))
&& !expected_type.is_unit()
}
None => false,
fn compute_exact_type_match(
ctx: &CompletionContext,
completion_ty: &hir::Type,
) -> Option<CompletionRelevanceTypeMatch> {
let expected_type = ctx.expected_type.as_ref()?;

// We don't ever consider unit type to be an exact type match, since
// nearly always this is not meaningful to the user.
if expected_type.is_unit() {
return None;
}

if completion_ty == expected_type {
Some(CompletionRelevanceTypeMatch::Exact)
} else if expected_type.could_unify_with(completion_ty) {
Some(CompletionRelevanceTypeMatch::CouldUnify)
} else {
None
}
}

Expand Down Expand Up @@ -347,6 +356,7 @@ mod tests {
use itertools::Itertools;

use crate::{
item::CompletionRelevanceTypeMatch,
test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
CompletionKind, CompletionRelevance,
};
Expand All @@ -359,7 +369,11 @@ mod tests {
fn check_relevance(ra_fixture: &str, expect: Expect) {
fn display_relevance(relevance: CompletionRelevance) -> String {
let relevance_factors = vec![
(relevance.exact_type_match, "type"),
(relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
(
relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
"type_could_unify",
),
(relevance.exact_name_match, "name"),
(relevance.is_local, "local"),
]
Expand Down Expand Up @@ -532,7 +546,9 @@ fn main() { let _: m::Spam = S$0 }
detail: "(i32)",
relevance: CompletionRelevance {
exact_name_match: false,
exact_type_match: true,
type_match: Some(
Exact,
),
is_local: false,
},
trigger_call_info: true,
Expand All @@ -558,7 +574,9 @@ fn main() { let _: m::Spam = S$0 }
detail: "()",
relevance: CompletionRelevance {
exact_name_match: false,
exact_type_match: true,
type_match: Some(
Exact,
),
is_local: false,
},
},
Expand Down Expand Up @@ -1107,7 +1125,7 @@ fn main() {
detail: "S",
relevance: CompletionRelevance {
exact_name_match: true,
exact_type_match: false,
type_match: None,
is_local: true,
},
ref_match: "&mut ",
Expand Down Expand Up @@ -1334,8 +1352,8 @@ fn foo() {
}
"#,
expect![[r#"
ev Foo::A(…) [type]
ev Foo::B [type]
ev Foo::A(…) [type_could_unify]
ev Foo::B [type_could_unify]
lc foo [type+local]
en Foo []
fn baz() []
Expand Down
2 changes: 1 addition & 1 deletion crates/ide_completion/src/render/enum_variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl<'a> EnumRender<'a> {

let ty = self.variant.parent_enum(self.ctx.completion.db).ty(self.ctx.completion.db);
item.set_relevance(CompletionRelevance {
exact_type_match: compute_exact_type_match(self.ctx.completion, &ty),
type_match: compute_exact_type_match(self.ctx.completion, &ty),
..CompletionRelevance::default()
});

Expand Down
2 changes: 1 addition & 1 deletion crates/ide_completion/src/render/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'a> FunctionRender<'a> {

let ret_type = self.func.ret_type(self.ctx.db());
item.set_relevance(CompletionRelevance {
exact_type_match: compute_exact_type_match(self.ctx.completion, &ret_type),
type_match: compute_exact_type_match(self.ctx.completion, &ret_type),
exact_name_match: compute_exact_name_match(self.ctx.completion, self.name.clone()),
..CompletionRelevance::default()
});
Expand Down
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/to_proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ mod tests {
(
"&arg",
Some(
"fffffffa",
"fffffff9",
),
),
(
Expand Down

0 comments on commit e80e58c

Please sign in to comment.