}
}
-#[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:
///
/// }
/// ```
pub exact_name_match: bool,
+ /// See CompletionRelevanceTypeMatch doc comments for cases where this is set.
+ pub type_match: Option<CompletionRelevanceTypeMatch>,
/// This is set in cases like these:
///
/// ```
- /// fn f(spam: String) {}
- /// fn main {
- /// let foo = String::new();
- /// f($0) // type of local matches the type of param
+ /// fn foo(a: u32) {
+ /// let b = 0;
+ /// $0 // `a` and `b` are local
/// }
/// ```
- pub exact_type_match: bool,
+ pub is_local: bool,
+}
+
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub enum CompletionRelevanceTypeMatch {
/// This is set in cases like these:
///
/// ```
- /// fn foo(bar: u32) {
- /// $0 // `bar` is local
+ /// enum Option<T> { Some(T), None }
+ /// fn f(a: Option<u32>) {}
+ /// fn main {
+ /// f(Option::N$0) // type `Option<T>` could unify with `Option<u32>`
/// }
/// ```
+ CouldUnify,
+ /// This is set in cases like these:
///
/// ```
- /// fn foo() {
- /// let bar = 0;
- /// $0 // `bar` is local
+ /// fn f(spam: String) {}
+ /// fn main {
+ /// let foo = String::new();
+ /// f($0) // type of local matches the type of param
/// }
/// ```
- pub is_local: bool,
+ Exact,
}
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;
}
// 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))
}
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.
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,
}],
];
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};
.set_deprecated(is_deprecated);
item.set_relevance(CompletionRelevance {
- exact_type_match: compute_exact_type_match(self.ctx.completion, ty),
+ type_match: compute_type_match(self.ctx.completion, ty),
exact_name_match: compute_exact_name_match(self.ctx.completion, name.to_string()),
..CompletionRelevance::default()
});
}
item.set_relevance(CompletionRelevance {
- exact_type_match: compute_exact_type_match(self.ctx.completion, &ty),
+ type_match: compute_type_match(self.ctx.completion, &ty),
exact_name_match: compute_exact_name_match(self.ctx.completion, &local_name),
is_local: true,
..CompletionRelevance::default()
}
}
-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_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
}
}
use itertools::Itertools;
use crate::{
+ item::CompletionRelevanceTypeMatch,
test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
CompletionKind, CompletionRelevance,
};
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"),
]
detail: "(i32)",
relevance: CompletionRelevance {
exact_name_match: false,
- exact_type_match: true,
+ type_match: Some(
+ Exact,
+ ),
is_local: false,
},
trigger_call_info: true,
detail: "()",
relevance: CompletionRelevance {
exact_name_match: false,
- exact_type_match: true,
+ type_match: Some(
+ Exact,
+ ),
is_local: false,
},
},
detail: "S",
relevance: CompletionRelevance {
exact_name_match: true,
- exact_type_match: false,
+ type_match: None,
is_local: true,
},
ref_match: "&mut ",
}
"#,
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() []
use crate::{
item::{CompletionItem, CompletionKind, ImportEdit},
- render::{builder_ext::Params, compute_exact_type_match, compute_ref_match, RenderContext},
+ render::{builder_ext::Params, compute_ref_match, compute_type_match, RenderContext},
CompletionRelevance,
};
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_type_match(self.ctx.completion, &ty),
..CompletionRelevance::default()
});
use crate::{
item::{CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, ImportEdit},
render::{
- builder_ext::Params, compute_exact_name_match, compute_exact_type_match, compute_ref_match,
+ builder_ext::Params, compute_exact_name_match, compute_ref_match, compute_type_match,
RenderContext,
},
};
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_type_match(self.ctx.completion, &ret_type),
exact_name_match: compute_exact_name_match(self.ctx.completion, self.name.clone()),
..CompletionRelevance::default()
});
(
"&arg",
Some(
- "fffffffa",
+ "fffffff9",
),
),
(