Skip to content

Commit 35f2e82

Browse files
committed
Don't show add_missing_match_arms when not needed
`does_not_fill_wildcard_with_wildcard` and `does_not_fill_wildcard_with_partial_wildcard_and_wildcard` both made no modifications to the code, which is a problem for mutable ast porting as it generates a best-effort minimal set of text edits, and assists require at least one text edit.
1 parent 5fddf3e commit 35f2e82

File tree

1 file changed

+45
-34
lines changed

1 file changed

+45
-34
lines changed

crates/ide-assists/src/handlers/add_missing_match_arms.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,18 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
7575
.collect();
7676

7777
let module = ctx.sema.scope(expr.syntax())?.module();
78-
let (mut missing_pats, is_non_exhaustive): (
78+
let (mut missing_pats, is_non_exhaustive, has_hidden_variants): (
7979
Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>,
8080
bool,
81+
bool,
8182
) = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) {
8283
let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate());
8384

8485
let variants = enum_def.variants(ctx.db());
8586

87+
let has_hidden_variants =
88+
variants.iter().any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
89+
8690
let missing_pats = variants
8791
.into_iter()
8892
.filter_map(|variant| {
@@ -101,7 +105,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
101105
} else {
102106
Box::new(missing_pats)
103107
};
104-
(missing_pats.peekable(), is_non_exhaustive)
108+
(missing_pats.peekable(), is_non_exhaustive, has_hidden_variants)
105109
} else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) {
106110
let is_non_exhaustive =
107111
enum_defs.iter().any(|enum_def| enum_def.is_non_exhaustive(ctx.db(), module.krate()));
@@ -124,6 +128,12 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
124128
if n_arms > 256 {
125129
return None;
126130
}
131+
132+
let has_hidden_variants = variants_of_enums
133+
.iter()
134+
.flatten()
135+
.any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
136+
127137
let missing_pats = variants_of_enums
128138
.into_iter()
129139
.multi_cartesian_product()
@@ -139,7 +149,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
139149
(ast::Pat::from(make::tuple_pat(patterns)), is_hidden)
140150
})
141151
.filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
142-
((Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(), is_non_exhaustive)
152+
(
153+
(Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(),
154+
is_non_exhaustive,
155+
has_hidden_variants,
156+
)
143157
} else if let Some((enum_def, len)) = resolve_array_of_enum_def(&ctx.sema, &expr) {
144158
let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate());
145159
let variants = enum_def.variants(ctx.db());
@@ -148,6 +162,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
148162
return None;
149163
}
150164

165+
let has_hidden_variants =
166+
variants.iter().any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
167+
151168
let variants_of_enums = vec![variants; len];
152169

153170
let missing_pats = variants_of_enums
@@ -164,14 +181,20 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
164181
(ast::Pat::from(make::slice_pat(patterns)), is_hidden)
165182
})
166183
.filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
167-
((Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(), is_non_exhaustive)
184+
(
185+
(Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable(),
186+
is_non_exhaustive,
187+
has_hidden_variants,
188+
)
168189
} else {
169190
return None;
170191
};
171192

172193
let mut needs_catch_all_arm = is_non_exhaustive && !has_catch_all_arm;
173194

174-
if !needs_catch_all_arm && missing_pats.peek().is_none() {
195+
if !needs_catch_all_arm
196+
&& ((has_hidden_variants && has_catch_all_arm) || missing_pats.peek().is_none())
197+
{
175198
return None;
176199
}
177200

@@ -181,11 +204,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
181204
target_range,
182205
|builder| {
183206
let new_match_arm_list = match_arm_list.clone_for_update();
184-
let missing_arms = missing_pats
185-
.map(|(pat, hidden)| {
186-
(make::match_arm(iter::once(pat), None, make::ext::expr_todo()), hidden)
207+
208+
// having any hidden variants means that we need a catch-all arm
209+
needs_catch_all_arm |= has_hidden_variants;
210+
211+
let missing_arms = missing_pats.filter_map(|(pat, hidden)| {
212+
// filter out hidden patterns because they're handled by the catch-all arm
213+
(!hidden).then(|| {
214+
make::match_arm(iter::once(pat), None, make::ext::expr_todo())
215+
.clone_for_update()
187216
})
188-
.map(|(it, hidden)| (it.clone_for_update(), hidden));
217+
});
189218

190219
let catch_all_arm = new_match_arm_list
191220
.arms()
@@ -204,15 +233,13 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
204233
cov_mark::hit!(add_missing_match_arms_empty_expr);
205234
}
206235
}
236+
207237
let mut first_new_arm = None;
208-
for (arm, hidden) in missing_arms {
209-
if hidden {
210-
needs_catch_all_arm = !has_catch_all_arm;
211-
} else {
212-
first_new_arm.get_or_insert_with(|| arm.clone());
213-
new_match_arm_list.add_arm(arm);
214-
}
238+
for arm in missing_arms {
239+
first_new_arm.get_or_insert_with(|| arm.clone());
240+
new_match_arm_list.add_arm(arm);
215241
}
242+
216243
if needs_catch_all_arm && !has_catch_all_arm {
217244
cov_mark::hit!(added_wildcard_pattern);
218245
let arm = make::match_arm(
@@ -1621,10 +1648,9 @@ pub enum E { #[doc(hidden)] A, }
16211648
);
16221649
}
16231650

1624-
// FIXME: I don't think the assist should be applicable in this case
16251651
#[test]
16261652
fn does_not_fill_wildcard_with_wildcard() {
1627-
check_assist(
1653+
check_assist_not_applicable(
16281654
add_missing_match_arms,
16291655
r#"
16301656
//- /main.rs crate:main deps:e
@@ -1635,13 +1661,6 @@ fn foo(t: ::e::E) {
16351661
}
16361662
//- /e.rs crate:e
16371663
pub enum E { #[doc(hidden)] A, }
1638-
"#,
1639-
r#"
1640-
fn foo(t: ::e::E) {
1641-
match t {
1642-
_ => todo!(),
1643-
}
1644-
}
16451664
"#,
16461665
);
16471666
}
@@ -1777,7 +1796,7 @@ fn foo(t: ::e::E, b: bool) {
17771796

17781797
#[test]
17791798
fn does_not_fill_wildcard_with_partial_wildcard_and_wildcard() {
1780-
check_assist(
1799+
check_assist_not_applicable(
17811800
add_missing_match_arms,
17821801
r#"
17831802
//- /main.rs crate:main deps:e
@@ -1789,14 +1808,6 @@ fn foo(t: ::e::E, b: bool) {
17891808
}
17901809
//- /e.rs crate:e
17911810
pub enum E { #[doc(hidden)] A, }"#,
1792-
r#"
1793-
fn foo(t: ::e::E, b: bool) {
1794-
match t {
1795-
_ if b => todo!(),
1796-
_ => todo!(),
1797-
}
1798-
}
1799-
"#,
18001811
);
18011812
}
18021813

0 commit comments

Comments
 (0)