aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/completions/unqualified_path.rs
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-02-09 20:32:05 +0000
committerLukas Wirth <[email protected]>2021-02-09 20:35:02 +0000
commit5454559c0a45d208db963df105f22f5e17f0340a (patch)
tree6038de6fd6a16ad6edef22a4bef9bd323071dc99 /crates/completion/src/completions/unqualified_path.rs
parent5d4ae1c8e3b76798fcb5eb656d886fe65a2c7277 (diff)
Show qualified variant pattern completions
Diffstat (limited to 'crates/completion/src/completions/unqualified_path.rs')
-rw-r--r--crates/completion/src/completions/unqualified_path.rs46
1 files changed, 4 insertions, 42 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 5112ecc2d..e9d0ff665 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,8 +1,6 @@
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 std::iter; 3use hir::ScopeDef;
4
5use hir::{known, Adt, ModuleDef, ScopeDef, Type};
6use syntax::AstNode; 4use syntax::AstNode;
7use test_utils::mark; 5use test_utils::mark;
8 6
@@ -21,7 +19,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
21 } 19 }
22 20
23 if let Some(ty) = &ctx.expected_type { 21 if let Some(ty) = &ctx.expected_type {
24 complete_enum_variants(acc, ctx, ty); 22 super::complete_enum_variants(acc, ctx, ty, |acc, ctx, variant, path| {
23 acc.add_qualified_enum_variant(ctx, variant, path)
24 });
25 } 25 }
26 26
27 if ctx.is_pat_binding_or_const { 27 if ctx.is_pat_binding_or_const {
@@ -45,44 +45,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
45 }); 45 });
46} 46}
47 47
48fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
49 if let Some(Adt::Enum(enum_data)) =
50 iter::successors(Some(ty.clone()), |ty| ty.remove_ref()).last().and_then(|ty| ty.as_adt())
51 {
52 let variants = enum_data.variants(ctx.db);
53
54 let module = if let Some(module) = ctx.scope.module() {
55 // Compute path from the completion site if available.
56 module
57 } else {
58 // Otherwise fall back to the enum's definition site.
59 enum_data.module(ctx.db)
60 };
61
62 if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
63 if impl_.target_ty(ctx.db) == *ty {
64 for &variant in &variants {
65 let self_path = hir::ModPath::from_segments(
66 hir::PathKind::Plain,
67 iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
68 );
69 acc.add_qualified_enum_variant(ctx, variant, self_path.clone());
70 }
71 }
72 }
73
74 for variant in variants {
75 if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
76 // Variants with trivial paths are already added by the existing completion logic,
77 // so we should avoid adding these twice
78 if path.segments().len() > 1 {
79 acc.add_qualified_enum_variant(ctx, variant, path);
80 }
81 }
82 }
83 }
84}
85
86#[cfg(test)] 48#[cfg(test)]
87mod tests { 49mod tests {
88 use expect_test::{expect, Expect}; 50 use expect_test::{expect, Expect};