about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-07-02 17:18:24 +0000
committerbors <bors@rust-lang.org>2022-07-02 17:18:24 +0000
commitd101439c77c6842e41e04f1438eb1d93095dea52 (patch)
treeafe4ffb14867243a092076b523217b5d704f4eb5
parent30680df3ccf035afc30952ab6660a262c3eac6af (diff)
parentea7ea7079cd8cf030ccd9b8c5e522165eace58c5 (diff)
downloadrust-d101439c77c6842e41e04f1438eb1d93095dea52.tar.gz
rust-d101439c77c6842e41e04f1438eb1d93095dea52.zip
Auto merge of #12627 - yue4u:fix/struct-variant-patterns, r=Veykril
fix: complete enum variants as patterns in pattern path

close #12593
-rw-r--r--crates/ide-completion/src/completions.rs6
-rw-r--r--crates/ide-completion/src/completions/expr.rs1
-rw-r--r--crates/ide-completion/src/completions/pattern.rs1
-rw-r--r--crates/ide-completion/src/completions/use_.rs4
-rw-r--r--crates/ide-completion/src/render/pattern.rs41
-rw-r--r--crates/ide-completion/src/tests/fn_param.rs2
-rw-r--r--crates/ide-completion/src/tests/pattern.rs137
-rw-r--r--crates/ide-completion/src/tests/special.rs1
-rw-r--r--crates/ide-completion/src/tests/use_tree.rs23
9 files changed, 140 insertions, 76 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 81bb59681ba..1bcbb3aaa65 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -357,6 +357,12 @@ impl Completions {
         variant: hir::Variant,
         local_name: Option<hir::Name>,
     ) {
+        if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }, .. } = path_ctx {
+            cov_mark::hit!(enum_variant_pattern_path);
+            self.add_variant_pat(ctx, pat_ctx, variant, local_name);
+            return;
+        }
+
         if let Some(builder) =
             render_variant_lit(RenderContext::new(ctx), path_ctx, local_name, variant, None)
         {
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index 058d0ab7bb5..df0556ba451 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -115,6 +115,7 @@ pub(crate) fn complete_expr_path(
                     };
 
                     if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
+                        cov_mark::hit!(completes_variant_through_self);
                         acc.add_enum_variants(ctx, path_ctx, e);
                     }
 
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 7a344c2c7b3..65b6eee1888 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -151,7 +151,6 @@ pub(crate) fn complete_pattern_path(
                     };
 
                     if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
-                        cov_mark::hit!(enum_plain_qualified_use_tree);
                         acc.add_enum_variants(ctx, path_ctx, e);
                     }
 
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index c98590f1361..e5689f332dd 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -79,9 +79,7 @@ pub(crate) fn complete_use_path(
                 }
                 hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
                     cov_mark::hit!(enum_plain_qualified_use_tree);
-                    e.variants(ctx.db)
-                        .into_iter()
-                        .for_each(|variant| acc.add_enum_variant(ctx, path_ctx, variant, None));
+                    acc.add_enum_variants(ctx, path_ctx, *e);
                 }
                 _ => {}
             }
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index f9c4037dee4..d6779961c07 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -7,7 +7,10 @@ use syntax::SmolStr;
 
 use crate::{
     context::{ParamKind, PatternContext},
-    render::{variant::visible_fields, RenderContext},
+    render::{
+        variant::{format_literal_label, visible_fields},
+        RenderContext,
+    },
     CompletionItem, CompletionItemKind,
 };
 
@@ -29,16 +32,11 @@ pub(crate) fn render_struct_pat(
 
     let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
     let (name, escaped_name) = (name.to_smol_str(), name.escaped().to_smol_str());
-    let pat = render_pat(
-        &ctx,
-        pattern_ctx,
-        &escaped_name,
-        strukt.kind(ctx.db()),
-        &visible_fields,
-        fields_omitted,
-    )?;
+    let kind = strukt.kind(ctx.db());
+    let label = format_literal_label(name.as_str(), kind);
+    let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
 
-    Some(build_completion(ctx, name, pat, strukt))
+    Some(build_completion(ctx, label, pat, strukt))
 }
 
 pub(crate) fn render_variant_pat(
@@ -60,25 +58,20 @@ pub(crate) fn render_variant_pat(
             (name.to_smol_str(), name.escaped().to_smol_str())
         }
     };
