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