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