Skip to content

Commit d101439

Browse files
committed
Auto merge of rust-lang#12627 - yue4u:fix/struct-variant-patterns, r=Veykril
fix: complete enum variants as patterns in pattern path close rust-lang#12593
2 parents 30680df + ea7ea70 commit d101439

File tree

9 files changed

+140
-76
lines changed

9 files changed

+140
-76
lines changed

crates/ide-completion/src/completions.rs

+6
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,12 @@ impl Completions {
357357
variant: hir::Variant,
358358
local_name: Option<hir::Name>,
359359
) {
360+
if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }, .. } = path_ctx {
361+
cov_mark::hit!(enum_variant_pattern_path);
362+
self.add_variant_pat(ctx, pat_ctx, variant, local_name);
363+
return;
364+
}
365+
360366
if let Some(builder) =
361367
render_variant_lit(RenderContext::new(ctx), path_ctx, local_name, variant, None)
362368
{

crates/ide-completion/src/completions/expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ pub(crate) fn complete_expr_path(
115115
};
116116

117117
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
118+
cov_mark::hit!(completes_variant_through_self);
118119
acc.add_enum_variants(ctx, path_ctx, e);
119120
}
120121

crates/ide-completion/src/completions/pattern.rs

-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ pub(crate) fn complete_pattern_path(
151151
};
152152

153153
if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
154-
cov_mark::hit!(enum_plain_qualified_use_tree);
155154
acc.add_enum_variants(ctx, path_ctx, e);
156155
}
157156

crates/ide-completion/src/completions/use_.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ pub(crate) fn complete_use_path(
7979
}
8080
hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
8181
cov_mark::hit!(enum_plain_qualified_use_tree);
82-
e.variants(ctx.db)
83-
.into_iter()
84-
.for_each(|variant| acc.add_enum_variant(ctx, path_ctx, variant, None));
82+
acc.add_enum_variants(ctx, path_ctx, *e);
8583
}
8684
_ => {}
8785
}

crates/ide-completion/src/render/pattern.rs

+17-24
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ use syntax::SmolStr;
77

88
use crate::{
99
context::{ParamKind, PatternContext},
10-
render::{variant::visible_fields, RenderContext},
10+
render::{
11+
variant::{format_literal_label, visible_fields},
12+
RenderContext,
13+
},
1114
CompletionItem, CompletionItemKind,
1215
};
1316

@@ -29,16 +32,11 @@ pub(crate) fn render_struct_pat(
2932

3033
let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
3134
let (name, escaped_name) = (name.to_smol_str(), name.escaped().to_smol_str());
32-
let pat = render_pat(
33-
&ctx,
34-
pattern_ctx,
35-
&escaped_name,
36-
strukt.kind(ctx.db()),
37-
&visible_fields,
38-
fields_omitted,
39-
)?;
35+
let kind = strukt.kind(ctx.db());
36+
let label = format_literal_label(name.as_str(), kind);
37+
let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
4038

41-
Some(build_completion(ctx, name, pat, strukt))
39+
Some(build_completion(ctx, label, pat, strukt))
4240
}
4341

4442
pub(crate) fn render_variant_pat(
@@ -60,25 +58,20 @@ pub(crate) fn render_variant_pat(
6058
(name.to_smol_str(), name.escaped().to_smol_str())
6159
}
6260
};
63-
let pat = render_pat(
64-
&ctx,
65-
pattern_ctx,
66-
&escaped_name,
67-
variant.kind(ctx.db()),
68-
&visible_fields,
69-
fields_omitted,
70-
)?;
61+
let kind = variant.kind(ctx.db());
62+
let label = format_literal_label(name.as_str(), kind);
63+
let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
7164

72-
Some(build_completion(ctx, name, pat, variant))
65+
Some(build_completion(ctx, label, pat, variant))
7366
}
7467

7568
fn build_completion(
7669
ctx: RenderContext<'_>,
77-
name: SmolStr,
70+
label: SmolStr,
7871
pat: String,
7972
def: impl HasAttrs + Copy,
8073
) -> CompletionItem {
81-
let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), name);
74+
let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
8275
item.set_documentation(ctx.docs(def))
8376
.set_deprecated(ctx.is_deprecated(def))
8477
.detail(&pat)
@@ -103,7 +96,7 @@ fn render_pat(
10396
StructKind::Record => {
10497
render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted)
10598
}
106-
StructKind::Unit => return None,
99+
StructKind::Unit => name.to_string(),
107100
};
108101