-    let pat = render_pat(
-        &ctx,
-        pattern_ctx,
-        &escaped_name,
-        variant.kind(ctx.db()),
-        &visible_fields,
-        fields_omitted,
-    )?;
+    let kind = variant.kind(ctx.db());
+    let label = format_literal_label(name.as_str(), kind);
+    let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
 
-    Some(build_completion(ctx, name, pat, variant))
+    Some(build_completion(ctx, label, pat, variant))
 }
 
 fn build_completion(
     ctx: RenderContext<'_>,
-    name: SmolStr,
+    label: SmolStr,
     pat: String,
     def: impl HasAttrs + Copy,
 ) -> CompletionItem {
-    let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), name);
+    let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
     item.set_documentation(ctx.docs(def))
         .set_deprecated(ctx.is_deprecated(def))
         .detail(&pat)
@@ -103,7 +96,7 @@ fn render_pat(
         StructKind::Record => {
             render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted)
         }
-        StructKind::Unit => return None,
+        StructKind::Unit => name.to_string(),
     };
 
     let needs_ascription = matches!(
@@ -138,7 +131,7 @@ fn render_record_as_pat(
             format!(
                 "{name} {{ {}{} }}",
                 fields.enumerate().format_with(", ", |(idx, field), f| {
-                    f(&format_args!("{}${}", field.name(db), idx + 1))
+                    f(&format_args!("{}${}", field.name(db).escaped(), idx + 1))
                 }),
                 if fields_omitted { ", .." } else { "" },
                 name = name
@@ -147,7 +140,7 @@ fn render_record_as_pat(
         None => {
             format!(
                 "{name} {{ {}{} }}",
-                fields.map(|field| field.name(db)).format(", "),
+                fields.map(|field| field.name(db).escaped().to_smol_str()).format(", "),
                 if fields_omitted { ", .." } else { "" },
                 name = name
             )
diff --git a/crates/ide-completion/src/tests/fn_param.rs b/crates/ide-completion/src/tests/fn_param.rs
index f5a5b5bae6a..cce74604c2d 100644
--- a/crates/ide-completion/src/tests/fn_param.rs
+++ b/crates/ide-completion/src/tests/fn_param.rs
@@ -139,8 +139,8 @@ fn foo2($0) {}
 "#,
         expect![[r#"
             st Bar
-            bn Bar              Bar { bar$1 }: Bar$0
             bn Bar { bar }: Bar
+            bn Bar {…}          Bar { bar$1 }: Bar$0
             kw mut
             kw ref
         "#]],
diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs
index 7169209d810..63ccf9003b4 100644
--- a/crates/ide-completion/src/tests/pattern.rs
+++ b/crates/ide-completion/src/tests/pattern.rs
@@ -1,7 +1,7 @@
 //! Completion tests for pattern position.
 use expect_test::{expect, Expect};
 
-use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
+use crate::tests::{check_edit, completion_list, BASE_ITEMS_FIXTURE};
 
 fn check_empty(ra_fixture: &str, expect: Expect) {
     let actual = completion_list(ra_fixture);
@@ -127,15 +127,15 @@ fn foo() {
         expect![[r#"
             ct CONST
             en Enum
-            ma makro!(…) macro_rules! makro
+            ma makro!(…)  macro_rules! makro
             md module
             st Record
             st Tuple
             st Unit
             ev TupleV
-            bn Record    Record { field$1 }$0
-            bn Tuple     Tuple($1)$0
-            bn TupleV    TupleV($1)$0
+            bn Record {…} Record { field$1 }$0
+            bn Tuple(…)   Tuple($1)$0
+            bn TupleV(…)  TupleV($1)$0
             kw mut
             kw ref
         "#]],
@@ -162,8 +162,9 @@ fn foo() {
             st Tuple
             st Unit
             ev Variant
-            bn Record            Record { field$1 }$0
-            bn Tuple             Tuple($1)$0
+            bn Record {…}        Record { field$1 }$0
+            bn Tuple(…)          Tuple($1)$0
+            bn Variant           Variant$0
             kw mut
             kw ref
         "#]],
@@ -178,13 +179,13 @@ fn foo(a$0) {
 }
 "#,
         expect![[r#"
-            ma makro!(…) macro_rules! makro
+            ma makro!(…)  macro_rules! makro
             md module
             st Record
             st Tuple
             st Unit
-            bn Record    Record { field$1 }: Record$0
-            bn Tuple     Tuple($1): Tuple$0
+            bn Record {…} Record { field$1 }: Record$0
+            bn Tuple(…)   Tuple($1): Tuple$0
             kw mut
             kw ref
         "#]],
@@ -195,13 +196,13 @@ fn foo(a$0: Tuple) {
 }
 "#,
         expect![[r#"
-            ma makro!(…) macro_rules! makro
+            ma makro!(…)  macro_rules! makro
             md module
             st Record
             st Tuple
             st Unit
-            bn Record    Record { field$1 }$0
-            bn Tuple     Tuple($1)$0
+            bn Record {…} Record { field$1 }$0
+            bn Tuple(…)   Tuple($1)$0
             kw mut
             kw ref
         "#]],
@@ -243,6 +244,7 @@ fn foo() {
         expect![[r#"
             en E
             ma m!(…) macro_rules! m
+            bn E::X  E::X$0
             kw mut
             kw ref
         "#]],
@@ -269,8 +271,8 @@ fn outer() {
             st Invisible
             st Record
             st Tuple
-            bn Record    Record { field$1, .. }$0
-            bn Tuple     Tuple($1, ..)$0
+            bn Record {…} Record { field$1, .. }$0
+            bn Tuple(…)   Tuple($1, ..)$0
             kw mut
             kw ref
         "#]],
@@ -293,8 +295,8 @@ impl Foo {
         expect![[r#"
             sp Self
             st Foo
-            bn Foo  Foo($1)$0
-            bn Self Self($1)$0
+            bn Foo(…)  Foo($1)$0
+            bn Self(…) Self($1)$0
             kw mut
             kw ref
         "#]],
@@ -316,9 +318,9 @@ fn func() {
 "#,
         expect![[r#"
             ct ASSOC_CONST const ASSOC_CONST: ()
-            ev RecordV {…} RecordV { field: u32 }
-            ev TupleV(…)   TupleV(u32)
-            ev UnitV       UnitV
+            bn RecordV {…} RecordV { field$1 }$0
+            bn TupleV(…)   TupleV($1)$0
+            bn UnitV       UnitV$0
         "#]],
     );
 }
@@ -334,8 +336,8 @@ fn outer(Foo { bar: $0 }: Foo) {}
         expect![[r#"
             st Bar
             st Foo
-            bn Bar Bar($1)$0
-            bn Foo Foo { bar$1 }$0
+            bn Bar(…)  Bar($1)$0
+            bn Foo {…} Foo { bar$1 }$0
             kw mut
             kw ref
         "#]],
@@ -368,8 +370,8 @@ fn foo($0) {}
         expect![[r#"
             st Bar
             st Foo
-            bn Bar Bar($1): Bar$0
-            bn Foo Foo { bar$1 }: Foo$0
+            bn Bar(…)  Bar($1): Bar$0
+            bn Foo {…} Foo { bar$1 }: Foo$0
             kw mut
             kw ref
         "#]],
@@ -389,8 +391,8 @@ fn foo() {
         expect![[r#"
             st Bar
             st Foo
-            bn Bar Bar($1)$0
-            bn Foo Foo { bar$1 }$0
+            bn Bar(…)  Bar($1)$0
+            bn Foo {…} Foo { bar$1 }$0
             kw mut
             kw ref
         "#]],
@@ -443,7 +445,7 @@ fn foo() {
 }
 "#,
         expect![[r#"
-            ev TupleVariant TupleVariant
+            bn TupleVariant(…) TupleVariant($1)$0
         "#]],
     );
     check_empty(
@@ -458,7 +460,86 @@ fn foo() {
 }
 "#,
         expect![[r#"
-            ev RecordVariant RecordVariant
+            bn RecordVariant {…} RecordVariant { field$1 }$0
+        "#]],
+    );
+}
+
+#[test]
+fn completes_enum_variant_pat() {
+    cov_mark::check!(enum_variant_pattern_path);
+    check_edit(
+        "RecordVariant {…}",
+        r#"
+enum Enum {
+    RecordVariant { field: u32 }
+}
+fn foo() {
+    match (Enum::RecordVariant { field: 0 }) {
+        Enum::RecordV$0
+    }
+}
+"#,
+        r#"
+enum Enum {
+    RecordVariant { field: u32 }
+}
+fn foo() {
+    match (Enum::RecordVariant { field: 0 }) {
+        Enum::RecordVariant { field$1 }$0
+    }
+}
+"#,
+    );
+}
+
+#[test]
+fn completes_enum_variant_pat_escape() {
+    cov_mark::check!(enum_variant_pattern_path);
+    check_empty(
+        r#"
+enum Enum {
+    A,
+    B { r#type: i32 },
+    r#type,
+    r#struct { r#type: i32 },
+}
+fn foo() {
+    match (Enum::A) {
+        $0
+    }
+}
+"#,
+        expect![[r#"
+            en Enum
+            bn Enum::A          Enum::A$0
+            bn Enum::B {…}      Enum::B { r#type$1 }$0
+            bn Enum::struct {…} Enum::r#struct { r#type$1 }$0
+            bn Enum::type       Enum::r#type$0
+            kw mut
+            kw ref
+        "#]],
+    );
+
+    check_empty(
+        r#"
+enum Enum {
+    A,
+    B { r#type: i32 },
+    r#type,
+    r#struct { r#type: i32 },
+}
+fn foo() {
+    match (Enum::A) {
+        Enum::$0
+    }
+}
+"#,
+        expect![[r#"
+            bn A          A$0
+            bn B {…}      B { r#type$1 }$0
+            bn struct {…} r#struct { r#type$1 }$0
+            bn type       r#type$0
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index 96d0219fef6..fc59f781dd3 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -519,6 +519,7 @@ fn foo() {
 
 #[test]
 fn completes_variant_through_self() {
+    cov_mark::check!(completes_variant_through_self);
     check(
         r#"
 enum Foo {
diff --git a/crates/ide-completion/src/tests/use_tree.rs b/crates/ide-completion/src/tests/use_tree.rs
index 3134915bdab..109007c7a07 100644
--- a/crates/ide-completion/src/tests/use_tree.rs
+++ b/crates/ide-completion/src/tests/use_tree.rs
@@ -165,30 +165,15 @@ fn enum_plain_qualified_use_tree() {
         r#"
 use Foo::$0
 
-enum Foo { Variant }
-impl Foo {
-    const CONST: () = ()
-    fn func() {}
-}
-"#,
-        expect![[r#"
-            ev Variant Variant
-        "#]],
-    );
-}
-
-#[test]
-fn enum_no_parens_in_qualified_use_tree() {
-    cov_mark::check!(enum_plain_qualified_use_tree);
-    check(
-        r#"
-use Foo::$0
-
 enum Foo {
     UnitVariant,
     TupleVariant(),
     RecordVariant {},
 }
+impl Foo {
+    const CONST: () = ()
+    fn func() {}
+}
 "#,
         expect![[r#"
             ev RecordVariant RecordVariant