]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/dot.rs
internal: Directly use self param in completions instead of searching
[rust.git] / crates / ide_completion / src / completions / dot.rs
1 //! Completes references after dot (fields and method calls).
2
3 use either::Either;
4 use rustc_hash::FxHashSet;
5
6 use crate::{context::CompletionContext, patterns::ImmediateLocation, Completions};
7
8 /// Complete dot accesses, i.e. fields or methods.
9 pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
10     let dot_receiver = match ctx.dot_receiver() {
11         Some(expr) => expr,
12         _ => return complete_undotted_self(acc, ctx),
13     };
14
15     let receiver_ty = match ctx.sema.type_of_expr(dot_receiver) {
16         Some(ty) => ty.original,
17         _ => return,
18     };
19
20     if matches!(ctx.completion_location, Some(ImmediateLocation::MethodCall { .. })) {
21         cov_mark::hit!(test_no_struct_field_completion_for_method_call);
22     } else {
23         complete_fields(ctx, &receiver_ty, |field, ty| match field {
24             Either::Left(field) => acc.add_field(ctx, None, field, &ty),
25             Either::Right(tuple_idx) => acc.add_tuple_field(ctx, None, tuple_idx, &ty),
26         });
27     }
28     complete_methods(ctx, &receiver_ty, |func| acc.add_method(ctx, func, None, None));
29 }
30
31 fn complete_undotted_self(acc: &mut Completions, ctx: &CompletionContext) {
32     if !ctx.config.enable_self_on_the_fly {
33         return;
34     }
35     if !ctx.is_trivial_path() || ctx.is_path_disallowed() || !ctx.expects_expression() {
36         return;
37     }
38     if let Some(func) = ctx.function_def.as_ref().and_then(|fn_| ctx.sema.to_def(fn_)) {
39         if let Some(self_) = func.self_param(ctx.db) {
40             let ty = self_.ty(ctx.db);
41             complete_fields(ctx, &ty, |field, ty| match field {
42                 either::Either::Left(field) => {
43                     acc.add_field(ctx, Some(hir::known::SELF_PARAM), field, &ty)
44                 }
45                 either::Either::Right(tuple_idx) => {
46                     acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), tuple_idx, &ty)
47                 }
48             });
49             complete_methods(ctx, &ty, |func| {
50                 acc.add_method(ctx, func, Some(hir::known::SELF_PARAM), None)
51             });
52         }
53     }
54 }
55
56 fn complete_fields(
57     ctx: &CompletionContext,
58     receiver: &hir::Type,
59     mut f: impl FnMut(Either<hir::Field, usize>, hir::Type),
60 ) {
61     for receiver in receiver.autoderef(ctx.db) {
62         for (field, ty) in receiver.fields(ctx.db) {
63             f(Either::Left(field), ty);
64         }
65         for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
66             // Tuple fields are always public (tuple struct fields are handled above).
67             f(Either::Right(i), ty);
68         }
69     }
70 }
71
72 fn complete_methods(
73     ctx: &CompletionContext,
74     receiver: &hir::Type,
75     mut f: impl FnMut(hir::Function),
76 ) {
77     if let Some(krate) = ctx.krate {
78         let mut seen_methods = FxHashSet::default();
79         let traits_in_scope = ctx.scope.visible_traits();
80         receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
81             if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
82                 f(func);
83             }
84             None::<()>
85         });
86     }
87 }
88
89 #[cfg(test)]
90 mod tests {
91     use expect_test::{expect, Expect};
92
93     use crate::tests::{check_edit, completion_list_no_kw};
94
95     fn check(ra_fixture: &str, expect: Expect) {
96         let actual = completion_list_no_kw(ra_fixture);
97         expect.assert_eq(&actual);
98     }
99
100     #[test]
101     fn test_struct_field_and_method_completion() {
102         check(
103             r#"
104 struct S { foo: u32 }
105 impl S {
106     fn bar(&self) {}
107 }
108 fn foo(s: S) { s.$0 }
109 "#,
110             expect![[r#"
111                 fd foo   u32
112                 me bar() fn(&self)
113             "#]],
114         );
115     }
116
117     #[test]
118     fn test_struct_field_completion_self() {
119         check(
120             r#"
121 struct S { the_field: (u32,) }
122 impl S {
123     fn foo(self) { self.$0 }
124 }
125 "#,
126             expect![[r#"
127                 fd the_field (u32,)
128                 me foo()     fn(self)
129             "#]],
130         )
131     }
132
133     #[test]
134     fn test_struct_field_completion_autoderef() {
135         check(
136             r#"
137 struct A { the_field: (u32, i32) }
138 impl A {
139     fn foo(&self) { self.$0 }
140 }
141 "#,
142             expect![[r#"
143                 fd the_field (u32, i32)
144                 me foo()     fn(&self)
145             "#]],
146         )
147     }
148
149     #[test]
150     fn test_no_struct_field_completion_for_method_call() {
151         cov_mark::check!(test_no_struct_field_completion_for_method_call);
152         check(
153             r#"
154 struct A { the_field: u32 }
155 fn foo(a: A) { a.$0() }
156 "#,
157             expect![[r#""#]],
158         );
159     }
160
161     #[test]
162     fn test_visibility_filtering() {
163         check(
164             r#"
165 //- /lib.rs crate:lib new_source_root:local
166 pub mod m {
167     pub struct A {
168         private_field: u32,
169         pub pub_field: u32,
170         pub(crate) crate_field: u32,
171         pub(super) super_field: u32,
172     }
173 }
174 //- /main.rs crate:main deps:lib new_source_root:local
175 fn foo(a: lib::m::A) { a.$0 }
176 "#,
177             expect![[r#"
178                 fd private_field u32
179                 fd pub_field     u32
180                 fd crate_field   u32
181                 fd super_field   u32
182             "#]],
183         );
184
185         check(
186             r#"
187 //- /lib.rs crate:lib new_source_root:library
188 pub mod m {
189     pub struct A {
190         private_field: u32,
191         pub pub_field: u32,
192         pub(crate) crate_field: u32,
193         pub(super) super_field: u32,
194     }
195 }
196 //- /main.rs crate:main deps:lib new_source_root:local
197 fn foo(a: lib::m::A) { a.$0 }
198 "#,
199             expect![[r#"
200                 fd pub_field u32
201             "#]],
202         );
203
204         check(
205             r#"
206 //- /lib.rs crate:lib new_source_root:library
207 pub mod m {
208     pub struct A(
209         i32,
210         pub f64,
211     );
212 }
213 //- /main.rs crate:main deps:lib new_source_root:local
214 fn foo(a: lib::m::A) { a.$0 }
215 "#,
216             expect![[r#"
217                 fd 1 f64
218             "#]],
219         );
220
221         check(
222             r#"
223 //- /lib.rs crate:lib new_source_root:local
224 pub struct A {}
225 mod m {
226     impl super::A {
227         fn private_method(&self) {}
228         pub(crate) fn crate_method(&self) {}
229         pub fn pub_method(&self) {}
230     }
231 }
232 //- /main.rs crate:main deps:lib new_source_root:local
233 fn foo(a: lib::A) { a.$0 }
234 "#,
235             expect![[r#"
236                 me private_method() fn(&self)
237                 me crate_method()   fn(&self)
238                 me pub_method()     fn(&self)
239             "#]],
240         );
241         check(
242             r#"
243 //- /lib.rs crate:lib new_source_root:library
244 pub struct A {}
245 mod m {
246     impl super::A {
247         fn private_method(&self) {}
248         pub(crate) fn crate_method(&self) {}
249         pub fn pub_method(&self) {}
250     }
251 }
252 //- /main.rs crate:main deps:lib new_source_root:local
253 fn foo(a: lib::A) { a.$0 }
254 "#,
255             expect![[r#"
256                 me pub_method() fn(&self)
257             "#]],
258         );
259     }
260
261     #[test]
262     fn test_doc_hidden_filtering() {
263         check(
264             r#"
265 //- /lib.rs crate:lib deps:dep
266 fn foo(a: dep::A) { a.$0 }
267 //- /dep.rs crate:dep
268 pub struct A {
269     #[doc(hidden)]
270     pub hidden_field: u32,
271     pub pub_field: u32,
272 }
273
274 impl A {
275     pub fn pub_method(&self) {}
276
277     #[doc(hidden)]
278     pub fn hidden_method(&self) {}
279 }
280             "#,
281             expect![[r#"
282                 fd pub_field    u32
283                 me pub_method() fn(&self)
284             "#]],
285         )
286     }
287
288     #[test]
289     fn test_union_field_completion() {
290         check(
291             r#"
292 union U { field: u8, other: u16 }
293 fn foo(u: U) { u.$0 }
294 "#,
295             expect![[r#"
296                 fd field u8
297                 fd other u16
298             "#]],
299         );
300     }
301
302     #[test]
303     fn test_method_completion_only_fitting_impls() {
304         check(
305             r#"
306 struct A<T> {}
307 impl A<u32> {
308     fn the_method(&self) {}
309 }
310 impl A<i32> {
311     fn the_other_method(&self) {}
312 }
313 fn foo(a: A<u32>) { a.$0 }
314 "#,
315             expect![[r#"
316                 me the_method() fn(&self)
317             "#]],
318         )
319     }
320
321     #[test]
322     fn test_trait_method_completion() {
323         check(
324             r#"
325 struct A {}
326 trait Trait { fn the_method(&self); }
327 impl Trait for A {}
328 fn foo(a: A) { a.$0 }
329 "#,
330             expect![[r#"
331                 me the_method() (as Trait) fn(&self)
332             "#]],
333         );
334         check_edit(
335             "the_method",
336             r#"
337 struct A {}
338 trait Trait { fn the_method(&self); }
339 impl Trait for A {}
340 fn foo(a: A) { a.$0 }
341 "#,
342             r#"
343 struct A {}
344 trait Trait { fn the_method(&self); }
345 impl Trait for A {}
346 fn foo(a: A) { a.the_method()$0 }
347 "#,
348         );
349     }
350
351     #[test]
352     fn test_trait_method_completion_deduplicated() {
353         check(
354             r"
355 struct A {}
356 trait Trait { fn the_method(&self); }
357 impl<T> Trait for T {}
358 fn foo(a: &A) { a.$0 }
359 ",
360             expect![[r#"
361                 me the_method() (as Trait) fn(&self)
362             "#]],
363         );
364     }
365
366     #[test]
367     fn completes_trait_method_from_other_module() {
368         check(
369             r"
370 struct A {}
371 mod m {
372     pub trait Trait { fn the_method(&self); }
373 }
374 use m::Trait;
375 impl Trait for A {}
376 fn foo(a: A) { a.$0 }
377 ",
378             expect![[r#"
379                 me the_method() (as Trait) fn(&self)
380             "#]],
381         );
382     }
383
384     #[test]
385     fn test_no_non_self_method() {
386         check(
387             r#"
388 struct A {}
389 impl A {
390     fn the_method() {}
391 }
392 fn foo(a: A) {
393    a.$0
394 }
395 "#,
396             expect![[r#""#]],
397         );
398     }
399
400     #[test]
401     fn test_tuple_field_completion() {
402         check(
403             r#"
404 fn foo() {
405    let b = (0, 3.14);
406    b.$0
407 }
408 "#,
409             expect![[r#"
410                 fd 0 i32
411                 fd 1 f64
412             "#]],
413         );
414     }
415
416     #[test]
417     fn test_tuple_struct_field_completion() {
418         check(
419             r#"
420 struct S(i32, f64);
421 fn foo() {
422    let b = S(0, 3.14);
423    b.$0
424 }
425 "#,
426             expect![[r#"
427                 fd 0 i32
428                 fd 1 f64
429             "#]],
430         );
431     }
432
433     #[test]
434     fn test_tuple_field_inference() {
435         check(
436             r#"
437 pub struct S;
438 impl S { pub fn blah(&self) {} }
439
440 struct T(S);
441
442 impl T {
443     fn foo(&self) {
444         // FIXME: This doesn't work without the trailing `a` as `0.` is a float
445         self.0.a$0
446     }
447 }
448 "#,
449             expect![[r#"
450                 me blah() fn(&self)
451             "#]],
452         );
453     }
454
455     #[test]
456     fn test_completion_works_in_consts() {
457         check(
458             r#"
459 struct A { the_field: u32 }
460 const X: u32 = {
461     A { the_field: 92 }.$0
462 };
463 "#,
464             expect![[r#"
465                 fd the_field u32
466             "#]],
467         );
468     }
469
470     #[test]
471     fn works_in_simple_macro_1() {
472         check(
473             r#"
474 macro_rules! m { ($e:expr) => { $e } }
475 struct A { the_field: u32 }
476 fn foo(a: A) {
477     m!(a.x$0)
478 }
479 "#,
480             expect![[r#"
481                 fd the_field u32
482             "#]],
483         );
484     }
485
486     #[test]
487     fn works_in_simple_macro_2() {
488         // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
489         check(
490             r#"
491 macro_rules! m { ($e:expr) => { $e } }
492 struct A { the_field: u32 }
493 fn foo(a: A) {
494     m!(a.$0)
495 }
496 "#,
497             expect![[r#"
498                 fd the_field u32
499             "#]],
500         );
501     }
502
503     #[test]
504     fn works_in_simple_macro_recursive_1() {
505         check(
506             r#"
507 macro_rules! m { ($e:expr) => { $e } }
508 struct A { the_field: u32 }
509 fn foo(a: A) {
510     m!(m!(m!(a.x$0)))
511 }
512 "#,
513             expect![[r#"
514                 fd the_field u32
515             "#]],
516         );
517     }
518
519     #[test]
520     fn macro_expansion_resilient() {
521         check(
522             r#"
523 macro_rules! d {
524     () => {};
525     ($val:expr) => {
526         match $val { tmp => { tmp } }
527     };
528     // Trailing comma with single argument is ignored
529     ($val:expr,) => { $crate::d!($val) };
530     ($($val:expr),+ $(,)?) => {
531         ($($crate::d!($val)),+,)
532     };
533 }
534 struct A { the_field: u32 }
535 fn foo(a: A) {
536     d!(a.$0)
537 }
538 "#,
539             expect![[r#"
540                 fd the_field u32
541             "#]],
542         );
543     }
544
545     #[test]
546     fn test_method_completion_issue_3547() {
547         check(
548             r#"
549 struct HashSet<T> {}
550 impl<T> HashSet<T> {
551     pub fn the_method(&self) {}
552 }
553 fn foo() {
554     let s: HashSet<_>;
555     s.$0
556 }
557 "#,
558             expect![[r#"
559                 me the_method() fn(&self)
560             "#]],
561         );
562     }
563
564     #[test]
565     fn completes_method_call_when_receiver_is_a_macro_call() {
566         check(
567             r#"
568 struct S;
569 impl S { fn foo(&self) {} }
570 macro_rules! make_s { () => { S }; }
571 fn main() { make_s!().f$0; }
572 "#,
573             expect![[r#"
574                 me foo() fn(&self)
575             "#]],
576         )
577     }
578
579     #[test]
580     fn completes_after_macro_call_in_submodule() {
581         check(
582             r#"
583 macro_rules! empty {
584     () => {};
585 }
586
587 mod foo {
588     #[derive(Debug, Default)]
589     struct Template2 {}
590
591     impl Template2 {
592         fn private(&self) {}
593     }
594     fn baz() {
595         let goo: Template2 = Template2 {};
596         empty!();
597         goo.$0
598     }
599 }
600         "#,
601             expect![[r#"
602                 me private() fn(&self)
603             "#]],
604         );
605     }
606
607     #[test]
608     fn issue_8931() {
609         check(
610             r#"
611 //- minicore: fn
612 struct S;
613
614 struct Foo;
615 impl Foo {
616     fn foo(&self) -> &[u8] { loop {} }
617 }
618
619 impl S {
620     fn indented(&mut self, f: impl FnOnce(&mut Self)) {
621     }
622
623     fn f(&mut self, v: Foo) {
624         self.indented(|this| v.$0)
625     }
626 }
627         "#,
628             expect![[r#"
629                 me foo() fn(&self) -> &[u8]
630             "#]],
631         );
632     }
633
634     #[test]
635     fn completes_bare_fields_and_methods_in_methods() {
636         check(
637             r#"
638 struct Foo { field: i32 }
639
640 impl Foo { fn foo(&self) { $0 } }"#,
641             expect![[r#"
642                 lc self       &Foo
643                 sp Self
644                 st Foo
645                 bt u32
646                 fd self.field i32
647                 me self.foo() fn(&self)
648             "#]],
649         );
650         check(
651             r#"
652 struct Foo(i32);
653
654 impl Foo { fn foo(&mut self) { $0 } }"#,
655             expect![[r#"
656                 lc self       &mut Foo
657                 sp Self
658                 st Foo
659                 bt u32
660                 fd self.0     i32
661                 me self.foo() fn(&mut self)
662             "#]],
663         );
664     }
665
666     #[test]
667     fn macro_completion_after_dot() {
668         check(
669             r#"
670 macro_rules! m {
671     ($e:expr) => { $e };
672 }
673
674 struct Completable;
675
676 impl Completable {
677     fn method(&self) {}
678 }
679
680 fn f() {
681     let c = Completable;
682     m!(c.$0);
683 }
684     "#,
685             expect![[r#"
686                 me method() fn(&self)
687             "#]],
688         );
689     }
690
691     #[test]
692     fn completes_method_call_when_receiver_type_has_errors_issue_10297() {
693         check(
694             r#"
695 //- minicore: iterator, sized
696 struct Vec<T>;
697 impl<T> IntoIterator for Vec<T> {
698     type Item = ();
699     type IntoIter = ();
700     fn into_iter(self);
701 }
702 fn main() {
703     let x: Vec<_>;
704     x.$0;
705 }
706 "#,
707             expect![[r#"
708                 me into_iter() (as IntoIterator) fn(self) -> <Self as IntoIterator>::IntoIter
709             "#]],
710         )
711     }
712 }