109102
let needs_ascription = matches!(
@@ -138,7 +131,7 @@ fn render_record_as_pat(
138131
format!(
139132
"{name} {{ {}{} }}",
140133
fields.enumerate().format_with(", ", |(idx, field), f| {
141-
f(&format_args!("{}${}", field.name(db), idx + 1))
134+
f(&format_args!("{}${}", field.name(db).escaped(), idx + 1))
142135
}),
143136
if fields_omitted { ", .." } else { "" },
144137
name = name
@@ -147,7 +140,7 @@ fn render_record_as_pat(
147140
None => {
148141
format!(
149142
"{name} {{ {}{} }}",
150-
fields.map(|field| field.name(db)).format(", "),
143+
fields.map(|field| field.name(db).escaped().to_smol_str()).format(", "),
151144
if fields_omitted { ", .." } else { "" },
152145
name = name
153146
)

crates/ide-completion/src/tests/fn_param.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ fn foo2($0) {}
139139
"#,
140140
expect![[r#"
141141
st Bar
142-
bn Bar Bar { bar$1 }: Bar$0
143142
bn Bar { bar }: Bar
143+
bn Bar {…} Bar { bar$1 }: Bar$0
144144
kw mut
145145
kw ref
146146
"#]],

crates/ide-completion/src/tests/pattern.rs

+109-28
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Completion tests for pattern position.
22
use expect_test::{expect, Expect};
33

4-
use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
4+
use crate::tests::{check_edit, completion_list, BASE_ITEMS_FIXTURE};
55

66
fn check_empty(ra_fixture: &str, expect: Expect) {
77
let actual = completion_list(ra_fixture);
@@ -127,15 +127,15 @@ fn foo() {
127127
expect![[r#"
128128
ct CONST
129129
en Enum
130-
ma makro!(…) macro_rules! makro
130+
ma makro!(…) macro_rules! makro
131131
md module
132132
st Record
133133
st Tuple
134134
st Unit
135135
ev TupleV
136-
bn Record Record { field$1 }$0
137-
bn Tuple Tuple($1)$0
138-
bn TupleV TupleV($1)$0
136+
bn Record {…} Record { field$1 }$0
137+
bn Tuple(…) Tuple($1)$0
138+
bn TupleV(…) TupleV($1)$0
139139
kw mut
140140
kw ref
141141
"#]],
@@ -162,8 +162,9 @@ fn foo() {
162162
st Tuple
163163
st Unit
164164
ev Variant
165-
bn Record Record { field$1 }$0
166-
bn Tuple Tuple($1)$0
165+
bn Record {…} Record { field$1 }$0
166+
bn Tuple(…) Tuple($1)$0
167+
bn Variant Variant$0
167168
kw mut
168169
kw ref
169170
"#]],
@@ -178,13 +179,13 @@ fn foo(a$0) {
178179
}
179180
"#,
180181
expect![[r#"
181-
ma makro!(…) macro_rules! makro
182+
ma makro!(…) macro_rules! makro
182183
md module
183184
st Record
184185
st Tuple
185186
st Unit
186-
bn Record Record { field$1 }: Record$0
187-
bn Tuple Tuple($1): Tuple$0
187+
bn Record {…} Record { field$1 }: Record$0
188+
bn Tuple(…) Tuple($1): Tuple$0
188189
kw mut
189190
kw ref
190191
"#]],
@@ -195,13 +196,13 @@ fn foo(a$0: Tuple) {
195196
}
196197
"#,
197198
expect![[r#"
198-
ma makro!(…) macro_rules! makro
199+
ma makro!(…) macro_rules! makro
199200
md module
200201
st Record
201202
st Tuple
202203
st Unit
203-
bn Record Record { field$1 }$0
204-
bn Tuple Tuple($1)$0
204+
bn Record {…} Record { field$1 }$0
205+
bn Tuple(…) Tuple($1)$0
205206
kw mut
206207
kw ref
207208
"#]],
@@ -243,6 +244,7 @@ fn foo() {
243244
expect![[r#"
244245
en E
245246
ma m!(…) macro_rules! m
247+
bn E::X E::X$0
246248
kw mut
247249
kw ref
248250
"#]],
@@ -269,8 +271,8 @@ fn outer() {
269271
st Invisible
270272
st Record
271273
st Tuple
272-
bn Record Record { field$1, .. }$0
273-
bn Tuple Tuple($1, ..)$0
274+
bn Record {…} Record { field$1, .. }$0
275+
bn Tuple(…) Tuple($1, ..)$0
274276
kw mut
275277
kw ref
276278
"#]],
@@ -293,8 +295,8 @@ impl Foo {
293295
expect![[r#"
294296
sp Self
295297
st Foo
296-
bn Foo Foo($1)$0
297-
bn Self Self($1)$0
298+
bn Foo(…) Foo($1)$0
299+
bn Self(…) Self($1)$0
298300
kw mut
299301
kw ref
300302
"#]],
@@ -316,9 +318,9 @@ fn func() {
316318
"#,
317319
expect![[r#"
318320
ct ASSOC_CONST const ASSOC_CONST: ()
319-
ev RecordV {…} RecordV { field: u32 }
320-
ev TupleV(…) TupleV(u32)
321-
ev UnitV UnitV
321+
bn RecordV {…} RecordV { field$1 }$0
322+
bn TupleV(…) TupleV($1)$0
323+
bn UnitV UnitV$0
322324
"#]],
323325
);
324326
}
@@ -334,8 +336,8 @@ fn outer(Foo { bar: $0 }: Foo) {}
334336
expect![[r#"
335337
st Bar
336338
st Foo
337-
bn Bar Bar($1)$0
338-
bn Foo Foo { bar$1 }$0
339+
bn Bar(…) Bar($1)$0
340+
bn Foo {…} Foo { bar$1 }$0
339341
kw mut
340342
kw ref
341343
"#]],
@@ -368,8 +370,8 @@ fn foo($0) {}
368370
expect![[r#"
369371
st Bar
370372
st Foo
371-
bn Bar Bar($1): Bar$0
372-
bn Foo Foo { bar$1 }: Foo$0
373+
bn Bar(…) Bar($1): Bar$0
374+
bn Foo {…} Foo { bar$1 }: Foo$0
373375
kw mut
374376
kw ref
375377
"#]],
@@ -389,8 +391,8 @@ fn foo() {
389391
expect![[r#"
390392
st Bar
391393
st Foo
392-
bn Bar Bar($1)$0
393-
bn Foo Foo { bar$1 }$0
394+
bn Bar(…) Bar($1)$0
395+
bn Foo {…} Foo { bar$1 }$0
394396
kw mut
395397
kw ref
396398
"#]],
@@ -443,7 +445,7 @@ fn foo() {
443445
}
444446
"#,
445447
expect![[r#"
446-
ev TupleVariant TupleVariant
448+
bn TupleVariant(…) TupleVariant($1)$0
447449
"#]],
448450
);
449451
check_empty(
@@ -458,7 +460,86 @@ fn foo() {
458460
}
459461
"#,
460462
expect![[r#"
461-
ev RecordVariant RecordVariant
463+
bn RecordVariant {…} RecordVariant { field$1 }$0
464+
"#]],
465+
);
466+
}
467+
468+
#[test]
469+
fn completes_enum_variant_pat() {
470+
cov_mark::check!(enum_variant_pattern_path);
471+
check_edit(
472+
"RecordVariant {…}",
473+
r#"
474+
enum Enum {
475+
RecordVariant { field: u32 }
476+
}
477+
fn foo() {
478+
match (Enum::RecordVariant { field: 0 }) {
479+
Enum::RecordV$0
480+
}
481+
}
482+
"#,
483+
r#"
484+
enum Enum {
485+
RecordVariant { field: u32 }
486+
}
487+
fn foo() {
488+
match (Enum::RecordVariant { field: 0 }) {
489+
Enum::RecordVariant { field$1 }$0
490+
}
491+
}
492+
"#,
493+
);
494+
}
495+
496+
#[test]
497+
fn completes_enum_variant_pat_escape() {
498+
cov_mark::check!(enum_variant_pattern_path);
499+
check_empty(
500+
r#"
501+
enum Enum {
502+
A,
503+
B { r#type: i32 },
504+
r#type,
505+
r#struct { r#type: i32 },
506+
}
507+
fn foo() {
508+
match (Enum::A) {
509+
$0
510+
}
511+
}
512+
"#,
513+
expect![[r#"
514+
en Enum
515+
bn Enum::A Enum::A$0
516+
bn Enum::B {…} Enum::B { r#type$1 }$0
517+
bn Enum::struct {…} Enum::r#struct { r#type$1 }$0
518+
bn Enum::type Enum::r#type$0
519+
kw mut
520+
kw ref
521+
"#]],
522+
);
523+
524+
check_empty(
525+
r#"
526+
enum Enum {
527+
A,
528+
B { r#type: i32 },
529+
r#type,
530+
r#struct { r#type: i32 },
531+
}
532+
fn foo() {
533+
match (Enum::A) {
534+
Enum::$0
535+
}
536+
}
537+
"#,
538+
expect![[r#"
539+
bn A A$0
540+
bn B {…} B { r#type$1 }$0
541+
bn struct {…} r#struct { r#type$1 }$0
542+
bn type r#type$0
462543
"#]],
463544
);
464545
}

crates/ide-completion/src/tests/special.rs

+1
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ fn foo() {
519519

520520
#[test]
521521
fn completes_variant_through_self() {
522+
cov_mark::check!(completes_variant_through_self);
522523
check(
523524
r#"
524525
enum Foo {

0 commit comments

Comments
 (0)