Skip to content

Commit 2935a89

Browse files
committed
Auto merge of #14037 - Veykril:if-let-match, r=Veykril
Handle boolean scrutinees in match <-> if let replacement assists better
2 parents 9814d79 + 6829190 commit 2935a89

File tree

1 file changed

+159
-24
lines changed

1 file changed

+159
-24
lines changed

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

+159-24
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use syntax::{
1313
edit::{AstNodeEdit, IndentLevel},
1414
make, HasName,
1515
},
16-
AstNode, TextRange,
16+
AstNode, TextRange, T,
1717
};
1818

1919
use crate::{
@@ -96,8 +96,9 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
9696
cond_bodies.push((cond, body));
9797
}
9898

99-
if !pat_seen {
100-
// Don't offer turning an if (chain) without patterns into a match
99+
if !pat_seen && cond_bodies.len() != 1 {
100+
// Don't offer turning an if (chain) without patterns into a match,
101+
// unless its a simple `if cond { .. } (else { .. })`
101102
return None;
102103
}
103104

@@ -114,6 +115,11 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
114115
Either::Left(pat) => {
115116
make::match_arm(iter::once(pat), None, unwrap_trivial_block(body))
116117
}
118+
Either::Right(_) if !pat_seen => make::match_arm(
119+
iter::once(make::literal_pat("true").into()),
120+
None,
121+
unwrap_trivial_block(body),
122+
),
117123
Either::Right(expr) => make::match_arm(
118124
iter::once(make::wildcard_pat().into()),
119125
Some(expr),
@@ -144,31 +150,36 @@ fn make_else_arm(
144150
else_block: Option<ast::BlockExpr>,
145151
conditionals: &[(Either<ast::Pat, ast::Expr>, ast::BlockExpr)],
146152
) -> ast::MatchArm {
147-
if let Some(else_block) = else_block {
148-
let pattern = if let [(Either::Left(pat), _)] = conditionals {
149-
ctx.sema
153+
let (pattern, expr) = if let Some(else_block) = else_block {
154+
let pattern = match conditionals {
155+
[(Either::Right(_), _)] => make::literal_pat("false").into(),
156+
[(Either::Left(pat), _)] => match ctx
157+
.sema
150158
.type_of_pat(pat)
151159
.and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted()))
152-
.zip(Some(pat))
153-
} else {
154-
None
155-
};
156-
let pattern = match pattern {
157-
Some((it, pat)) => {
158-
if does_pat_match_variant(pat, &it.sad_pattern()) {
159-
it.happy_pattern_wildcard()
160-
} else if does_nested_pattern(pat) {
161-
make::wildcard_pat().into()
162-
} else {
163-
it.sad_pattern()
160+
{
161+
Some(it) => {
162+
if does_pat_match_variant(pat, &it.sad_pattern()) {
163+
it.happy_pattern_wildcard()
164+
} else if does_nested_pattern(pat) {
165+
make::wildcard_pat().into()
166+
} else {
167+
it.sad_pattern()
168+
}
164169
}
165-
}
166-
None => make::wildcard_pat().into(),
170+
None => make::wildcard_pat().into(),
171+
},
172+
_ => make::wildcard_pat().into(),
167173
};
168-
make::match_arm(iter::once(pattern), None, unwrap_trivial_block(else_block))
174+
(pattern, unwrap_trivial_block(else_block))
169175
} else {
170-
make::match_arm(iter::once(make::wildcard_pat().into()), None, make::expr_unit())
171-
}
176+
let pattern = match conditionals {
177+
[(Either::Right(_), _)] => make::literal_pat("false").into(),
178+
_ => make::wildcard_pat().into(),
179+
};
180+
(pattern, make::expr_unit())
181+
};
182+
make::match_arm(iter::once(pattern), None, expr)
172183
}
173184

174185
// Assist: replace_match_with_if_let
@@ -231,7 +242,19 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
231242
}
232243
}
233244

234-
let condition = make::expr_let(if_let_pat, scrutinee);
245+
let condition = match if_let_pat {
246+
ast::Pat::LiteralPat(p)
247+
if p.literal().map_or(false, |it| it.token().kind() == T![true]) =>
248+
{
249+
scrutinee
250+
}
251+
ast::Pat::LiteralPat(p)
252+
if p.literal().map_or(false, |it| it.token().kind() == T![false]) =>
253+
{
254+
make::expr_prefix(T![!], scrutinee)
255+
}
256+
_ => make::expr_let(if_let_pat, scrutinee).into(),
257+
};
235258
let then_block = make_block_expr(then_expr.reset_indent());
236259
let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
237260
let if_let_expr = make::expr_if(
@@ -327,6 +350,58 @@ fn main() {
327350
)
328351
}
329352

353+
#[test]
354+
fn test_if_with_match_no_else() {
355+
check_assist(
356+
replace_if_let_with_match,
357+
r#"
358+
pub fn foo(foo: bool) {
359+
if foo$0 {
360+
self.foo();
361+
}
362+
}
363+
"#,
364+
r#"
365+
pub fn foo(foo: bool) {
366+
match foo {
367+
true => {
368+
self.foo();
369+
}
370+
false => (),
371+
}
372+
}
373+
"#,
374+
)
375+
}
376+
377+
#[test]
378+
fn test_if_with_match_with_else() {
379+
check_assist(
380+
replace_if_let_with_match,
381+
r#"
382+
pub fn foo(foo: bool) {
383+
if foo$0 {
384+
self.foo();
385+
} else {
386+
self.bar();
387+
}
388+
}
389+
"#,
390+
r#"
391+
pub fn foo(foo: bool) {
392+
match foo {
393+
true => {
394+
self.foo();
395+
}
396+
false => {
397+
self.bar();
398+
}
399+
}
400+
}
401+
"#,
402+
)
403+
}
404+
330405
#[test]
331406
fn test_if_let_with_match_no_else() {
332407
check_assist(
@@ -993,6 +1068,66 @@ fn main() {
9931068
code()
9941069
}
9951070
}
1071+
"#,
1072+
)
1073+
}
1074+
1075+
#[test]
1076+
fn test_replace_match_with_if_bool() {
1077+
check_assist(
1078+
replace_match_with_if_let,
1079+
r#"
1080+
fn main() {
1081+
match$0 b {
1082+
true => (),
1083+
_ => code(),
1084+
}
1085+
}
1086+
"#,
1087+
r#"
1088+
fn main() {
1089+
if b {
1090+
()
1091+
} else {
1092+
code()
1093+
}
1094+
}
1095+
"#,
1096+
);
1097+
check_assist(
1098+
replace_match_with_if_let,
1099+
r#"
1100+
fn main() {
1101+
match$0 b {
1102+
false => code(),
1103+
true => (),
1104+
}
1105+
}
1106+
"#,
1107+
r#"
1108+
fn main() {
1109+
if !b {
1110+
code()
1111+
}
1112+
}
1113+
"#,
1114+
);
1115+
check_assist(
1116+
replace_match_with_if_let,
1117+
r#"
1118+
fn main() {
1119+
match$0 b {
1120+
false => (),
1121+
true => code(),
1122+
}
1123+
}
1124+
"#,
1125+
r#"
1126+
fn main() {
1127+
if b {
1128+
code()
1129+
}
1130+
}
9961131
"#,
9971132
)
9981133
}

0 commit comments

Comments
 (0)