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