]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/dot.rs
Respect `#[doc(hidden)]` in dot-completion
[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,
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             // FIXME: Handle visibility
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 mod inner {
178     pub struct A {
179         private_field: u32,
180         pub pub_field: u32,
181         pub(crate) crate_field: u32,
182         pub(crate) super_field: u32,
183     }
184 }
185 fn foo(a: inner::A) { a.$0 }
186 "#,
187             expect![[r#"
188                 fd pub_field   u32
189                 fd crate_field u32
190                 fd super_field u32
191             "#]],
192         );
193
194         check(
195             r#"
196 struct A {}
197 mod m {
198     impl super::A {
199         fn private_method(&self) {}
200         pub(crate) fn the_method(&self) {}
201     }
202 }
203 fn foo(a: A) { a.$0 }
204 "#,
205             expect![[r#"
206                 me the_method() fn(&self)
207             "#]],
208         );
209     }
210
211     #[test]
212     fn test_doc_hidden_filtering() {
213         check(
214             r#"
215 //- /lib.rs crate:lib deps:dep
216 fn foo(a: dep::A) { a.$0 }
217 //- /dep.rs crate:dep
218 pub struct A {
219     #[doc(hidden)]
220     pub hidden_field: u32,
221     pub pub_field: u32,
222 }
223
224 impl A {
225     pub fn pub_method(&self) {}
226
227     #[doc(hidden)]
228     pub fn hidden_method(&self) {}
229 }
230             "#,
231             expect![[r#"
232                 fd pub_field    u32
233                 me pub_method() fn(&self)
234             "#]]
235         )
236     }
237
238     #[test]
239     fn test_union_field_completion() {
240         check(
241             r#"
242 union U { field: u8, other: u16 }
243 fn foo(u: U) { u.$0 }
244 "#,
245             expect![[r#"
246                 fd field u8
247                 fd other u16
248             "#]],
249         );
250     }
251
252     #[test]
253     fn test_method_completion_only_fitting_impls() {
254         check(
255             r#"
256 struct A<T> {}
257 impl A<u32> {
258     fn the_method(&self) {}
259 }
260 impl A<i32> {
261     fn the_other_method(&self) {}
262 }
263 fn foo(a: A<u32>) { a.$0 }
264 "#,
265             expect![[r#"
266                 me the_method() fn(&self)
267             "#]],
268         )
269     }
270
271     #[test]
272     fn test_trait_method_completion() {
273         check(
274             r#"
275 struct A {}
276 trait Trait { fn the_method(&self); }
277 impl Trait for A {}
278 fn foo(a: A) { a.$0 }
279 "#,
280             expect![[r#"
281                 me the_method() (as Trait) fn(&self)
282             "#]],
283         );
284         check_edit(
285             "the_method",
286             r#"
287 struct A {}
288 trait Trait { fn the_method(&self); }
289 impl Trait for A {}
290 fn foo(a: A) { a.$0 }
291 "#,
292             r#"
293 struct A {}
294 trait Trait { fn the_method(&self); }
295 impl Trait for A {}
296 fn foo(a: A) { a.the_method()$0 }
297 "#,
298         );
299     }
300
301     #[test]
302     fn test_trait_method_completion_deduplicated() {
303         check(
304             r"
305 struct A {}
306 trait Trait { fn the_method(&self); }
307 impl<T> Trait for T {}
308 fn foo(a: &A) { a.$0 }
309 ",
310             expect![[r#"
311                 me the_method() (as Trait) fn(&self)
312             "#]],
313         );
314     }
315
316     #[test]
317     fn completes_trait_method_from_other_module() {
318         check(
319             r"
320 struct A {}
321 mod m {
322     pub trait Trait { fn the_method(&self); }
323 }
324 use m::Trait;
325 impl Trait for A {}
326 fn foo(a: A) { a.$0 }
327 ",
328             expect![[r#"
329                 me the_method() (as Trait) fn(&self)
330             "#]],
331         );
332     }
333
334     #[test]
335     fn test_no_non_self_method() {
336         check(
337             r#"
338 struct A {}
339 impl A {
340     fn the_method() {}
341 }
342 fn foo(a: A) {
343    a.$0
344 }
345 "#,
346             expect![[""]],
347         );
348     }
349
350     #[test]
351     fn test_tuple_field_completion() {
352         check(
353             r#"
354 fn foo() {
355    let b = (0, 3.14);
356    b.$0
357 }
358 "#,
359             expect![[r#"
360                 fd 0 i32
361                 fd 1 f64
362             "#]],
363         )
364     }
365
366     #[test]
367     fn test_tuple_field_inference() {
368         check(
369             r#"
370 pub struct S;
371 impl S { pub fn blah(&self) {} }
372
373 struct T(S);
374
375 impl T {
376     fn foo(&self) {
377         // FIXME: This doesn't work without the trailing `a` as `0.` is a float
378         self.0.a$0
379     }
380 }
381 "#,
382             expect![[r#"
383                 me blah() fn(&self)
384             "#]],
385         );
386     }
387
388     #[test]
389     fn test_completion_works_in_consts() {
390         check(
391             r#"
392 struct A { the_field: u32 }
393 const X: u32 = {
394     A { the_field: 92 }.$0
395 };
396 "#,
397             expect![[r#"
398                 fd the_field u32
399             "#]],
400         );
401     }
402
403     #[test]
404     fn works_in_simple_macro_1() {
405         check(
406             r#"
407 macro_rules! m { ($e:expr) => { $e } }
408 struct A { the_field: u32 }
409 fn foo(a: A) {
410     m!(a.x$0)
411 }
412 "#,
413             expect![[r#"
414                 fd the_field u32
415             "#]],
416         );
417     }
418
419     #[test]
420     fn works_in_simple_macro_2() {
421         // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
422         check(
423             r#"
424 macro_rules! m { ($e:expr) => { $e } }
425 struct A { the_field: u32 }
426 fn foo(a: A) {
427     m!(a.$0)
428 }
429 "#,
430             expect![[r#"
431                 fd the_field u32
432             "#]],
433         );
434     }
435
436     #[test]
437     fn works_in_simple_macro_recursive_1() {
438         check(
439             r#"
440 macro_rules! m { ($e:expr) => { $e } }
441 struct A { the_field: u32 }
442 fn foo(a: A) {
443     m!(m!(m!(a.x$0)))
444 }
445 "#,
446             expect![[r#"
447                 fd the_field u32
448             "#]],
449         );
450     }
451
452     #[test]
453     fn macro_expansion_resilient() {
454         check(
455             r#"
456 macro_rules! d {
457     () => {};
458     ($val:expr) => {
459         match $val { tmp => { tmp } }
460     };
461     // Trailing comma with single argument is ignored
462     ($val:expr,) => { $crate::d!($val) };
463     ($($val:expr),+ $(,)?) => {
464         ($($crate::d!($val)),+,)
465     };
466 }
467 struct A { the_field: u32 }
468 fn foo(a: A) {
469     d!(a.$0)
470 }
471 "#,
472             expect![[r#"
473                 fd the_field u32
474             "#]],
475         );
476     }
477
478     #[test]
479     fn test_method_completion_issue_3547() {
480         check(
481             r#"
482 struct HashSet<T> {}
483 impl<T> HashSet<T> {
484     pub fn the_method(&self) {}
485 }
486 fn foo() {
487     let s: HashSet<_>;
488     s.$0
489 }
490 "#,
491             expect![[r#"
492                 me the_method() fn(&self)
493             "#]],
494         );
495     }
496
497     #[test]
498     fn completes_method_call_when_receiver_is_a_macro_call() {
499         check(
500             r#"
501 struct S;
502 impl S { fn foo(&self) {} }
503 macro_rules! make_s { () => { S }; }
504 fn main() { make_s!().f$0; }
505 "#,
506             expect![[r#"
507                 me foo() fn(&self)
508             "#]],
509         )
510     }
511
512     #[test]
513     fn completes_after_macro_call_in_submodule() {
514         check(
515             r#"
516 macro_rules! empty {
517     () => {};
518 }
519
520 mod foo {
521     #[derive(Debug, Default)]
522     struct Template2 {}
523
524     impl Template2 {
525         fn private(&self) {}
526     }
527     fn baz() {
528         let goo: Template2 = Template2 {};
529         empty!();
530         goo.$0
531     }
532 }
533         "#,
534             expect![[r#"
535                 me private() fn(&self)
536             "#]],
537         );
538     }
539
540     #[test]
541     fn issue_8931() {
542         check(
543             r#"
544 //- minicore: fn
545 struct S;
546
547 struct Foo;
548 impl Foo {
549     fn foo(&self) -> &[u8] { loop {} }
550 }
551
552 impl S {
553     fn indented(&mut self, f: impl FnOnce(&mut Self)) {
554     }
555
556     fn f(&mut self, v: Foo) {
557         self.indented(|this| v.$0)
558     }
559 }
560         "#,
561             expect![[r#"
562                 me foo() fn(&self) -> &[u8]
563             "#]],
564         );
565     }
566
567     #[test]
568     fn completes_bare_fields_and_methods_in_methods() {
569         check(
570             r#"
571 struct Foo { field: i32 }
572
573 impl Foo { fn foo(&self) { $0 } }"#,
574             expect![[r#"
575                 lc self       &Foo
576                 sp Self
577                 st Foo
578                 fd self.field i32
579                 me self.foo() fn(&self)
580             "#]],
581         );
582         check(
583             r#"
584 struct Foo(i32);
585
586 impl Foo { fn foo(&mut self) { $0 } }"#,
587             expect![[r#"
588                 lc self       &mut Foo
589                 sp Self
590                 st Foo
591                 fd self.0     i32
592                 me self.foo() fn(&mut self)
593             "#]],
594         );
595     }
596 }