Skip to content

Commit d13247a

Browse files
committed
Added a field has_local_inherent_impl to CompletionRelevance.
1 parent 8800504 commit d13247a

2 files changed

Lines changed: 83 additions & 2 deletions

File tree

crates/ide-completion/src/item.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ pub struct CompletionRelevance {
184184
pub function: Option<CompletionRelevanceFn>,
185185
/// true when there is an `await.method()` or `iter().method()` completion.
186186
pub is_skipping_completion: bool,
187+
/// if inherent impl already exists in current module, user may not want to implement it again.
188+
pub has_local_inherent_impl: bool,
187189
}
188190
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
189191
pub struct CompletionRelevanceTraitInfo {
@@ -275,6 +277,7 @@ impl CompletionRelevance {
275277
trait_,
276278
function,
277279
is_skipping_completion,
280+
has_local_inherent_impl,
278281
} = self;
279282

280283
// only applicable for completions within use items
@@ -347,6 +350,10 @@ impl CompletionRelevance {
347350
score += fn_score;
348351
};
349352

353+
if has_local_inherent_impl {
354+
score -= 5;
355+
}
356+
350357
score
351358
}
352359

crates/ide-completion/src/render.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub(crate) mod type_alias;
1010
pub(crate) mod union_literal;
1111
pub(crate) mod variant;
1212

13-
use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type};
13+
use hir::{AsAssocItem, HasAttrs, HirDisplay, Impl, ModuleDef, ScopeDef, Type};
1414
use ide_db::text_edit::TextEdit;
1515
use ide_db::{
1616
RootDatabase, SnippetCap, SymbolKind,
@@ -23,7 +23,9 @@ use syntax::{AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr, ast, format_smo
2323
use crate::{
2424
CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode,
2525
CompletionRelevance,
26-
context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext},
26+
context::{
27+
DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext, TypeLocation,
28+
},
2729
item::{Builder, CompletionRelevanceTypeMatch},
2830
render::{
2931
function::render_fn,
@@ -422,6 +424,7 @@ fn render_resolution_path(
422424
}
423425

424426
let completion = ctx.completion;
427+
let module = completion.module;
425428
let cap = ctx.snippet_cap();
426429
let db = completion.db;
427430
let config = completion.config;
@@ -466,6 +469,7 @@ fn render_resolution_path(
466469
exact_name_match: compute_exact_name_match(completion, &name),
467470
is_local: matches!(resolution, ScopeDef::Local(_)),
468471
requires_import,
472+
has_local_inherent_impl: compute_has_local_inherent_impl(db, path_ctx, &ty, module),
469473
..CompletionRelevance::default()
470474
});
471475

@@ -660,6 +664,18 @@ fn compute_type_match(
660664
match_types(ctx, expected_type, completion_ty)
661665
}
662666

667+
fn compute_has_local_inherent_impl(
668+
db: &RootDatabase,
669+
path_ctx: &PathCompletionCtx<'_>,
670+
completion_ty: &hir::Type<'_>,
671+
curr_module: hir::Module,
672+
) -> bool {
673+
matches!(path_ctx.kind, PathKind::Type { location: TypeLocation::ImplTarget })
674+
&& Impl::all_for_type(db, completion_ty.clone())
675+
.iter()
676+
.any(|imp| imp.trait_(db).is_none() && imp.module(db) == curr_module)
677+
}
678+
663679
fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
664680
ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
665681
}
@@ -832,6 +848,7 @@ mod tests {
832848
),
833849
(relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
834850
(relevance.requires_import, "requires_import"),
851+
(relevance.has_local_inherent_impl, "has_local_inherent_impl"),
835852
]
836853
.into_iter()
837854
.filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
@@ -1214,6 +1231,7 @@ fn main() { Foo::Fo$0 }
12141231
},
12151232
),
12161233
is_skipping_completion: false,
1234+
has_local_inherent_impl: false,
12171235
},
12181236
trigger_call_info: true,
12191237
},
@@ -1264,6 +1282,7 @@ fn main() { Foo::Fo$0 }
12641282
},
12651283
),
12661284
is_skipping_completion: false,
1285+
has_local_inherent_impl: false,
12671286
},
12681287
trigger_call_info: true,
12691288
},
@@ -1407,6 +1426,7 @@ fn main() { Foo::Fo$0 }
14071426
},
14081427
),
14091428
is_skipping_completion: false,
1429+
has_local_inherent_impl: false,
14101430
},
14111431
trigger_call_info: true,
14121432
},
@@ -1490,6 +1510,7 @@ fn main() { let _: m::Spam = S$0 }
14901510
},
14911511
),
14921512
is_skipping_completion: false,
1513+
has_local_inherent_impl: false,
14931514
},
14941515
trigger_call_info: true,
14951516
},
@@ -1526,6 +1547,7 @@ fn main() { let _: m::Spam = S$0 }
15261547
},
15271548
),
15281549
is_skipping_completion: false,
1550+
has_local_inherent_impl: false,
15291551
},
15301552
trigger_call_info: true,
15311553
},
@@ -1616,6 +1638,7 @@ fn foo() { A { the$0 } }
16161638
postfix_match: None,
16171639
function: None,
16181640
is_skipping_completion: false,
1641+
has_local_inherent_impl: false,
16191642
},
16201643
},
16211644
]
@@ -1675,6 +1698,7 @@ impl S {
16751698
},
16761699
),
16771700
is_skipping_completion: false,
1701+
has_local_inherent_impl: false,
16781702
},
16791703
},
16801704
CompletionItem {
@@ -1766,6 +1790,7 @@ use self::E::*;
17661790
},
17671791
),
17681792
is_skipping_completion: false,
1793+
has_local_inherent_impl: false,
17691794
},
17701795
trigger_call_info: true,
17711796
},
@@ -1836,6 +1861,7 @@ fn foo(s: S) { s.$0 }
18361861
},
18371862
),
18381863
is_skipping_completion: false,
1864+
has_local_inherent_impl: false,
18391865
},
18401866
},
18411867
]
@@ -2048,6 +2074,7 @@ fn f() -> i32 {
20482074
postfix_match: None,
20492075
function: None,
20502076
is_skipping_completion: false,
2077+
has_local_inherent_impl: false,
20512078
},
20522079
},
20532080
]
@@ -2193,6 +2220,48 @@ fn f() {
21932220
);
21942221
}
21952222

