1 //! Completes references after dot (fields and method calls).
5 use rustc_hash::FxHashSet;
7 use crate::{context::CompletionContext, patterns::ImmediateLocation, Completions};
9 /// Complete dot accesses, i.e. fields or methods.
10 pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
11 let dot_receiver = match ctx.dot_receiver() {
13 _ => return complete_undotted_self(acc, ctx),
16 let receiver_ty = match ctx.sema.type_of_expr(dot_receiver) {
17 Some(ty) => ty.original,
21 if matches!(ctx.completion_location, Some(ImmediateLocation::MethodCall { .. })) {
22 cov_mark::hit!(test_no_struct_field_completion_for_method_call);
24 complete_fields(ctx, &receiver_ty, |field, ty| match field {
25 Either::Left(field) => acc.add_field(ctx, None, field, &ty),
26 Either::Right(tuple_idx) => acc.add_tuple_field(ctx, None, tuple_idx, &ty),
29 complete_methods(ctx, &receiver_ty, |func| acc.add_method(ctx, func, None, None));
32 fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
33 if !ctx.config.enable_self_on_the_fly {
36 if !ctx.is_trivial_path() || ctx.is_path_disallowed() || !ctx.expects_expression() {
39 ctx.scope.process_all_names(&mut |name, def| {
40 if let ScopeDef::Local(local) = &def {
41 if local.is_self(ctx.db) {
42 let ty = local.ty(ctx.db);
43 complete_fields(ctx, &ty, |field, ty| match field {
44 either::Either::Left(field) => {
45 acc.add_field(ctx, Some(name.clone()), field, &ty)
47 either::Either::Right(tuple_idx) => {
48 acc.add_tuple_field(ctx, Some(name.clone()), tuple_idx, &ty)
51 complete_methods(ctx, &ty, |func| {
52 acc.add_method(ctx, func, Some(name.clone()), None)
60 ctx: &CompletionContext,
62 mut f: impl FnMut(Either<hir::Field, usize>, hir::Type),
64 for receiver in receiver.autoderef(ctx.db) {
65 for (field, ty) in receiver.fields(ctx.db) {
66 if !ctx.is_visible(&field) {
69 f(Either::Left(field), ty);
71 for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
72 // Tuple fields are always public (tuple struct fields are handled above).
73 f(Either::Right(i), ty);
79 ctx: &CompletionContext,
81 mut f: impl FnMut(hir::Function),
83 if let Some(krate) = ctx.krate {
84 let mut seen_methods = FxHashSet::default();
85 let traits_in_scope = ctx.scope.traits_in_scope();
86 receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
87 if func.self_param(ctx.db).is_some()
88 && ctx.is_visible(&func)
89 && seen_methods.insert(func.name(ctx.db))
100 use expect_test::{expect, Expect};
102 use crate::tests::{check_edit, completion_list_no_kw};
104 fn check(ra_fixture: &str, expect: Expect) {
105 let actual = completion_list_no_kw(ra_fixture);
106 expect.assert_eq(&actual);
110 fn test_struct_field_and_method_completion() {
113 struct S { foo: u32 }
117 fn foo(s: S) { s.$0 }
124 sn match match expr {}
125 sn box Box::new(expr)
131 sn call function(expr)
139 fn test_struct_field_completion_self() {
142 struct S { the_field: (u32,) }
144 fn foo(self) { self.$0 }
152 sn match match expr {}
153 sn box Box::new(expr)
159 sn call function(expr)
167 fn test_struct_field_completion_autoderef() {
170 struct A { the_field: (u32, i32) }
172 fn foo(&self) { self.$0 }
176 fd the_field (u32, i32)
180 sn match match expr {}
181 sn box Box::new(expr)
187 sn call function(expr)
195 fn test_no_struct_field_completion_for_method_call() {
196 cov_mark::check!(test_no_struct_field_completion_for_method_call);
199 struct A { the_field: u32 }
200 fn foo(a: A) { a.$0() }
205 sn match match expr {}
206 sn box Box::new(expr)
212 sn call function(expr)
218 fn test_visibility_filtering() {
221 //- /lib.rs crate:lib new_source_root:local
226 pub(crate) crate_field: u32,
227 pub(super) super_field: u32,
230 //- /main.rs crate:main deps:lib new_source_root:local
231 fn foo(a: lib::m::A) { a.$0 }
240 sn match match expr {}
241 sn box Box::new(expr)
247 sn call function(expr)
255 //- /lib.rs crate:lib new_source_root:library
260 pub(crate) crate_field: u32,
261 pub(super) super_field: u32,
264 //- /main.rs crate:main deps:lib new_source_root:local
265 fn foo(a: lib::m::A) { a.$0 }
271 sn match match expr {}
272 sn box Box::new(expr)
278 sn call function(expr)
286 //- /lib.rs crate:lib new_source_root:library
293 //- /main.rs crate:main deps:lib new_source_root:local
294 fn foo(a: lib::m::A) { a.$0 }
300 sn match match expr {}
301 sn box Box::new(expr)
307 sn call function(expr)
315 //- /lib.rs crate:lib new_source_root:local
319 fn private_method(&self) {}
320 pub(crate) fn crate_method(&self) {}
321 pub fn pub_method(&self) {}
324 //- /main.rs crate:main deps:lib new_source_root:local
325 fn foo(a: lib::A) { a.$0 }
328 me private_method() fn(&self)
329 me crate_method() fn(&self)
330 me pub_method() fn(&self)
333 sn match match expr {}
334 sn box Box::new(expr)
340 sn call function(expr)
347 //- /lib.rs crate:lib new_source_root:library
351 fn private_method(&self) {}
352 pub(crate) fn crate_method(&self) {}
353 pub fn pub_method(&self) {}
356 //- /main.rs crate:main deps:lib new_source_root:local
357 fn foo(a: lib::A) { a.$0 }
360 me pub_method() fn(&self)
363 sn match match expr {}
364 sn box Box::new(expr)
370 sn call function(expr)
378 fn test_doc_hidden_filtering() {
381 //- /lib.rs crate:lib deps:dep
382 fn foo(a: dep::A) { a.$0 }
383 //- /dep.rs crate:dep
386 pub hidden_field: u32,
391 pub fn pub_method(&self) {}
394 pub fn hidden_method(&self) {}
399 me pub_method() fn(&self)
402 sn match match expr {}
403 sn box Box::new(expr)
409 sn call function(expr)
417 fn test_union_field_completion() {
420 union U { field: u8, other: u16 }
421 fn foo(u: U) { u.$0 }
428 sn match match expr {}
429 sn box Box::new(expr)
435 sn call function(expr)
443 fn test_method_completion_only_fitting_impls() {
448 fn the_method(&self) {}
451 fn the_other_method(&self) {}
453 fn foo(a: A<u32>) { a.$0 }
456 me the_method() fn(&self)
459 sn match match expr {}
460 sn box Box::new(expr)
466 sn call function(expr)
474 fn test_trait_method_completion() {
478 trait Trait { fn the_method(&self); }
480 fn foo(a: A) { a.$0 }
483 me the_method() (as Trait) fn(&self)
486 sn match match expr {}
487 sn box Box::new(expr)
493 sn call function(expr)
502 trait Trait { fn the_method(&self); }
504 fn foo(a: A) { a.$0 }
508 trait Trait { fn the_method(&self); }
510 fn foo(a: A) { a.the_method()$0 }
516 fn test_trait_method_completion_deduplicated() {
520 trait Trait { fn the_method(&self); }
521 impl<T> Trait for T {}
522 fn foo(a: &A) { a.$0 }
525 me the_method() (as Trait) fn(&self)
528 sn match match expr {}
529 sn box Box::new(expr)
535 sn call function(expr)
543 fn completes_trait_method_from_other_module() {
548 pub trait Trait { fn the_method(&self); }
552 fn foo(a: A) { a.$0 }
555 me the_method() (as Trait) fn(&self)
558 sn match match expr {}
559 sn box Box::new(expr)
565 sn call function(expr)
573 fn test_no_non_self_method() {
587 sn match match expr {}
588 sn box Box::new(expr)
594 sn call function(expr)
602 fn test_tuple_field_completion() {
615 sn match match expr {}
616 sn box Box::new(expr)
622 sn call function(expr)
630 fn test_tuple_struct_field_completion() {
644 sn match match expr {}
645 sn box Box::new(expr)
651 sn call function(expr)
659 fn test_tuple_field_inference() {
663 impl S { pub fn blah(&self) {} }
669 // FIXME: This doesn't work without the trailing `a` as `0.` is a float
678 sn match match expr {}
679 sn box Box::new(expr)
685 sn call function(expr)
693 fn test_completion_works_in_consts() {
696 struct A { the_field: u32 }
698 A { the_field: 92 }.$0
705 sn match match expr {}
706 sn box Box::new(expr)
712 sn call function(expr)
720 fn works_in_simple_macro_1() {
723 macro_rules! m { ($e:expr) => { $e } }
724 struct A { the_field: u32 }
733 sn match match expr {}
734 sn box Box::new(expr)
740 sn call function(expr)
746 fn works_in_simple_macro_2() {
747 // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
750 macro_rules! m { ($e:expr) => { $e } }
751 struct A { the_field: u32 }
760 sn match match expr {}
761 sn box Box::new(expr)
767 sn call function(expr)
773 fn works_in_simple_macro_recursive_1() {
776 macro_rules! m { ($e:expr) => { $e } }
777 struct A { the_field: u32 }
786 sn match match expr {}
787 sn box Box::new(expr)
793 sn call function(expr)
799 fn macro_expansion_resilient() {
805 match $val { tmp => { tmp } }
807 // Trailing comma with single argument is ignored
808 ($val:expr,) => { $crate::d!($val) };
809 ($($val:expr),+ $(,)?) => {
810 ($($crate::d!($val)),+,)
813 struct A { the_field: u32 }
822 sn match match expr {}
823 sn box Box::new(expr)
829 sn call function(expr)
835 fn test_method_completion_issue_3547() {
840 pub fn the_method(&self) {}
848 me the_method() fn(&self)
851 sn match match expr {}
852 sn box Box::new(expr)
858 sn call function(expr)
866 fn completes_method_call_when_receiver_is_a_macro_call() {
870 impl S { fn foo(&self) {} }
871 macro_rules! make_s { () => { S }; }
872 fn main() { make_s!().f$0; }
878 sn match match expr {}
879 sn box Box::new(expr)
885 sn call function(expr)
893 fn completes_after_macro_call_in_submodule() {
901 #[derive(Debug, Default)]
908 let goo: Template2 = Template2 {};
915 me private() fn(&self)
918 sn match match expr {}
919 sn box Box::new(expr)
925 sn call function(expr)
941 fn foo(&self) -> &[u8] { loop {} }
945 fn indented(&mut self, f: impl FnOnce(&mut Self)) {
948 fn f(&mut self, v: Foo) {
949 self.indented(|this| v.$0)
954 me foo() fn(&self) -> &[u8]
957 sn match match expr {}
958 sn box Box::new(expr)
964 sn call function(expr)
970 fn completes_bare_fields_and_methods_in_methods() {
973 struct Foo { field: i32 }
975 impl Foo { fn foo(&self) { $0 } }"#,
982 me self.foo() fn(&self)
989 impl Foo { fn foo(&mut self) { $0 } }"#,
996 me self.foo() fn(&mut self)
1002 fn macro_completion_after_dot() {
1006 ($e:expr) => { $e };
1016 let c = Completable;
1021 me method() fn(&self)
1024 sn match match expr {}
1025 sn box Box::new(expr)
1031 sn call function(expr)
1037 fn completes_method_call_when_receiver_type_has_errors_issue_10297() {
1040 //- minicore: iterator, sized
1042 impl<T> IntoIterator for Vec<T> {
1053 me into_iter() (as IntoIterator) fn(self) -> <Self as IntoIterator>::IntoIter
1056 sn match match expr {}
1057 sn box Box::new(expr)
1063 sn call function(expr)