Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/ide-completion/src/item.rs | 7 | ||||
| -rw-r--r-- | crates/ide-completion/src/render.rs | 78 |
2 files changed, 83 insertions, 2 deletions
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index e6dd1d37d9..62211a808c 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -184,6 +184,8 @@ pub struct CompletionRelevance { pub function: Option<CompletionRelevanceFn>, /// true when there is an `await.method()` or `iter().method()` completion. pub is_skipping_completion: bool, + /// if inherent impl already exists in current module, user may not want to implement it again. + pub has_local_inherent_impl: bool, } #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct CompletionRelevanceTraitInfo { @@ -275,6 +277,7 @@ impl CompletionRelevance { trait_, function, is_skipping_completion, + has_local_inherent_impl, } = self; // only applicable for completions within use items @@ -347,6 +350,10 @@ impl CompletionRelevance { score += fn_score; }; + if has_local_inherent_impl { + score -= 5; + } + score } diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index b6da6fba63..3b9d75b15f 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -10,7 +10,7 @@ pub(crate) mod type_alias; pub(crate) mod union_literal; pub(crate) mod variant; -use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type}; +use hir::{AsAssocItem, HasAttrs, HirDisplay, Impl, ModuleDef, ScopeDef, Type}; use ide_db::text_edit::TextEdit; use ide_db::{ RootDatabase, SnippetCap, SymbolKind, @@ -23,7 +23,9 @@ use syntax::{AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr, ast, format_smo use crate::{ CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode, CompletionRelevance, - context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext}, + context::{ + DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext, TypeLocation, + }, item::{Builder, CompletionRelevanceTypeMatch}, render::{ function::render_fn, @@ -422,6 +424,7 @@ fn render_resolution_path( } let completion = ctx.completion; + let module = completion.module; let cap = ctx.snippet_cap(); let db = completion.db; let config = completion.config; @@ -466,6 +469,7 @@ fn render_resolution_path( exact_name_match: compute_exact_name_match(completion, &name), is_local: matches!(resolution, ScopeDef::Local(_)), requires_import, + has_local_inherent_impl: compute_has_local_inherent_impl(db, path_ctx, &ty, module), ..CompletionRelevance::default() }); @@ -660,6 +664,18 @@ fn compute_type_match( match_types(ctx, expected_type, completion_ty) } +fn compute_has_local_inherent_impl( + db: &RootDatabase, + path_ctx: &PathCompletionCtx<'_>, + completion_ty: &hir::Type<'_>, + curr_module: hir::Module, +) -> bool { + matches!(path_ctx.kind, PathKind::Type { location: TypeLocation::ImplTarget }) + && Impl::all_for_type(db, completion_ty.clone()) + .iter() + .any(|imp| imp.trait_(db).is_none() && imp.module(db) == curr_module) +} + fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool { ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name) } @@ -832,6 +848,7 @@ mod tests { ), (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"), (relevance.requires_import, "requires_import"), + (relevance.has_local_inherent_impl, "has_local_inherent_impl"), ] .into_iter() .filter_map(|(cond, desc)| if cond { Some(desc) } else { None }) @@ -1214,6 +1231,7 @@ fn main() { Foo::Fo$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, trigger_call_info: true, }, @@ -1264,6 +1282,7 @@ fn main() { Foo::Fo$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, trigger_call_info: true, }, @@ -1407,6 +1426,7 @@ fn main() { Foo::Fo$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, trigger_call_info: true, }, @@ -1490,6 +1510,7 @@ fn main() { let _: m::Spam = S$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, trigger_call_info: true, }, @@ -1526,6 +1547,7 @@ fn main() { let _: m::Spam = S$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, trigger_call_info: true, }, @@ -1616,6 +1638,7 @@ fn foo() { A { the$0 } } postfix_match: None, function: None, is_skipping_completion: false, + has_local_inherent_impl: false, }, }, ] @@ -1675,6 +1698,7 @@ impl S { }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, }, CompletionItem { @@ -1766,6 +1790,7 @@ use self::E::*; }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, trigger_call_info: true, }, @@ -1836,6 +1861,7 @@ fn foo(s: S) { s.$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, }, ] @@ -2048,6 +2074,7 @@ fn f() -> i32 { postfix_match: None, function: None, is_skipping_completion: false, + has_local_inherent_impl: false, }, }, ] @@ -2194,6 +2221,48 @@ fn f() { } #[test] + fn score_has_local_inherent_impl() { + check_relevance( + r#" +trait Foob {} +struct Fooa {} +impl Fooa {} + +impl Foo$0 +"#, + expect![[r#" + tt Foob [] + st Fooa Fooa [has_local_inherent_impl] + "#]], + ); + + // inherent impl in different modules, not trigger `has_local_inherent_impl` + check_relevance( + r#" +trait Foob {} +struct Fooa {} + +mod a { + use super::*; + impl Fooa {} +} + +mod b { + use super::*; + impl Foo$0 +} + +"#, + expect![[r#" + st Fooa Fooa [] + tt Foob [] + md a [] + md b [] + "#]], + ); + } + + #[test] fn test_avoid_redundant_suggestion() { check_relevance( r#" @@ -2861,6 +2930,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 } }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, ref_match: "&@107", }, @@ -2948,6 +3018,7 @@ fn foo() { postfix_match: None, function: None, is_skipping_completion: false, + has_local_inherent_impl: false, }, }, ] @@ -3006,6 +3077,7 @@ fn main() { }, ), is_skipping_completion: false, + has_local_inherent_impl: false, }, ref_match: "&@92", }, @@ -3476,6 +3548,7 @@ fn main() { postfix_match: None, function: None, is_skipping_completion: false, + has_local_inherent_impl: false, }, }, CompletionItem { @@ -3510,6 +3583,7 @@ fn main() { postfix_match: None, function: None, is_skipping_completion: false, + has_local_inherent_impl: false, }, }, ] |