]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/dot.rs
Add MethodCall and FieldAccess variants to ImmediateLocation
[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::{HasVisibility, ScopeDef};
5 use rustc_hash::FxHashSet;
6
7 use crate::{context::CompletionContext, 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,
18         _ => return,
19     };
20
21     if ctx.is_call {
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() {
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.scope.module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) {
67                 // Skip private field. FIXME: If the definition location of the
68                 // field is editable, we should show the completion
69                 continue;
70             }
71             f(Either::Left(field), ty);
72         }
73         for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
74             // FIXME: Handle visibility
75             f(Either::Right(i), ty);
76         }
77     }
78 }
79
80 fn complete_methods(
81     ctx: &CompletionContext,
82     receiver: &hir::Type,
83     mut f: impl FnMut(hir::Function),
84 ) {
85     if let Some(krate) = ctx.krate {
86         let mut seen_methods = FxHashSet::default();
87         let traits_in_scope = ctx.scope.traits_in_scope();
88         receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
89             if func.self_param(ctx.db).is_some()
90                 && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m))
91                 && seen_methods.insert(func.name(ctx.db))
92             {
93                 f(func);
94             }
95             None::<()>
96         });
97     }
98 }
99
100 #[cfg(test)]
101 mod tests {
102     use expect_test::{expect, Expect};
103
104     use crate::{test_utils::completion_list, CompletionKind};
105
106     fn check(ra_fixture: &str, expect: Expect) {
107         let actual = completion_list(ra_fixture, CompletionKind::Reference);
108         expect.assert_eq(&actual);
109     }
110
111     #[test]
112     fn test_struct_field_and_method_completion() {
113         check(
114             r#"
115 struct S { foo: u32 }
116 impl S {
117     fn bar(&self) {}
118 }
119 fn foo(s: S) { s.$0 }
120 "#,
121             expect![[r#"
122                 fd foo   u32
123                 me bar() fn(&self)
124             "#]],
125         );
126     }
127
128     #[test]
129     fn test_struct_field_completion_self() {
130         check(
131             r#"
132 struct S { the_field: (u32,) }
133 impl S {
134     fn foo(self) { self.$0 }
135 }
136 "#,
137             expect![[r#"
138                 fd the_field (u32,)
139                 me foo()     fn(self)
140             "#]],
141         )
142     }
143
144     #[test]
145     fn test_struct_field_completion_autoderef() {
146         check(
147             r#"
148 struct A { the_field: (u32, i32) }
149 impl A {
150     fn foo(&self) { self.$0 }
151 }
152 "#,
153             expect![[r#"
154                 fd the_field (u32, i32)
155                 me foo()     fn(&self)
156             "#]],
157         )
158     }
159
160     #[test]
161     fn test_no_struct_field_completion_for_method_call() {
162         cov_mark::check!(test_no_struct_field_completion_for_method_call);
163         check(
164             r#"
165 struct A { the_field: u32 }
166 fn foo(a: A) { a.$0() }
167 "#,
168             expect![[""]],
169         );
170     }
171
172     #[test]
173     fn test_visibility_filtering() {
174         check(
175             r#"
176 mod inner {
177     pub struct A {
178         private_field: u32,
179         pub pub_field: u32,
180         pub(crate) crate_field: u32,
181         pub(crate) super_field: u32,
182     }
183 }
184 fn foo(a: inner::A) { a.$0 }
185 "#,
186             expect![[r#"
187                 fd pub_field   u32
188                 fd crate_field u32
189                 fd super_field u32
190             "#]],
191         );
192
193         check(
194             r#"
195 struct A {}
196 mod m {
197     impl super::A {
198         fn private_method(&self) {}
199         pub(crate) fn the_method(&self) {}
200     }
201 }
202 fn foo(a: A) { a.$0 }
203 "#,
204             expect![[r#"
205                 me the_method() fn(&self)
206             "#]],
207         );
208     }
209
210     #[test]
211     fn test_union_field_completion() {
212         check(
213             r#"
214 union U { field: u8, other: u16 }
215 fn foo(u: U) { u.$0 }
216 "#,
217             expect![[r#"
218                 fd field u8
219                 fd other u16
220             "#]],
221         );
222     }
223
224     #[test]
225     fn test_method_completion_only_fitting_impls() {
226         check(
227             r#"
228 struct A<T> {}
229 impl A<u32> {
230     fn the_method(&self) {}
231 }
232 impl A<i32> {
233     fn the_other_method(&self) {}
234 }
235 fn foo(a: A<u32>) { a.$0 }
236 "#,
237             expect![[r#"
238                 me the_method() fn(&self)
239             "#]],
240         )
241     }
242
243     #[test]
244     fn test_trait_method_completion() {
245         check(
246             r#"
247 struct A {}
248 trait Trait { fn the_method(&self); }
249 impl Trait for A {}
250 fn foo(a: A) { a.$0 }
251 "#,
252             expect![[r#"
253                 me the_method() fn(&self)
254             "#]],
255         );
256     }
257
258     #[test]
259     fn test_trait_method_completion_deduplicated() {
260         check(
261             r"
262 struct A {}
263 trait Trait { fn the_method(&self); }
264 impl<T> Trait for T {}
265 fn foo(a: &A) { a.$0 }
266 ",
267             expect![[r#"
268                 me the_method() fn(&self)
269             "#]],
270         );
271     }
272
273     #[test]
274     fn completes_trait_method_from_other_module() {
275         check(
276             r"
277 struct A {}
278 mod m {
279     pub trait Trait { fn the_method(&self); }
280 }
281 use m::Trait;
282 impl Trait for A {}
283 fn foo(a: A) { a.$0 }
284 ",
285             expect![[r#"
286                 me the_method() fn(&self)
287             "#]],
288         );
289     }
290
291     #[test]
292     fn test_no_non_self_method() {
293         check(
294             r#"
295 struct A {}
296 impl A {
297     fn the_method() {}
298 }
299 fn foo(a: A) {
300    a.$0
301 }
302 "#,
303             expect![[""]],
304         );
305     }
306
307     #[test]
308     fn test_tuple_field_completion() {
309         check(
310             r#"
311 fn foo() {
312    let b = (0, 3.14);
313    b.$0
314 }
315 "#,
316             expect![[r#"
317                 fd 0 i32
318                 fd 1 f64
319             "#]],
320         )
321     }
322
323     #[test]
324     fn test_tuple_field_inference() {
325         check(
326             r#"
327 pub struct S;
328 impl S { pub fn blah(&self) {} }
329
330 struct T(S);
331
332 impl T {
333     fn foo(&self) {
334         // FIXME: This doesn't work without the trailing `a` as `0.` is a float
335         self.0.a$0
336     }
337 }
338 "#,
339             expect![[r#"
340                 me blah() fn(&self)
341             "#]],
342         );
343     }
344
345     #[test]
346     fn test_completion_works_in_consts() {
347         check(
348             r#"
349 struct A { the_field: u32 }
350 const X: u32 = {
351     A { the_field: 92 }.$0
352 };
353 "#,
354             expect![[r#"
355                 fd the_field u32
356             "#]],
357         );
358     }
359
360     #[test]
361     fn works_in_simple_macro_1() {
362         check(
363             r#"
364 macro_rules! m { ($e:expr) => { $e } }
365 struct A { the_field: u32 }
366 fn foo(a: A) {
367     m!(a.x$0)
368 }
369 "#,
370             expect![[r#"
371                 fd the_field u32
372             "#]],
373         );
374     }
375
376     #[test]
377     fn works_in_simple_macro_2() {
378         // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
379         check(
380             r#"
381 macro_rules! m { ($e:expr) => { $e } }
382 struct A { the_field: u32 }
383 fn foo(a: A) {
384     m!(a.$0)
385 }
386 "#,
387             expect![[r#"
388                 fd the_field u32
389             "#]],
390         );
391     }
392
393     #[test]
394     fn works_in_simple_macro_recursive_1() {
395         check(
396             r#"
397 macro_rules! m { ($e:expr) => { $e } }
398 struct A { the_field: u32 }
399 fn foo(a: A) {
400     m!(m!(m!(a.x$0)))
401 }
402 "#,
403             expect![[r#"
404                 fd the_field u32
405             "#]],
406         );
407     }
408
409     #[test]
410     fn macro_expansion_resilient() {
411         check(
412             r#"
413 macro_rules! d {
414     () => {};
415     ($val:expr) => {
416         match $val { tmp => { tmp } }
417     };
418     // Trailing comma with single argument is ignored
419     ($val:expr,) => { $crate::d!($val) };
420     ($($val:expr),+ $(,)?) => {
421         ($($crate::d!($val)),+,)
422     };
423 }
424 struct A { the_field: u32 }
425 fn foo(a: A) {
426     d!(a.$0)
427 }
428 "#,
429             expect![[r#"
430                 fd the_field u32
431             "#]],
432         );
433     }
434
435     #[test]
436     fn test_method_completion_issue_3547() {
437         check(
438             r#"
439 struct HashSet<T> {}
440 impl<T> HashSet<T> {
441     pub fn the_method(&self) {}
442 }
443 fn foo() {
444     let s: HashSet<_>;
445     s.$0
446 }
447 "#,
448             expect![[r#"
449                 me the_method() fn(&self)
450             "#]],
451         );
452     }
453
454     #[test]
455     fn completes_method_call_when_receiver_is_a_macro_call() {
456         check(
457             r#"
458 struct S;
459 impl S { fn foo(&self) {} }
460 macro_rules! make_s { () => { S }; }
461 fn main() { make_s!().f$0; }
462 "#,
463             expect![[r#"
464                 me foo() fn(&self)
465             "#]],
466         )
467     }
468
469     #[test]
470     fn completes_after_macro_call_in_submodule() {
471         check(
472             r#"
473 macro_rules! empty {
474     () => {};
475 }
476
477 mod foo {
478     #[derive(Debug, Default)]
479     struct Template2 {}
480
481     impl Template2 {
482         fn private(&self) {}
483     }
484     fn baz() {
485         let goo: Template2 = Template2 {};
486         empty!();
487         goo.$0
488     }
489 }
490         "#,
491             expect![[r#"
492                 me private() fn(&self)
493             "#]],
494         );
495     }
496
497     #[test]
498     fn issue_8931() {
499         check(
500             r#"
501 #[lang = "fn_once"]
502 trait FnOnce<Args> {
503     type Output;
504 }
505 struct S;
506
507 struct Foo;
508 impl Foo {
509     fn foo(&self) -> &[u8] { loop {} }
510 }
511
512 impl S {
513     fn indented(&mut self, f: impl FnOnce(&mut Self)) {
514     }
515
516     fn f(&mut self, v: Foo) {
517         self.indented(|this| v.$0)
518     }
519 }
520         "#,
521             expect![[r#"
522                 me foo() fn(&self) -> &[u8]
523             "#]],
524         );
525     }
526
527     #[test]
528     fn completes_bare_fields_and_methods_in_methods() {
529         check(
530             r#"
531 struct Foo { field: i32 }
532
533 impl Foo { fn foo(&self) { $0 } }"#,
534             expect![[r#"
535                 lc self       &Foo
536                 sp Self
537                 st Foo
538                 fd self.field i32
539                 me self.foo() fn(&self)
540             "#]],
541         );
542         check(
543             r#"
544 struct Foo(i32);
545
546 impl Foo { fn foo(&mut self) { $0 } }"#,
547             expect![[r#"
548                 lc self       &mut Foo
549                 sp Self
550                 st Foo
551                 fd self.0     i32
552                 me self.foo() fn(&mut self)
553             "#]],
554         );
555     }
556 }