feat: completion list suggests constructor like & builder methods first
This commit is contained in:
parent
3770f73bd6
commit
24a3c42bd6
@ -166,6 +166,8 @@ pub struct CompletionRelevance {
|
|||||||
pub postfix_match: Option<CompletionRelevancePostfixMatch>,
|
pub postfix_match: Option<CompletionRelevancePostfixMatch>,
|
||||||
/// This is set for type inference results
|
/// This is set for type inference results
|
||||||
pub is_definite: bool,
|
pub is_definite: bool,
|
||||||
|
/// This is set for items that are function (associated or method)
|
||||||
|
pub function: Option<CompletionRelevanceFn>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
@ -207,6 +209,24 @@ pub enum CompletionRelevancePostfixMatch {
|
|||||||
Exact,
|
Exact,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub struct CompletionRelevanceFn {
|
||||||
|
pub has_args: bool,
|
||||||
|
pub has_self_arg: bool,
|
||||||
|
pub return_type: CompletionRelevanceReturnType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub enum CompletionRelevanceReturnType {
|
||||||
|
Other,
|
||||||
|
/// Returns the Self type of the impl/trait
|
||||||
|
DirectConstructor,
|
||||||
|
/// Returns something that indirectly constructs the `Self` type of the impl/trait e.g. `Result<Self, ()>`, `Option<Self>`
|
||||||
|
Constructor,
|
||||||
|
/// Returns a possible builder for the type
|
||||||
|
Builder,
|
||||||
|
}
|
||||||
|
|
||||||
impl CompletionRelevance {
|
impl CompletionRelevance {
|
||||||
/// Provides a relevance score. Higher values are more relevant.
|
/// Provides a relevance score. Higher values are more relevant.
|
||||||
///
|
///
|
||||||
@ -231,6 +251,7 @@ impl CompletionRelevance {
|
|||||||
postfix_match,
|
postfix_match,
|
||||||
is_definite,
|
is_definite,
|
||||||
is_item_from_notable_trait,
|
is_item_from_notable_trait,
|
||||||
|
function,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// lower rank private things
|
// lower rank private things
|
||||||
@ -275,6 +296,33 @@ impl CompletionRelevance {
|
|||||||
if is_definite {
|
if is_definite {
|
||||||
score += 10;
|
score += 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
score += function
|
||||||
|
.map(|asf| {
|
||||||
|
let mut fn_score = match asf.return_type {
|
||||||
|
CompletionRelevanceReturnType::DirectConstructor => 15,
|
||||||
|
CompletionRelevanceReturnType::Builder => 10,
|
||||||
|
CompletionRelevanceReturnType::Constructor => 5,
|
||||||
|
CompletionRelevanceReturnType::Other => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// When a fn is bumped due to return type:
|
||||||
|
// Bump Constructor or Builder methods with no arguments,
|
||||||
|
// over them tha with self arguments
|
||||||
|
if fn_score > 0 {
|
||||||
|
if !asf.has_args {
|
||||||
|
// bump associated functions
|
||||||
|
fn_score += 1;
|
||||||
|
} else if asf.has_self_arg {
|
||||||
|
// downgrade methods (below Constructor)
|
||||||
|
fn_score = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_score
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
score
|
score
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,6 +675,16 @@ mod tests {
|
|||||||
expect.assert_debug_eq(&actual);
|
expect.assert_debug_eq(&actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn check_function_relevance(ra_fixture: &str, expect: Expect) {
|
||||||
|
let actual: Vec<_> = do_completion(ra_fixture, CompletionItemKind::Method)
|
||||||
|
.into_iter()
|
||||||
|
.map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
expect.assert_debug_eq(&actual);
|
||||||
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
|
fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
|
||||||
let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
|
let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
|
||||||
@ -1254,6 +1264,7 @@ fn main() { let _: m::Spam = S$0 }
|
|||||||
is_private_editable: false,
|
is_private_editable: false,
|
||||||
postfix_match: None,
|
postfix_match: None,
|
||||||
is_definite: false,
|
is_definite: false,
|
||||||
|
function: None,
|
||||||
},
|
},
|
||||||
trigger_call_info: true,
|
trigger_call_info: true,
|
||||||
},
|
},
|
||||||
@ -1281,6 +1292,7 @@ fn main() { let _: m::Spam = S$0 }
|
|||||||
is_private_editable: false,
|
is_private_editable: false,
|
||||||
postfix_match: None,
|
postfix_match: None,
|
||||||
is_definite: false,
|
is_definite: false,
|
||||||
|
function: None,
|
||||||
},
|
},
|
||||||
trigger_call_info: true,
|
trigger_call_info: true,
|
||||||
},
|
},
|
||||||
@ -1360,6 +1372,7 @@ fn foo() { A { the$0 } }
|
|||||||
is_private_editable: false,
|
is_private_editable: false,
|
||||||
postfix_match: None,
|
postfix_match: None,
|
||||||
is_definite: false,
|
is_definite: false,
|
||||||
|
function: None,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -1393,6 +1406,26 @@ impl S {
|
|||||||
documentation: Documentation(
|
documentation: Documentation(
|
||||||
"Method docs",
|
"Method docs",
|
||||||
),
|
),
|
||||||
|
relevance: CompletionRelevance {
|
||||||
|
exact_name_match: false,
|
||||||
|
type_match: None,
|
||||||
|
is_local: false,
|
||||||
|
is_item_from_trait: false,
|
||||||
|
is_item_from_notable_trait: false,
|
||||||
|
is_name_already_imported: false,
|
||||||
|
requires_import: false,
|
||||||
|
is_op_method: false,
|
||||||
|
is_private_editable: false,
|
||||||
|
postfix_match: None,
|
||||||
|
is_definite: false,
|
||||||
|
function: Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
CompletionItem {
|
CompletionItem {
|
||||||
label: "foo",
|
label: "foo",
|
||||||
@ -1498,6 +1531,26 @@ fn foo(s: S) { s.$0 }
|
|||||||
kind: Method,
|
kind: Method,
|
||||||
lookup: "the_method",
|
lookup: "the_method",
|
||||||
detail: "fn(&self)",
|
detail: "fn(&self)",
|
||||||
|
relevance: CompletionRelevance {
|
||||||
|
exact_name_match: false,
|
||||||
|
type_match: None,
|
||||||
|
is_local: false,
|
||||||
|
is_item_from_trait: false,
|
||||||
|
is_item_from_notable_trait: false,
|
||||||
|
is_name_already_imported: false,
|
||||||
|
requires_import: false,
|
||||||
|
is_op_method: false,
|
||||||
|
is_private_editable: false,
|
||||||
|
postfix_match: None,
|
||||||
|
is_definite: false,
|
||||||
|
function: Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
"#]],
|
"#]],
|
||||||
@ -2098,6 +2151,254 @@ fn main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn constructor_order_simple() {
|
||||||
|
check_relevance(
|
||||||
|
r#"
|
||||||
|
struct Foo;
|
||||||
|
struct Other;
|
||||||
|
struct Option<T>(T);
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn fn_ctr() -> Foo { unimplemented!() }
|
||||||
|
fn fn_another(n: u32) -> Other { unimplemented!() }
|
||||||
|
fn fn_ctr_self() -> Option<Self> { unimplemented!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let a = Foo::$0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
fn fn_ctr() [type_could_unify]
|
||||||
|
fn fn_ctr_self() [type_could_unify]
|
||||||
|
fn fn_another(…) [type_could_unify]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn constructor_order_kind() {
|
||||||
|
check_function_relevance(
|
||||||
|
r#"
|
||||||
|
struct Foo;
|
||||||
|
struct Bar;
|
||||||
|
struct Option<T>(T);
|
||||||
|
enum Result<T, E> { Ok(T), Err(E) };
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn fn_ctr(&self) -> Foo { unimplemented!() }
|
||||||
|
fn fn_ctr_with_args(&self, n: u32) -> Foo { unimplemented!() }
|
||||||
|
fn fn_another(&self, n: u32) -> Bar { unimplemented!() }
|
||||||
|
fn fn_ctr_wrapped(&self, ) -> Option<Self> { unimplemented!() }
|
||||||
|
fn fn_ctr_wrapped_2(&self, ) -> Result<Self, Bar> { unimplemented!() }
|
||||||
|
fn fn_ctr_wrapped_3(&self, ) -> Result<Bar, Self> { unimplemented!() } // Self is not the first type
|
||||||
|
fn fn_ctr_wrapped_with_args(&self, m: u32) -> Option<Self> { unimplemented!() }
|
||||||
|
fn fn_another_unit(&self) { unimplemented!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let a = self::Foo::$0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"fn(&self, u32) -> Bar",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self)",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self) -> Foo",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: DirectConstructor,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self, u32) -> Foo",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: DirectConstructor,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self) -> Option<Foo>",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Constructor,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self) -> Result<Foo, Bar>",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Constructor,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self) -> Result<Bar, Foo>",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Constructor,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"fn(&self, u32) -> Option<Foo>",
|
||||||
|
Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Constructor,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn constructor_order_relevance() {
|
||||||
|
check_relevance(
|
||||||
|
r#"
|
||||||
|
struct Foo;
|
||||||
|
struct FooBuilder;
|
||||||
|
struct Result<T>(T);
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn fn_no_ret(&self) {}
|
||||||
|
fn fn_ctr_with_args(input: u32) -> Foo { unimplemented!() }
|
||||||
|
fn fn_direct_ctr() -> Self { unimplemented!() }
|
||||||
|
fn fn_ctr() -> Result<Self> { unimplemented!() }
|
||||||
|
fn fn_other() -> Result<u32> { unimplemented!() }
|
||||||
|
fn fn_builder() -> FooBuilder { unimplemented!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let a = self::Foo::$0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
// preference:
|
||||||
|
// Direct Constructor
|
||||||
|
// Direct Constructor with args
|
||||||
|
// Builder
|
||||||
|
// Constructor
|
||||||
|
// Others
|
||||||
|
expect![[r#"
|
||||||
|
fn fn_direct_ctr() [type_could_unify]
|
||||||
|
fn fn_ctr_with_args(…) [type_could_unify]
|
||||||
|
fn fn_builder() [type_could_unify]
|
||||||
|
fn fn_ctr() [type_could_unify]
|
||||||
|
me fn_no_ret(…) [type_could_unify]
|
||||||
|
fn fn_other() [type_could_unify]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_relevance_generic_1() {
|
||||||
|
check_relevance(
|
||||||
|
r#"
|
||||||
|
struct Foo<T: Default>(T);
|
||||||
|
struct FooBuilder;
|
||||||
|
struct Option<T>(T);
|
||||||
|
enum Result<T, E>{Ok(T), Err(E)};
|
||||||
|
|
||||||
|
impl<T: Default> Foo<T> {
|
||||||
|
fn fn_returns_unit(&self) {}
|
||||||
|
fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
|
||||||
|
fn fn_direct_ctr() -> Self { unimplemented!() }
|
||||||
|
fn fn_ctr_wrapped() -> Option<Self> { unimplemented!() }
|
||||||
|
fn fn_ctr_wrapped_2() -> Result<Self, u32> { unimplemented!() }
|
||||||
|
fn fn_other() -> Option<u32> { unimplemented!() }
|
||||||
|
fn fn_builder() -> FooBuilder { unimplemented!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let a = self::Foo::<u32>::$0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
fn fn_direct_ctr() [type_could_unify]
|
||||||
|
fn fn_ctr_with_args(…) [type_could_unify]
|
||||||
|
fn fn_builder() [type_could_unify]
|
||||||
|
fn fn_ctr_wrapped() [type_could_unify]
|
||||||
|
fn fn_ctr_wrapped_2() [type_could_unify]
|
||||||
|
me fn_returns_unit(…) [type_could_unify]
|
||||||
|
fn fn_other() [type_could_unify]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn function_relevance_generic_2() {
|
||||||
|
// Generic 2
|
||||||
|
check_relevance(
|
||||||
|
r#"
|
||||||
|
struct Foo<T: Default>(T);
|
||||||
|
struct FooBuilder;
|
||||||
|
struct Option<T>(T);
|
||||||
|
enum Result<T, E>{Ok(T), Err(E)};
|
||||||
|
|
||||||
|
impl<T: Default> Foo<T> {
|
||||||
|
fn fn_no_ret(&self) {}
|
||||||
|
fn fn_ctr_with_args(input: T) -> Foo<T> { unimplemented!() }
|
||||||
|
fn fn_direct_ctr() -> Self { unimplemented!() }
|
||||||
|
fn fn_ctr() -> Option<Self> { unimplemented!() }
|
||||||
|
fn fn_ctr2() -> Result<Self, u32> { unimplemented!() }
|
||||||
|
fn fn_other() -> Option<u32> { unimplemented!() }
|
||||||
|
fn fn_builder() -> FooBuilder { unimplemented!() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
let a : Res<Foo<u32>> = Foo::$0;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
fn fn_direct_ctr() [type_could_unify]
|
||||||
|
fn fn_ctr_with_args(…) [type_could_unify]
|
||||||
|
fn fn_builder() [type_could_unify]
|
||||||
|
fn fn_ctr() [type_could_unify]
|
||||||
|
fn fn_ctr2() [type_could_unify]
|
||||||
|
me fn_no_ret(…) [type_could_unify]
|
||||||
|
fn fn_other() [type_could_unify]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn struct_field_method_ref() {
|
fn struct_field_method_ref() {
|
||||||
check_kinds(
|
check_kinds(
|
||||||
@ -2118,6 +2419,26 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
|
|||||||
kind: Method,
|
kind: Method,
|
||||||
lookup: "baz",
|
lookup: "baz",
|
||||||
detail: "fn(&self) -> u32",
|
detail: "fn(&self) -> u32",
|
||||||
|
relevance: CompletionRelevance {
|
||||||
|
exact_name_match: false,
|
||||||
|
type_match: None,
|
||||||
|
is_local: false,
|
||||||
|
is_item_from_trait: false,
|
||||||
|
is_item_from_notable_trait: false,
|
||||||
|
is_name_already_imported: false,
|
||||||
|
requires_import: false,
|
||||||
|
is_op_method: false,
|
||||||
|
is_private_editable: false,
|
||||||
|
postfix_match: None,
|
||||||
|
is_definite: false,
|
||||||
|
function: Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
ref_match: "&@107",
|
ref_match: "&@107",
|
||||||
},
|
},
|
||||||
CompletionItem {
|
CompletionItem {
|
||||||
@ -2192,6 +2513,7 @@ fn foo() {
|
|||||||
is_private_editable: false,
|
is_private_editable: false,
|
||||||
postfix_match: None,
|
postfix_match: None,
|
||||||
is_definite: false,
|
is_definite: false,
|
||||||
|
function: None,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -2229,6 +2551,26 @@ fn main() {
|
|||||||
),
|
),
|
||||||
lookup: "foo",
|
lookup: "foo",
|
||||||
detail: "fn() -> S",
|
detail: "fn() -> S",
|
||||||
|
relevance: CompletionRelevance {
|
||||||
|
exact_name_match: false,
|
||||||
|
type_match: None,
|
||||||
|
is_local: false,
|
||||||
|
is_item_from_trait: false,
|
||||||
|
is_item_from_notable_trait: false,
|
||||||
|
is_name_already_imported: false,
|
||||||
|
requires_import: false,
|
||||||
|
is_op_method: false,
|
||||||
|
is_private_editable: false,
|
||||||
|
postfix_match: None,
|
||||||
|
is_definite: false,
|
||||||
|
function: Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: false,
|
||||||
|
has_self_arg: false,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
ref_match: "&@92",
|
ref_match: "&@92",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -2590,6 +2932,13 @@ fn main() {
|
|||||||
is_private_editable: false,
|
is_private_editable: false,
|
||||||
postfix_match: None,
|
postfix_match: None,
|
||||||
is_definite: false,
|
is_definite: false,
|
||||||
|
function: Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CompletionItem {
|
CompletionItem {
|
||||||
@ -2612,6 +2961,13 @@ fn main() {
|
|||||||
is_private_editable: false,
|
is_private_editable: false,
|
||||||
postfix_match: None,
|
postfix_match: None,
|
||||||
is_definite: false,
|
is_definite: false,
|
||||||
|
function: Some(
|
||||||
|
CompletionRelevanceFn {
|
||||||
|
has_args: true,
|
||||||
|
has_self_arg: true,
|
||||||
|
return_type: Other,
|
||||||
|
},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -8,8 +8,13 @@ use syntax::{format_smolstr, AstNode, SmolStr};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind},
|
context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind},
|
||||||
item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
|
item::{
|
||||||
render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext},
|
Builder, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevanceFn,
|
||||||
|
CompletionRelevanceReturnType,
|
||||||
|
},
|
||||||
|
render::{
|
||||||
|
compute_exact_name_match, compute_ref_match, compute_type_match, match_types, RenderContext,
|
||||||
|
},
|
||||||
CallableSnippets,
|
CallableSnippets,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,13 +104,20 @@ fn render(
|
|||||||
.filter(|_| !has_call_parens)
|
.filter(|_| !has_call_parens)
|
||||||
.and_then(|cap| Some((cap, params(ctx.completion, func, &func_kind, has_dot_receiver)?)));
|
.and_then(|cap| Some((cap, params(ctx.completion, func, &func_kind, has_dot_receiver)?)));
|
||||||
|
|
||||||
|
let type_match = if has_call_parens || complete_call_parens.is_some() {
|
||||||
|
compute_type_match(completion, &ret_type)
|
||||||
|
} else {
|
||||||
|
compute_type_match(completion, &func.ty(db))
|
||||||
|
};
|
||||||
|
|
||||||
|
let function = assoc_item
|
||||||
|
.and_then(|assoc_item| assoc_item.implementing_ty(db))
|
||||||
|
.and_then(|self_type| compute_function_match(db, &ctx, self_type, func, &ret_type));
|
||||||
|
|
||||||
item.set_relevance(CompletionRelevance {
|
item.set_relevance(CompletionRelevance {
|
||||||
type_match: if has_call_parens || complete_call_parens.is_some() {
|
type_match,
|
||||||
compute_type_match(completion, &ret_type)
|
|
||||||
} else {
|
|
||||||
compute_type_match(completion, &func.ty(db))
|
|
||||||
},
|
|
||||||
exact_name_match: compute_exact_name_match(completion, &call),
|
exact_name_match: compute_exact_name_match(completion, &call),
|
||||||
|
function,
|
||||||
is_op_method,
|
is_op_method,
|
||||||
is_item_from_notable_trait,
|
is_item_from_notable_trait,
|
||||||
..ctx.completion_relevance()
|
..ctx.completion_relevance()
|
||||||
@ -156,6 +168,39 @@ fn render(
|
|||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compute_function_match(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
ctx: &RenderContext<'_>,
|
||||||
|
self_type: hir::Type,
|
||||||
|
func: hir::Function,
|
||||||
|
func_return_type: &hir::Type,
|
||||||
|
) -> Option<CompletionRelevanceFn> {
|
||||||
|
let has_args = func.num_params(db) > 0;
|
||||||
|
let has_self_arg = func.self_param(db).is_some();
|
||||||
|
|
||||||
|
let return_type = if match_types(ctx.completion, &self_type, &func_return_type).is_some() {
|
||||||
|
// fn([..]) -> Self
|
||||||
|
CompletionRelevanceReturnType::DirectConstructor
|
||||||
|
} else if func_return_type
|
||||||
|
.type_arguments()
|
||||||
|
.any(|ret_type_arg| match_types(ctx.completion, &self_type, &ret_type_arg).is_some())
|
||||||
|
{
|
||||||
|
// fn([..]) -> Result<Self, E> OR Wrapped<Foo, Self>
|
||||||
|
CompletionRelevanceReturnType::Constructor
|
||||||
|
} else if func_return_type
|
||||||
|
.as_adt()
|
||||||
|
.and_then(|adt| adt.name(db).as_str().map(|name| name.ends_with("Builder")))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
// fn([..]) -> [..]Builder
|
||||||
|
CompletionRelevanceReturnType::Builder
|
||||||
|
} else {
|
||||||
|
CompletionRelevanceReturnType::Other
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(CompletionRelevanceFn { return_type, has_args, has_self_arg })
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn add_call_parens<'b>(
|
pub(super) fn add_call_parens<'b>(
|
||||||
builder: &'b mut Builder,
|
builder: &'b mut Builder,
|
||||||
ctx: &CompletionContext<'_>,
|
ctx: &CompletionContext<'_>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user