2223+
#[test]
2224+
fn score_has_local_inherent_impl() {
2225+
check_relevance(
2226+
r#"
2227+
trait Foob {}
2228+
struct Fooa {}
2229+
impl Fooa {}
2230+
2231+
impl Foo$0
2232+
"#,
2233+
expect![[r#"
2234+
tt Foob []
2235+
st Fooa Fooa [has_local_inherent_impl]
2236+
"#]],
2237+
);
2238+
2239+
// inherent impl in different modules, not trigger `has_local_inherent_impl`
2240+
check_relevance(
2241+
r#"
2242+
trait Foob {}
2243+
struct Fooa {}
2244+
2245+
mod a {
2246+
use super::*;
2247+
impl Fooa {}
2248+
}
2249+
2250+
mod b {
2251+
use super::*;
2252+
impl Foo$0
2253+
}
2254+
2255+
"#,
2256+
expect![[r#"
2257+
st Fooa Fooa []
2258+
tt Foob []
2259+
md a []
2260+
md b []
2261+
"#]],
2262+
);
2263+
}
2264+
21962265
#[test]
21972266
fn test_avoid_redundant_suggestion() {
21982267
check_relevance(
@@ -2861,6 +2930,7 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
28612930
},
28622931
),
28632932
is_skipping_completion: false,
2933+
has_local_inherent_impl: false,
28642934
},
28652935
ref_match: "&@107",
28662936
},
@@ -2948,6 +3018,7 @@ fn foo() {
29483018
postfix_match: None,
29493019
function: None,
29503020
is_skipping_completion: false,
3021+
has_local_inherent_impl: false,
29513022
},
29523023
},
29533024
]
@@ -3006,6 +3077,7 @@ fn main() {
30063077
},
30073078
),
30083079
is_skipping_completion: false,
3080+
has_local_inherent_impl: false,
30093081
},
30103082
ref_match: "&@92",
30113083
},
@@ -3476,6 +3548,7 @@ fn main() {
34763548
postfix_match: None,
34773549
function: None,
34783550
is_skipping_completion: false,
3551+
has_local_inherent_impl: false,
34793552
},
34803553
},
34813554
CompletionItem {
@@ -3510,6 +3583,7 @@ fn main() {
35103583
postfix_match: None,
35113584
function: None,
35123585
is_skipping_completion: false,
3586+
has_local_inherent_impl: false,
35133587
},
35143588
},
35153589
]

0 commit comments

Comments
 (0)