7992: improved completion sorting for functions and methods r=JoshMcguigan a=JoshMcguigan

This PR improves completion sorting for functions and methods. Related to #7935.

### Before

The methods are being sorted by `coc` by closeness in file. 

![pre-fn-relevance](https://user-images.githubusercontent.com/22216761/111018669-fe3d3f00-836e-11eb-9607-cc05af080a6a.png)

### After

Notice `bbb()` on top (type + name match), followed by `ddd()` (type match).

![image](https://user-images.githubusercontent.com/22216761/111018680-0e551e80-836f-11eb-94b1-c88336ecbc6e.png)


Co-authored-by: Josh Mcguigan <joshmcg88@gmail.com>
This commit is contained in:
bors[bot] 2021-03-15 15:53:15 +00:00 committed by GitHub
commit eec64ec01b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 1 deletions

View File

@ -927,6 +927,66 @@ fn f(foo: &Foo) { f(foo, w$0) }
);
}
#[test]
fn score_fn_type_and_name_match() {
check_relevance(
r#"
struct A { bar: u8 }
fn baz() -> u8 { 0 }
fn bar() -> u8 { 0 }
fn f() { A { bar: b$0 }; }
"#,
expect![[r#"
fn baz() [type]
st A []
fn bar() [type+name]
fn f() []
"#]],
);
}
#[test]
fn score_method_type_and_name_match() {
check_relevance(
r#"
fn baz(aaa: u32){}
struct Foo;
impl Foo {
fn aaa(&self) -> u32 { 0 }
fn bbb(&self) -> u32 { 0 }
fn ccc(&self) -> u64 { 0 }
}
fn f() {
baz(Foo.$0
}
"#,
expect![[r#"
me aaa() [type+name]
me bbb() [type]
me ccc() []
"#]],
);
}
#[test]
fn score_method_name_match_only() {
check_relevance(
r#"
fn baz(aaa: u32){}
struct Foo;
impl Foo {
fn aaa(&self) -> u64 { 0 }
}
fn f() {
baz(Foo.$0
}
"#,
expect![[r#"
me aaa() [name]
"#]],
);
}
#[test]
fn suggest_ref_mut() {
cov_mark::check!(suggest_ref);

View File

@ -5,7 +5,7 @@ use ide_db::SymbolKind;
use syntax::ast::Fn;
use crate::{
item::{CompletionItem, CompletionItemKind, CompletionKind, ImportEdit},
item::{CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, ImportEdit},
render::{builder_ext::Params, RenderContext},
};
@ -55,6 +55,21 @@ impl<'a> FunctionRender<'a> {
.add_call_parens(self.ctx.completion, self.name, params)
.add_import(import_to_add);
let mut relevance = CompletionRelevance::default();
if let Some(expected_type) = &self.ctx.completion.expected_type {
let ret_ty = self.func.ret_type(self.ctx.db());
// We don't ever consider a function which returns unit type to be an
// exact type match, since nearly always this is not meaningful to the
// user.
relevance.exact_type_match = &ret_ty == expected_type && !ret_ty.is_unit();
}
if let Some(expected_name) = &self.ctx.completion.expected_name {
relevance.exact_name_match =
expected_name == &self.func.name(self.ctx.db()).to_string();
}
item.set_relevance(relevance);
item.build()
}