aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/completions/qualified_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/completions/qualified_path.rs')
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs85
1 files changed, 58 insertions, 27 deletions
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}