diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 40bd1e75e..a97e876e9 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use hir::{Ty, AdtDef, TypeCtor}; | 1 | use hir::{Ty, AdtDef, TypeCtor}; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions}; | 3 | use crate::completion::{CompletionContext, Completions}; |
4 | use rustc_hash::FxHashSet; | ||
4 | 5 | ||
5 | /// Complete dot accesses, i.e. fields or methods (currently only fields). | 6 | /// Complete dot accesses, i.e. fields or methods (currently only fields). |
6 | pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | 7 | pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { |
@@ -36,9 +37,10 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
36 | } | 37 | } |
37 | 38 | ||
38 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 39 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { |
40 | let mut seen_methods = FxHashSet::default(); | ||
39 | ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { | 41 | ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { |
40 | let data = func.data(ctx.db); | 42 | let data = func.data(ctx.db); |
41 | if data.has_self_param() { | 43 | if data.has_self_param() && seen_methods.insert(data.name().clone()) { |
42 | acc.add_function(ctx, func); | 44 | acc.add_function(ctx, func); |
43 | } | 45 | } |
44 | None::<()> | 46 | None::<()> |
@@ -231,6 +233,34 @@ mod tests { | |||
231 | } | 233 | } |
232 | 234 | ||
233 | #[test] | 235 | #[test] |
236 | fn test_trait_method_completion_deduplicated() { | ||
237 | assert_debug_snapshot_matches!( | ||
238 | do_ref_completion( | ||
239 | r" | ||
240 | struct A {} | ||
241 | trait Trait { fn the_method(&self); } | ||
242 | impl<T> Trait for T {} | ||
243 | fn foo(a: &A) { | ||
244 | a.<|> | ||
245 | } | ||
246 | ", | ||
247 | ), | ||
248 | @r###" | ||
249 | ⋮[ | ||
250 | ⋮ CompletionItem { | ||
251 | ⋮ label: "the_method", | ||
252 | ⋮ source_range: [155; 155), | ||
253 | ⋮ delete: [155; 155), | ||
254 | ⋮ insert: "the_method()$0", | ||
255 | ⋮ kind: Method, | ||
256 | ⋮ detail: "fn the_method(&self)", | ||
257 | ⋮ }, | ||
258 | ⋮] | ||
259 | "### | ||
260 | ); | ||
261 | } | ||
262 | |||
263 | #[test] | ||
234 | fn test_no_non_self_method() { | 264 | fn test_no_non_self_method() { |
235 | assert_debug_snapshot_matches!( | 265 | assert_debug_snapshot_matches!( |
236 | do_ref_completion( | 266 | do_ref_completion( |