Repository: rust-analyzer/rust-analyzer
Pull request #11785 (2022-03-21 20:46:02)

fix: Fix tuple- and record struct completions not working with existing braces
bors r+

bors[bot]: Build failed:
  * [Rust (ubuntu-latest)](https://github.com/rust-analyzer/rust-analyzer/runs/5634455890?check_suite_focus=true)

Patch:
diff --git a/crates/ide_completion/src/render/literal.rs b/crates/ide_completion/src/render/literal.rs
index d91e80f90c..e65631712e 100644
--- a/crates/ide_completion/src/render/literal.rs
+++ b/crates/ide_completion/src/render/literal.rs
@@ -49,12 +49,12 @@ fn render(
     name: hir::Name,
     path: Option<hir::ModPath>,
 ) -> Option<CompletionItem> {
-    if let Some(PathCompletionCtx { has_call_parens: true, .. }) = completion.path_context {
-        return None;
-    }
     let db = completion.db;
-    let fields = thing.fields(completion)?;
+    let kind = thing.kind(db);
+    let has_call_parens =
+        matches!(completion.path_context, Some(PathCompletionCtx { has_call_parens: true, .. }));
 
+    let fields = thing.fields(completion)?;
     let (qualified_name, short_qualified_name, qualified) = match path {
         Some(path) => {
             let short = hir::ModPath::from_segments(
@@ -68,13 +68,14 @@ fn render(
     let qualified_name = qualified_name.to_string();
     let snippet_cap = ctx.snippet_cap();
 
-    let kind = thing.kind(db);
     let mut rendered = match kind {
-        StructKind::Tuple => render_tuple_lit(db, snippet_cap, &fields, &qualified_name),
-        StructKind::Record => render_record_lit(db, snippet_cap, &fields, &qualified_name),
-        StructKind::Unit => {
-            RenderedLiteral { literal: qualified_name.clone(), detail: qualified_name.clone() }
+        StructKind::Tuple if !has_call_parens => {
+            render_tuple_lit(db, snippet_cap, &fields, &qualified_name)
+        }
+        StructKind::Record if !has_call_parens => {
+            render_record_lit(db, snippet_cap, &fields, &qualified_name)
         }
+        _ => RenderedLiteral { literal: qualified_name.clone(), detail: qualified_name.clone() },
     };
 
     if snippet_cap.is_some() {
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs
index efceb85718..ff61bf61c5 100644
--- a/crates/ide_completion/src/render/pattern.rs
+++ b/crates/ide_completion/src/render/pattern.rs
@@ -6,7 +6,7 @@ use itertools::Itertools;
 use syntax::SmolStr;
 
 use crate::{
-    context::{ParamKind, PatternContext},
+    context::{ParamKind, PathCompletionCtx, PatternContext},
     render::{variant::visible_fields, RenderContext},
     CompletionItem, CompletionItemKind,
 };
@@ -77,12 +77,19 @@ fn render_pat(
     fields: &[hir::Field],
     fields_omitted: bool,
 ) -> Option<String> {
+    let has_call_parens = matches!(
+        ctx.completion.path_context,
+        Some(PathCompletionCtx { has_call_parens: true, .. })
+    );
     let mut pat = match kind {
-        StructKind::Tuple => render_tuple_as_pat(ctx.snippet_cap(), fields, name, fields_omitted),
-        StructKind::Record => {
+        StructKind::Tuple if !has_call_parens => {
+            render_tuple_as_pat(ctx.snippet_cap(), fields, name, fields_omitted)
+        }
+        StructKind::Record if !has_call_parens => {
             render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted)
         }
-        _ => return None,
+        StructKind::Unit => return None,
+        _ => name.to_owned(),
     };
 
     if matches!(
@@ -91,7 +98,7 @@ fn render_pat(
             param_ctx: Some((.., ParamKind::Function(_))),
             has_type_ascription: false,
             ..
-        })
+        }) if !has_call_parens
     ) {
         pat.push(':');
         pat.push(' ');


Test patch:
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index bb8b34b79a..f38c504fab 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -552,3 +552,24 @@ fn func() {
         "#]],
     );
 }
+
+#[test]
+fn with_parens() {
+    check_empty(
+        r#"
+enum Enum {
+    Variant()
+}
+impl Enum {
+    fn variant() -> Self { Enum::Variant() }
+}
+fn func() {
+    Enum::$0()
+}
+"#,
+        expect![[r#"
+            ev Variant(…) Variant
+            fn variant    fn() -> Enum
+        "#]],
+    );
+}
diff --git a/crates/ide_completion/src/tests/pattern.rs b/crates/ide_completion/src/tests/pattern.rs
index 405a128b7e..3b59263528 100644
--- a/crates/ide_completion/src/tests/pattern.rs
+++ b/crates/ide_completion/src/tests/pattern.rs
@@ -429,7 +429,9 @@ fn foo() {
     }
 }
 "#,
-        expect![[r#""#]],
+        expect![[r#"
+            ev TupleVariant(…) TupleVariant
+        "#]],
     );
     check_empty(
         r#"
@@ -442,7 +444,9 @@ fn foo() {
     }
 }
 "#,
-        expect![[r#""#]],
+        expect![[r#"
+            ev RecordVariant {…} RecordVariant
+        "#]],
     );
 }