]> git.lizzy.rs Git - rust.git/blob - crates/completion/src/completions/qualified_path.rs
More useful fn detail in completion
[rust.git] / crates / completion / src / completions / qualified_path.rs
1 //! Completion of paths, i.e. `some::prefix::$0`.
2
3 use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
4 use rustc_hash::FxHashSet;
5 use syntax::AstNode;
6 use test_utils::mark;
7
8 use crate::{CompletionContext, Completions};
9
10 pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
11     let path = match &ctx.path_qual {
12         Some(path) => path.clone(),
13         None => return,
14     };
15
16     if ctx.attribute_under_caret.is_some() || ctx.mod_declaration_under_caret.is_some() {
17         return;
18     }
19
20     let context_module = ctx.scope.module();
21
22     let resolution = match ctx.sema.resolve_path(&path) {
23         Some(res) => res,
24         None => return,
25     };
26
27     // Add associated types on type parameters and `Self`.
28     resolution.assoc_type_shorthand_candidates(ctx.db, |alias| {
29         acc.add_type_alias(ctx, alias);
30         None::<()>
31     });
32
33     match resolution {
34         PathResolution::Def(hir::ModuleDef::Module(module)) => {
35             let module_scope = module.scope(ctx.db, context_module);
36             for (name, def) in module_scope {
37                 if ctx.use_item_syntax.is_some() {
38                     if let ScopeDef::Unknown = def {
39                         if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
40                             if name_ref.syntax().text() == name.to_string().as_str() {
41                                 // for `use self::foo$0`, don't suggest `foo` as a completion
42                                 mark::hit!(dont_complete_current_use);
43                                 continue;
44                             }
45                         }
46                     }
47                 }
48
49                 acc.add_resolution(ctx, name.to_string(), &def);
50             }
51         }
52         PathResolution::Def(def @ hir::ModuleDef::Adt(_))
53         | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) => {
54             if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
55                 for variant in e.variants(ctx.db) {
56                     acc.add_enum_variant(ctx, variant, None);
57                 }
58             }
59             let ty = match def {
60                 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
61                 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
62                 _ => unreachable!(),
63             };
64
65             // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
66             // (where AssocType is defined on a trait, not an inherent impl)
67
68             let krate = ctx.krate;
69             if let Some(krate) = krate {
70                 let traits_in_scope = ctx.scope.traits_in_scope();
71                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
72                     if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
73                         return None;
74                     }
75                     match item {
76                         hir::AssocItem::Function(func) => {
77                             acc.add_function(ctx, func, None);
78                         }
79                         hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
80                         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
81                     }
82                     None::<()>
83                 });
84
85                 // Iterate assoc types separately
86                 ty.iterate_assoc_items(ctx.db, krate, |item| {
87                     if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
88                         return None;
89                     }
90                     match item {
91                         hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
92                         hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
93                     }
94                     None::<()>
95                 });
96             }
97         }
98         PathResolution::Def(hir::ModuleDef::Trait(t)) => {
99             // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
100             for item in t.items(ctx.db) {
101                 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
102                     continue;
103                 }
104                 match item {
105                     hir::AssocItem::Function(func) => {
106                         acc.add_function(ctx, func, None);
107                     }
108                     hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
109                     hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
110                 }
111             }
112         }
113         PathResolution::TypeParam(_) | PathResolution::SelfType(_) => {
114             if let Some(krate) = ctx.krate {
115                 let ty = match resolution {
116                     PathResolution::TypeParam(param) => param.ty(ctx.db),
117                     PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db),
118                     _ => return,
119                 };
120
121                 if let Some(Adt::Enum(e)) = ty.as_adt() {
122                     for variant in e.variants(ctx.db) {
123                         acc.add_enum_variant(ctx, variant, None);
124                     }
125                 }
126
127                 let traits_in_scope = ctx.scope.traits_in_scope();
128                 let mut seen = FxHashSet::default();
129                 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
130                     if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
131                         return None;
132                     }
133
134                     // We might iterate candidates of a trait multiple times here, so deduplicate
135                     // them.
136                     if seen.insert(item) {
137                         match item {
138                             hir::AssocItem::Function(func) => {
139                                 acc.add_function(ctx, func, None);
140                             }
141                             hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
142                             hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
143                         }
144                     }
145                     None::<()>
146                 });
147             }
148         }
149         _ => {}
150     }
151 }
152
153 #[cfg(test)]
154 mod tests {
155     use expect_test::{expect, Expect};
156     use test_utils::mark;
157
158     use crate::{
159         test_utils::{check_edit, completion_list},
160         CompletionKind,
161     };
162
163     fn check(ra_fixture: &str, expect: Expect) {
164         let actual = completion_list(ra_fixture, CompletionKind::Reference);
165         expect.assert_eq(&actual);
166     }
167
168     fn check_builtin(ra_fixture: &str, expect: Expect) {
169         let actual = completion_list(ra_fixture, CompletionKind::BuiltinType);
170         expect.assert_eq(&actual);
171     }
172
173     #[test]
174     fn dont_complete_current_use() {
175         mark::check!(dont_complete_current_use);
176         check(r#"use self::foo$0;"#, expect![[""]]);
177     }
178
179     #[test]
180     fn dont_complete_current_use_in_braces_with_glob() {
181         check(
182             r#"
183 mod foo { pub struct S; }
184 use self::{foo::*, bar$0};
185 "#,
186             expect![[r#"
187                 st S
188                 md foo
189             "#]],
190         );
191     }
192
193     #[test]
194     fn dont_complete_primitive_in_use() {
195         check_builtin(r#"use self::$0;"#, expect![[""]]);
196     }
197
198     #[test]
199     fn dont_complete_primitive_in_module_scope() {
200         check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
201     }
202
203     #[test]
204     fn completes_primitives() {
205         check_builtin(
206             r#"fn main() { let _: $0 = 92; }"#,
207             expect![[r#"
208                 bt u32
209                 bt bool
210                 bt u8
211                 bt isize
212                 bt u16
213                 bt u64
214                 bt u128
215                 bt f32
216                 bt i128
217                 bt i16
218                 bt str
219                 bt i64
220                 bt char
221                 bt f64
222                 bt i32
223                 bt i8
224                 bt usize
225             "#]],
226         );
227     }
228
229     #[test]
230     fn completes_mod_with_same_name_as_function() {
231         check(
232             r#"
233 use self::my::$0;
234
235 mod my { pub struct Bar; }
236 fn my() {}
237 "#,
238             expect![[r#"
239                 st Bar
240             "#]],
241         );
242     }
243
244     #[test]
245     fn filters_visibility() {
246         check(
247             r#"
248 use self::my::$0;
249
250 mod my {
251     struct Bar;
252     pub struct Foo;
253     pub use Bar as PublicBar;
254 }
255 "#,
256             expect![[r#"
257                 st Foo
258                 st PublicBar
259             "#]],
260         );
261     }
262
263     #[test]
264     fn completes_use_item_starting_with_self() {
265         check(
266             r#"
267 use self::m::$0;
268
269 mod m { pub struct Bar; }
270 "#,
271             expect![[r#"
272                 st Bar
273             "#]],
274         );
275     }
276
277     #[test]
278     fn completes_use_item_starting_with_crate() {
279         check(
280             r#"
281 //- /lib.rs
282 mod foo;
283 struct Spam;
284 //- /foo.rs
285 use crate::Sp$0
286 "#,
287             expect![[r#"
288                 md foo
289                 st Spam
290             "#]],
291         );
292     }
293
294     #[test]
295     fn completes_nested_use_tree() {
296         check(
297             r#"
298 //- /lib.rs
299 mod foo;
300 struct Spam;
301 //- /foo.rs
302 use crate::{Sp$0};
303 "#,
304             expect![[r#"
305                 md foo
306                 st Spam
307             "#]],
308         );
309     }
310
311     #[test]
312     fn completes_deeply_nested_use_tree() {
313         check(
314             r#"
315 //- /lib.rs
316 mod foo;
317 pub mod bar {
318     pub mod baz {
319         pub struct Spam;
320     }
321 }
322 //- /foo.rs
323 use crate::{bar::{baz::Sp$0}};
324 "#,
325             expect![[r#"
326                 st Spam
327             "#]],
328         );
329     }
330
331     #[test]
332     fn completes_enum_variant() {
333         check(
334             r#"
335 enum E { Foo, Bar(i32) }
336 fn foo() { let _ = E::$0 }
337 "#,
338             expect![[r#"
339                 ev Foo    ()
340                 ev Bar(…) (i32)
341             "#]],
342         );
343     }
344
345     #[test]
346     fn completes_struct_associated_items() {
347         check(
348             r#"
349 //- /lib.rs
350 struct S;
351
352 impl S {
353     fn a() {}
354     fn b(&self) {}
355     const C: i32 = 42;
356     type T = i32;
357 }
358
359 fn foo() { let _ = S::$0 }
360 "#,
361             expect![[r#"
362                 fn a()  -> ()
363                 me b(…) -> ()
364                 ct C    const C: i32 = 42;
365                 ta T    type T = i32;
366             "#]],
367         );
368     }
369
370     #[test]
371     fn associated_item_visibility() {
372         check(
373             r#"
374 struct S;
375
376 mod m {
377     impl super::S {
378         pub(crate) fn public_method() { }
379         fn private_method() { }
380         pub(crate) type PublicType = u32;
381         type PrivateType = u32;
382         pub(crate) const PUBLIC_CONST: u32 = 1;
383         const PRIVATE_CONST: u32 = 1;
384     }
385 }
386
387 fn foo() { let _ = S::$0 }
388 "#,
389             expect![[r#"
390                 fn public_method() -> ()
391                 ct PUBLIC_CONST    pub(crate) const PUBLIC_CONST: u32 = 1;
392                 ta PublicType      pub(crate) type PublicType = u32;
393             "#]],
394         );
395     }
396
397     #[test]
398     fn completes_enum_associated_method() {
399         check(
400             r#"
401 enum E {};
402 impl E { fn m() { } }
403
404 fn foo() { let _ = E::$0 }
405         "#,
406             expect![[r#"
407                 fn m() -> ()
408             "#]],
409         );
410     }
411
412     #[test]
413     fn completes_union_associated_method() {
414         check(
415             r#"
416 union U {};
417 impl U { fn m() { } }
418
419 fn foo() { let _ = U::$0 }
420 "#,
421             expect![[r#"
422                 fn m() -> ()
423             "#]],
424         );
425     }
426
427     #[test]
428     fn completes_use_paths_across_crates() {
429         check(
430             r#"
431 //- /main.rs crate:main deps:foo
432 use foo::$0;
433
434 //- /foo/lib.rs crate:foo
435 pub mod bar { pub struct S; }
436 "#,
437             expect![[r#"
438                 md bar
439             "#]],
440         );
441     }
442
443     #[test]
444     fn completes_trait_associated_method_1() {
445         check(
446             r#"
447 trait Trait { fn m(); }
448
449 fn foo() { let _ = Trait::$0 }
450 "#,
451             expect![[r#"
452                 fn m() -> ()
453             "#]],
454         );
455     }
456
457     #[test]
458     fn completes_trait_associated_method_2() {
459         check(
460             r#"
461 trait Trait { fn m(); }
462
463 struct S;
464 impl Trait for S {}
465
466 fn foo() { let _ = S::$0 }
467 "#,
468             expect![[r#"
469                 fn m() -> ()
470             "#]],
471         );
472     }
473
474     #[test]
475     fn completes_trait_associated_method_3() {
476         check(
477             r#"
478 trait Trait { fn m(); }
479
480 struct S;
481 impl Trait for S {}
482
483 fn foo() { let _ = <S as Trait>::$0 }
484 "#,
485             expect![[r#"
486                 fn m() -> ()
487             "#]],
488         );
489     }
490
491     #[test]
492     fn completes_ty_param_assoc_ty() {
493         check(
494             r#"
495 trait Super {
496     type Ty;
497     const CONST: u8;
498     fn func() {}
499     fn method(&self) {}
500 }
501
502 trait Sub: Super {
503     type SubTy;
504     const C2: ();
505     fn subfunc() {}
506     fn submethod(&self) {}
507 }
508
509 fn foo<T: Sub>() { T::$0 }
510 "#,
511             expect![[r#"
512                 ta SubTy        type SubTy;
513                 ta Ty           type Ty;
514                 ct C2           const C2: ();
515                 fn subfunc()    -> ()
516                 me submethod(…) -> ()
517                 ct CONST        const CONST: u8;
518                 fn func()       -> ()
519                 me method(…)    -> ()
520             "#]],
521         );
522     }
523
524     #[test]
525     fn completes_self_param_assoc_ty() {
526         check(
527             r#"
528 trait Super {
529     type Ty;
530     const CONST: u8 = 0;
531     fn func() {}
532     fn method(&self) {}
533 }
534
535 trait Sub: Super {
536     type SubTy;
537     const C2: () = ();
538     fn subfunc() {}
539     fn submethod(&self) {}
540 }
541
542 struct Wrap<T>(T);
543 impl<T> Super for Wrap<T> {}
544 impl<T> Sub for Wrap<T> {
545     fn subfunc() {
546         // Should be able to assume `Self: Sub + Super`
547         Self::$0
548     }
549 }
550 "#,
551             expect![[r#"
552                 ta SubTy        type SubTy;
553                 ta Ty           type Ty;
554                 ct CONST        const CONST: u8 = 0;
555                 fn func()       -> ()
556                 me method(…)    -> ()
557                 ct C2           const C2: () = ();
558                 fn subfunc()    -> ()
559                 me submethod(…) -> ()
560             "#]],
561         );
562     }
563
564     #[test]
565     fn completes_type_alias() {
566         check(
567             r#"
568 struct S;
569 impl S { fn foo() {} }
570 type T = S;
571 impl T { fn bar() {} }
572
573 fn main() { T::$0; }
574 "#,
575             expect![[r#"
576                 fn foo() -> ()
577                 fn bar() -> ()
578             "#]],
579         );
580     }
581
582     #[test]
583     fn completes_qualified_macros() {
584         check(
585             r#"
586 #[macro_export]
587 macro_rules! foo { () => {} }
588
589 fn main() { let _ = crate::$0 }
590         "#,
591             expect![[r##"
592                 fn main()  -> ()
593                 ma foo!(…) #[macro_export] macro_rules! foo
594             "##]],
595         );
596     }
597
598     #[test]
599     fn test_super_super_completion() {
600         check(
601             r#"
602 mod a {
603     const A: usize = 0;
604     mod b {
605         const B: usize = 0;
606         mod c { use super::super::$0 }
607     }
608 }
609 "#,
610             expect![[r#"
611                 md b
612                 ct A
613             "#]],
614         );
615     }
616
617     #[test]
618     fn completes_reexported_items_under_correct_name() {
619         check(
620             r#"
621 fn foo() { self::m::$0 }
622
623 mod m {
624     pub use super::p::wrong_fn as right_fn;
625     pub use super::p::WRONG_CONST as RIGHT_CONST;
626     pub use super::p::WrongType as RightType;
627 }
628 mod p {
629     fn wrong_fn() {}
630     const WRONG_CONST: u32 = 1;
631     struct WrongType {};
632 }
633 "#,
634             expect![[r#"
635                 ct RIGHT_CONST
636                 fn right_fn()  -> ()
637                 st RightType
638             "#]],
639         );
640
641         check_edit(
642             "RightType",
643             r#"
644 fn foo() { self::m::$0 }
645
646 mod m {
647     pub use super::p::wrong_fn as right_fn;
648     pub use super::p::WRONG_CONST as RIGHT_CONST;
649     pub use super::p::WrongType as RightType;
650 }
651 mod p {
652     fn wrong_fn() {}
653     const WRONG_CONST: u32 = 1;
654     struct WrongType {};
655 }
656 "#,
657             r#"
658 fn foo() { self::m::RightType }
659
660 mod m {
661     pub use super::p::wrong_fn as right_fn;
662     pub use super::p::WRONG_CONST as RIGHT_CONST;
663     pub use super::p::WrongType as RightType;
664 }
665 mod p {
666     fn wrong_fn() {}
667     const WRONG_CONST: u32 = 1;
668     struct WrongType {};
669 }
670 "#,
671         );
672     }
673
674     #[test]
675     fn completes_in_simple_macro_call() {
676         check(
677             r#"
678 macro_rules! m { ($e:expr) => { $e } }
679 fn main() { m!(self::f$0); }
680 fn foo() {}
681 "#,
682             expect![[r#"
683                 fn main() -> ()
684                 fn foo()  -> ()
685             "#]],
686         );
687     }
688
689     #[test]
690     fn function_mod_share_name() {
691         check(
692             r#"
693 fn foo() { self::m::$0 }
694
695 mod m {
696     pub mod z {}
697     pub fn z() {}
698 }
699 "#,
700             expect![[r#"
701                 md z
702                 fn z() -> ()
703             "#]],
704         );
705     }
706
707     #[test]
708     fn completes_hashmap_new() {
709         check(
710             r#"
711 struct RandomState;
712 struct HashMap<K, V, S = RandomState> {}
713
714 impl<K, V> HashMap<K, V, RandomState> {
715     pub fn new() -> HashMap<K, V, RandomState> { }
716 }
717 fn foo() {
718     HashMap::$0
719 }
720 "#,
721             expect![[r#"
722                 fn new() -> HashMap<K, V, RandomState>
723             "#]],
724         );
725     }
726
727     #[test]
728     fn dont_complete_attr() {
729         check(
730             r#"
731 mod foo { pub struct Foo; }
732 #[foo::$0]
733 fn f() {}
734 "#,
735             expect![[""]],
736         );
737     }
738
739     #[test]
740     fn completes_function() {
741         check(
742             r#"
743 fn foo(
744     a: i32,
745     b: i32
746 ) {
747
748 }
749
750 fn main() {
751     fo$0
752 }
753 "#,
754             expect![[r#"
755                 fn main() -> ()
756                 fn foo(…) -> ()
757             "#]],
758         );
759     }
760
761     #[test]
762     fn completes_self_enum() {
763         check(
764             r#"
765 enum Foo {
766     Bar,
767     Baz,
768 }
769
770 impl Foo {
771     fn foo(self) {
772         Self::$0
773     }
774 }
775 "#,
776             expect![[r#"
777                 ev Bar    ()
778                 ev Baz    ()
779                 me foo(…) -> ()
780             "#]],
781         );
782     }
783 }