diff options
Diffstat (limited to 'crates/ide_completion/src/completions/qualified_path.rs')
-rw-r--r-- | crates/ide_completion/src/completions/qualified_path.rs | 85 |
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 | ||
179 | fn add_enum_variants(ctx: &CompletionContext, acc: &mut Completions, e: hir::Enum) { | 178 | fn 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 | |||
189 | fn 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#" | ||
946 | mod foo { | ||
947 | pub const CONST: () = (); | ||
948 | pub type Type = (); | ||
949 | } | ||
950 | |||
951 | struct Foo<T>(t); | ||
952 | |||
953 | fn foo(_: Foo<foo::$0>) {} | ||
954 | "#, | ||
955 | expect![[r#" | ||
956 | ta Type | ||
957 | ct CONST | ||
958 | "#]], | ||
959 | ); | ||
960 | } | ||
930 | } | 961 | } |