diff options
Diffstat (limited to 'crates/completion/src/completions.rs')
-rw-r--r-- | crates/completion/src/completions.rs | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs index c3ce6e51d..3b582ed07 100644 --- a/crates/completion/src/completions.rs +++ b/crates/completion/src/completions.rs | |||
@@ -15,7 +15,9 @@ pub(crate) mod trait_impl; | |||
15 | pub(crate) mod mod_; | 15 | pub(crate) mod mod_; |
16 | pub(crate) mod flyimport; | 16 | pub(crate) mod flyimport; |
17 | 17 | ||
18 | use hir::{ModPath, ScopeDef, Type}; | 18 | use std::iter; |
19 | |||
20 | use hir::{known, ModPath, ScopeDef, Type}; | ||
19 | 21 | ||
20 | use crate::{ | 22 | use crate::{ |
21 | item::Builder, | 23 | item::Builder, |
@@ -118,7 +120,18 @@ impl Completions { | |||
118 | variant: hir::Variant, | 120 | variant: hir::Variant, |
119 | local_name: Option<hir::Name>, | 121 | local_name: Option<hir::Name>, |
120 | ) { | 122 | ) { |
121 | if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name) { | 123 | if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name, None) { |
124 | self.add(item); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | pub(crate) fn add_qualified_variant_pat( | ||
129 | &mut self, | ||
130 | ctx: &CompletionContext, | ||
131 | variant: hir::Variant, | ||
132 | path: ModPath, | ||
133 | ) { | ||
134 | if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, None, Some(path)) { | ||
122 | self.add(item); | 135 | self.add(item); |
123 | } | 136 | } |
124 | } | 137 | } |
@@ -166,3 +179,46 @@ impl Completions { | |||
166 | self.add(item); | 179 | self.add(item); |
167 | } | 180 | } |
168 | } | 181 | } |
182 | |||
183 | fn complete_enum_variants( | ||
184 | acc: &mut Completions, | ||
185 | ctx: &CompletionContext, | ||
186 | ty: &hir::Type, | ||
187 | cb: impl Fn(&mut Completions, &CompletionContext, hir::Variant, hir::ModPath), | ||
188 | ) { | ||
189 | if let Some(hir::Adt::Enum(enum_data)) = | ||
190 | iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt()) | ||
191 | { | ||
192 | let variants = enum_data.variants(ctx.db); | ||
193 | |||
194 | let module = if let Some(module) = ctx.scope.module() { | ||
195 | // Compute path from the completion site if available. | ||
196 | module | ||
197 | } else { | ||
198 | // Otherwise fall back to the enum's definition site. | ||
199 | enum_data.module(ctx.db) | ||
200 | }; | ||
201 | |||
202 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { | ||
203 | if impl_.target_ty(ctx.db) == *ty { | ||
204 | for &variant in &variants { | ||
205 | let self_path = hir::ModPath::from_segments( | ||
206 | hir::PathKind::Plain, | ||
207 | iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), | ||
208 | ); | ||
209 | cb(acc, ctx, variant, self_path); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | for variant in variants { | ||
215 | if let Some(path) = module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) { | ||
216 | // Variants with trivial paths are already added by the existing completion logic, | ||
217 | // so we should avoid adding these twice | ||
218 | if path.segments().len() > 1 { | ||
219 | cb(acc, ctx, variant, path); | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | } | ||