aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-06-16 14:08:44 +0100
committerLukas Wirth <[email protected]>2021-06-16 14:08:44 +0100
commit354ad29493dbb258c11190abd7632af95c538e16 (patch)
tree09418c3c079d2a849cc99aaeddf5feaab39317f3
parent79703efc7fddce3f0080d3d97c200d6a2a2ffaa9 (diff)
Filter out non-type completions in the respective completions modules instead
-rw-r--r--crates/hir/src/lib.rs12
-rw-r--r--crates/ide_completion/src/completions.rs3
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs85
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs58
-rw-r--r--crates/ide_completion/src/context.rs4
-rw-r--r--crates/ide_completion/src/render.rs3
6 files changed, 94 insertions, 71 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5bc0b2338..b7eabaabb 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2688,18 +2688,6 @@ impl ScopeDef {
2688 2688
2689 items 2689 items
2690 } 2690 }
2691
2692 pub fn is_value_def(&self) -> bool {
2693 matches!(
2694 self,
2695 ScopeDef::ModuleDef(ModuleDef::Function(_))
2696 | ScopeDef::ModuleDef(ModuleDef::Variant(_))
2697 | ScopeDef::ModuleDef(ModuleDef::Const(_))
2698 | ScopeDef::ModuleDef(ModuleDef::Static(_))
2699 | ScopeDef::GenericParam(GenericParam::ConstParam(_))
2700 | ScopeDef::Local(_)
2701 )
2702 }
2703} 2691}
2704 2692
2705impl From<ItemInNs> for ScopeDef { 2693impl From<ItemInNs> for ScopeDef {
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index bd90cefb2..aef70f26a 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -109,9 +109,6 @@ impl Completions {
109 local_name: hir::Name, 109 local_name: hir::Name,
110 resolution: &hir::ScopeDef, 110 resolution: &hir::ScopeDef,
111 ) { 111 ) {
112 if ctx.expects_type() && resolution.is_value_def() {
113 return;
114 }
115 self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution)); 112 self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution));
116 } 113 }
117 114
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 6083537b7..1643eeed4 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -19,6 +19,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
19 Some(res) => res, 19 Some(res) => res,
20 None => return, 20 None => return,
21 }; 21 };
22
22 let context_module = ctx.scope.module(); 23 let context_module = ctx.scope.module();
23 24
24 if ctx.expects_item() || ctx.expects_assoc_item() { 25 if ctx.expects_item() || ctx.expects_assoc_item() {
@@ -60,21 +61,31 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
60 } 61 }
61 } 62 }
62 63
63 if let hir::ScopeDef::MacroDef(macro_def) = def { 64 let add_resolution = match def {
64 if !macro_def.is_fn_like() { 65 // Don't suggest attribute macros and derives.
65 // Don't suggest attribute macros and derives. 66 hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
66 continue; 67 // no values in type places
68 hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(_))
69 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Variant(_))
70 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Static(_))
71 | hir::ScopeDef::Local(_) => !ctx.expects_type(),
72 // unless its a constant in a generic arg list position
73 hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => {
74 !ctx.expects_type() || ctx.expects_generic_arg()
67 } 75 }
68 } 76 _ => true,
77 };
69 78
70 acc.add_resolution(ctx, name, &def); 79 if add_resolution {
80 acc.add_resolution(ctx, name, &def);
81 }
71 } 82 }
72 } 83 }
73 hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_)) 84 hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_))
74 | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) 85 | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_))
75 | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => { 86 | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => {
76 if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def { 87 if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
77 add_enum_variants(ctx, acc, e); 88 add_enum_variants(acc, ctx, e);
78 } 89 }
79 let ty = match def { 90 let ty = match def {
80 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db), 91 hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
@@ -82,7 +93,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
82 let ty = a.ty(ctx.db); 93 let ty = a.ty(ctx.db);
83 if let Some(hir::Adt::Enum(e)) = ty.as_adt() { 94 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
84 cov_mark::hit!(completes_variant_through_alias); 95 cov_mark::hit!(completes_variant_through_alias);
85 add_enum_variants(ctx, acc, e); 96 add_enum_variants(acc, ctx, e);
86 } 97 }
87 ty 98 ty
88 } 99 }
@@ -107,11 +118,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
107 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { 118 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
108 return None; 119 return None;
109 } 120 }
110 match item { 121 add_assoc_item(acc, ctx, item);
111 hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
112 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
113 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
114 }
115 None::<()> 122 None::<()>
116 }); 123 });
117 124
@@ -133,11 +140,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
133 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { 140 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
134 continue; 141 continue;
135 } 142 }
136 match item { 143 add_assoc_item(acc, ctx, item);
137 hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
138 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
139 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
140 }
141 } 144 }
142 } 145 }
143 hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => { 146 hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
@@ -149,7 +152,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
149 }; 152 };
150 153
151 if let Some(hir::Adt::Enum(e)) = ty.as_adt() { 154 if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
152 add_enum_variants(ctx, acc, e); 155 add_enum_variants(acc, ctx, e);
153 } 156 }
154 157
155 let traits_in_scope = ctx.scope.traits_in_scope(); 158 let traits_in_scope = ctx.scope.traits_in_scope();
@@ -162,11 +165,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
162 // We might iterate candidates of a trait multiple times here, so deduplicate 165 // We might iterate candidates of a trait multiple times here, so deduplicate
163 // them. 166 // them.
164 if seen.insert(item) { 167 if seen.insert(item) {
165 match item { 168 add_assoc_item(acc, ctx, item);
166 hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
167 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
168 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
169 }
170 } 169 }
171 None::<()> 170 None::<()>
172 }); 171 });
@@ -176,10 +175,22 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
176 } 175 }
177} 176}
178 177
179fn add_enum_variants(ctx: &CompletionContext, acc: &mut Completions, e: hir::Enum) { 178fn add_assoc_item(acc: &mut Completions, ctx: &CompletionContext, item: hir::AssocItem) {
180 for variant in e.variants(ctx.db) { 179 match item {
181 acc.add_enum_variant(ctx, variant, None); 180 hir::AssocItem::Function(func) if !ctx.expects_type() => acc.add_function(ctx, func, None),
181 hir::AssocItem::Const(ct) if !ctx.expects_type() || ctx.expects_generic_arg() => {
182 acc.add_const(ctx, ct)
183 }
184 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
185 _ => (),
186 }
187}
188
189fn add_enum_variants(acc: &mut Completions, ctx: &CompletionContext, e: hir::Enum) {
190 if ctx.expects_type() {
191 return;
182 } 192 }
193 e.variants(ctx.db).into_iter().for_each(|variant| acc.add_enum_variant(ctx, variant, None));
183} 194}
184 195
185#[cfg(test)] 196#[cfg(test)]
@@ -927,4 +938,24 @@ fn main() {
927 "#]], 938 "#]],
928 ); 939 );
929 } 940 }
941
942 #[test]
943 fn completes_types_and_const_in_arg_list() {
944 check(
945 r#"
946mod foo {
947 pub const CONST: () = ();
948 pub type Type = ();
949}
950
951struct Foo<T>(t);
952
953fn foo(_: Foo<foo::$0>) {}
954"#,
955 expect![[r#"
956 ta Type
957 ct CONST
958 "#]],
959 );
960 }
930} 961}
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index f86b2d3f3..b5af1c810 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -36,12 +36,14 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
36 return; 36 return;
37 } 37 }
38 38
39 if let Some(hir::Adt::Enum(e)) = 39 if !ctx.expects_type() {
40 ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt()) 40 if let Some(hir::Adt::Enum(e)) =
41 { 41 ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
42 super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| { 42 {
43 acc.add_qualified_enum_variant(ctx, variant, path) 43 super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| {
44 }); 44 acc.add_qualified_enum_variant(ctx, variant, path)
45 });
46 }
45 } 47 }
46 48
47 if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location { 49 if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
@@ -59,12 +61,25 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
59 } 61 }
60 62
61 ctx.scope.process_all_names(&mut |name, res| { 63 ctx.scope.process_all_names(&mut |name, res| {
62 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { 64 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) =
65 res
66 {
63 cov_mark::hit!(skip_lifetime_completion); 67 cov_mark::hit!(skip_lifetime_completion);
64 return; 68 return;
65 } 69 }
66 let add_resolution = match res { 70 let add_resolution = match res {
71 // Don't suggest attribute macros and derives.
67 ScopeDef::MacroDef(mac) => mac.is_fn_like(), 72 ScopeDef::MacroDef(mac) => mac.is_fn_like(),
73 // no values in type places
74 ScopeDef::ModuleDef(hir::ModuleDef::Function(_))
75 | ScopeDef::ModuleDef(hir::ModuleDef::Variant(_))
76 | ScopeDef::ModuleDef(hir::ModuleDef::Static(_))
77 | ScopeDef::Local(_) => !ctx.expects_type(),
78 // unless its a constant in a generic arg list position
79 ScopeDef::ModuleDef(hir::ModuleDef::Const(_))
80 | ScopeDef::GenericParam(hir::GenericParam::ConstParam(_)) => {
81 !ctx.expects_type() || ctx.expects_generic_arg()
82 }
68 _ => true, 83 _ => true,
69 }; 84 };
70 if add_resolution { 85 if add_resolution {
@@ -794,36 +809,27 @@ $0
794 } 809 }
795 810
796 #[test] 811 #[test]
797 fn completes_assoc_types_in_dynimpl_trait() { 812 fn completes_types_and_const_in_arg_list() {
798 check( 813 check(
799 r#" 814 r#"
800trait Foo { 815enum Bar {
801 type Bar; 816 Baz
802} 817}
803
804fn foo(_: impl Foo<B$0>) {}
805"#,
806 expect![[r#"
807 ta Bar = type Bar;
808 tt Foo
809 "#]],
810 );
811 }
812
813 #[test]
814 fn completes_assoc_types_in_trait_bound() {
815 check(
816 r#"
817trait Foo { 818trait Foo {
818 type Bar; 819 type Bar;
819} 820}
820 821
821fn foo<T: Foo<B$0>>(_: T) {} 822const CONST: () = ();
823
824fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {}
822"#, 825"#,
823 expect![[r#" 826 expect![[r#"
824 ta Bar = type Bar; 827 ta Bar = type Bar;
825 tp T 828 tp T
829 cp CONST_PARAM
826 tt Foo 830 tt Foo
831 en Bar
832 ct CONST
827 "#]], 833 "#]],
828 ); 834 );
829 } 835 }
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 4c3929a26..a8437d81c 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -276,6 +276,10 @@ impl<'a> CompletionContext<'a> {
276 matches!(self.completion_location, Some(ImmediateLocation::ItemList)) 276 matches!(self.completion_location, Some(ImmediateLocation::ItemList))
277 } 277 }
278 278
279 pub(crate) fn expects_generic_arg(&self) -> bool {
280 matches!(self.completion_location, Some(ImmediateLocation::GenericArgList(_)))
281 }
282
279 pub(crate) fn has_block_expr_parent(&self) -> bool { 283 pub(crate) fn has_block_expr_parent(&self) -> bool {
280 matches!(self.completion_location, Some(ImmediateLocation::BlockExpr)) 284 matches!(self.completion_location, Some(ImmediateLocation::BlockExpr))
281 } 285 }
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index d8ca18c73..add296124 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -55,9 +55,6 @@ pub(crate) fn render_resolution_with_import(
55 import_edit: ImportEdit, 55 import_edit: ImportEdit,
56) -> Option<CompletionItem> { 56) -> Option<CompletionItem> {
57 let resolution = hir::ScopeDef::from(import_edit.import.original_item); 57 let resolution = hir::ScopeDef::from(import_edit.import.original_item);
58 if ctx.completion.expects_type() && resolution.is_value_def() {
59 return None;
60 }
61 let local_name = match resolution { 58 let local_name = match resolution {
62 hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), 59 hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
63 hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, 60 hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,