aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions/unqualified_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/completions/unqualified_path.rs')
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs130
1 files changed, 112 insertions, 18 deletions
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index bd955aa85..952f052a1 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -1,30 +1,32 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use hir::ScopeDef; 3use hir::ScopeDef;
4use syntax::{ast, AstNode};
4 5
5use crate::{CompletionContext, Completions}; 6use crate::{patterns::ImmediateLocation, CompletionContext, Completions};
6 7
7pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 8pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
8 if !ctx.is_trivial_path { 9 if ctx.is_path_disallowed() || !ctx.is_trivial_path() {
9 return;
10 }
11 if ctx.is_path_disallowed() || ctx.expects_item() {
12 return; 10 return;
13 } 11 }
14 12
15 if ctx.expects_assoc_item() { 13 if ctx.expects_item() || ctx.expects_assoc_item() {
16 ctx.scope.process_all_names(&mut |name, def| { 14 // only show macros in {Assoc}ItemList
17 if let ScopeDef::MacroDef(macro_def) = def { 15 ctx.scope.process_all_names(&mut |name, res| {
18 acc.add_macro(ctx, Some(name.clone()), macro_def); 16 if let hir::ScopeDef::MacroDef(mac) = res {
17 if mac.is_fn_like() {
18 acc.add_macro(ctx, Some(name.clone()), mac);
19 }
19 } 20 }
20 if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def { 21 if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
21 acc.add_resolution(ctx, name, &def); 22 acc.add_resolution(ctx, name, &res);
22 } 23 }
23 }); 24 });
24 return; 25 return;
25 } 26 }
26 27
27 if ctx.expects_use_tree() { 28 if ctx.expects_use_tree() {
29 // only show modules in a fresh UseTree
28 cov_mark::hit!(only_completes_modules_in_import); 30 cov_mark::hit!(only_completes_modules_in_import);
29 ctx.scope.process_all_names(&mut |name, res| { 31 ctx.scope.process_all_names(&mut |name, res| {
30 if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res { 32 if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
@@ -42,12 +44,32 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
42 }); 44 });
43 } 45 }
44 46
47 if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
48 if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) {
49 if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
50 ctx.sema.resolve_path(&path_seg.parent_path())
51 {
52 trait_.items(ctx.sema.db).into_iter().for_each(|it| {
53 if let hir::AssocItem::TypeAlias(alias) = it {
54 acc.add_type_alias_with_eq(ctx, alias)
55 }
56 });
57 }
58 }
59 }
60
45 ctx.scope.process_all_names(&mut |name, res| { 61 ctx.scope.process_all_names(&mut |name, res| {
46 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { 62 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
47 cov_mark::hit!(skip_lifetime_completion); 63 cov_mark::hit!(skip_lifetime_completion);
48 return; 64 return;
49 } 65 }
50 acc.add_resolution(ctx, name, &res); 66 let add_resolution = match res {
67 ScopeDef::MacroDef(mac) => mac.is_fn_like(),
68 _ => true,
69 };
70 if add_resolution {
71 acc.add_resolution(ctx, name, &res);
72 }
51 }); 73 });
52} 74}
53 75
@@ -70,6 +92,28 @@ mod tests {
70 } 92 }
71 93
72 #[test] 94 #[test]
95 fn dont_complete_values_in_type_pos() {
96 check(
97 r#"
98const FOO: () = ();
99static BAR: () = ();
100enum Foo {
101 Bar
102}
103struct Baz;
104fn foo() {
105 let local = ();
106 let _: $0;
107}
108"#,
109 expect![[r#"
110 en Foo
111 st Baz
112 "#]],
113 );
114 }
115
116 #[test]
73 fn only_completes_modules_in_import() { 117 fn only_completes_modules_in_import() {
74 cov_mark::check!(only_completes_modules_in_import); 118 cov_mark::check!(only_completes_modules_in_import);
75 check( 119 check(
@@ -340,7 +384,6 @@ fn x() -> $0
340"#, 384"#,
341 expect![[r#" 385 expect![[r#"
342 st Foo 386 st Foo
343 fn x() fn()
344 "#]], 387 "#]],
345 ); 388 );
346 } 389 }
@@ -392,7 +435,6 @@ pub mod prelude {
392} 435}
393"#, 436"#,
394 expect![[r#" 437 expect![[r#"
395 fn foo() fn()
396 md std 438 md std
397 st Option 439 st Option
398 "#]], 440 "#]],
@@ -428,6 +470,44 @@ mod macros {
428 } 470 }
429 471
430 #[test] 472 #[test]
473 fn does_not_complete_non_fn_macros() {
474 check(
475 r#"
476#[rustc_builtin_macro]
477pub macro Clone {}
478
479fn f() {$0}
480"#,
481 expect![[r#"
482 fn f() fn()
483 "#]],
484 );
485 check(
486 r#"
487#[rustc_builtin_macro]
488pub macro Clone {}
489
490struct S;
491impl S {
492 $0
493}
494"#,
495 expect![[r#""#]],
496 );
497 check(
498 r#"
499#[rustc_builtin_macro]
500pub macro bench {}
501
502fn f() {$0}
503"#,
504 expect![[r#"
505 fn f() fn()
506 "#]],
507 );
508 }
509
510 #[test]
431 fn completes_std_prelude_if_core_is_defined() { 511 fn completes_std_prelude_if_core_is_defined() {
432 check( 512 check(
433 r#" 513 r#"
@@ -449,7 +529,6 @@ pub mod prelude {
449} 529}
450"#, 530"#,
451 expect![[r#" 531 expect![[r#"
452 fn foo() fn()
453 md std 532 md std
454 md core 533 md core
455 st String 534 st String
@@ -510,7 +589,6 @@ macro_rules! foo { () => {} }
510fn main() { let x: $0 } 589fn main() { let x: $0 }
511"#, 590"#,
512 expect![[r#" 591 expect![[r#"
513 fn main() fn()
514 ma foo!(…) macro_rules! foo 592 ma foo!(…) macro_rules! foo
515 "#]], 593 "#]],
516 ); 594 );
@@ -693,12 +771,11 @@ impl MyStruct {
693"#, 771"#,
694 expect![[r#" 772 expect![[r#"
695 md bar 773 md bar
696 ma foo! macro_rules! foo 774 ma foo!(…) macro_rules! foo
697 "#]], 775 "#]],
698 ) 776 )
699 } 777 }
700 778
701 // FIXME: The completions here currently come from `macro_in_item_position`, but they shouldn't
702 #[test] 779 #[test]
703 fn completes_in_item_list() { 780 fn completes_in_item_list() {
704 check( 781 check(
@@ -715,4 +792,21 @@ $0
715 "#]], 792 "#]],
716 ) 793 )
717 } 794 }
795
796 #[test]
797 fn completes_assoc_types_in_dynimpl_trait() {
798 check(
799 r#"
800trait Foo {
801 type Bar;
802}
803
804fn foo(_: impl Foo<B$0>) {}
805"#,
806 expect![[r#"
807 ta Bar = type Bar;
808 tt Foo
809 "#]],
810 );
811 }
718} 812}