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