Skip to content

Commit 83b8523

Browse files
authored
Merge pull request #20456 from A4-Tacks/match-with-if-let-guard
Add guard to let-chain for replace_match_with_if_let
2 parents b06ce60 + 8399a88 commit 83b8523

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

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

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ide_db::{
88
ty_filter::TryEnum,
99
};
1010
use syntax::{
11-
AstNode, T, TextRange,
11+
AstNode, Edition, T, TextRange,
1212
ast::{self, HasName, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory},
1313
};
1414

@@ -187,7 +187,7 @@ fn make_else_arm(
187187

188188
// Assist: replace_match_with_if_let
189189
//
190-
// Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
190+
// Replaces a binary `match` with a wildcard pattern with an `if let` expression.
191191
//
192192
// ```
193193
// enum Action { Move { distance: u32 }, Stop }
@@ -225,18 +225,24 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
225225

226226
let mut arms = match_arm_list.arms();
227227
let (first_arm, second_arm) = (arms.next()?, arms.next()?);
228-
if arms.next().is_some() || first_arm.guard().is_some() || second_arm.guard().is_some() {
228+
if arms.next().is_some() || second_arm.guard().is_some() {
229+
return None;
230+
}
231+
if first_arm.guard().is_some() && ctx.edition() < Edition::Edition2024 {
229232
return None;
230233
}
231234

232-
let (if_let_pat, then_expr, else_expr) = pick_pattern_and_expr_order(
235+
let (if_let_pat, guard, then_expr, else_expr) = pick_pattern_and_expr_order(
233236
&ctx.sema,
234237
first_arm.pat()?,
235238
second_arm.pat()?,
236239
first_arm.expr()?,
237240
second_arm.expr()?,
241+
first_arm.guard(),
242+
second_arm.guard(),
238243
)?;
239244
let scrutinee = match_expr.expr()?;
245+
let guard = guard.and_then(|it| it.condition());
240246

241247
let let_ = match &if_let_pat {
242248
ast::Pat::LiteralPat(p)
@@ -277,6 +283,11 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
277283
}
278284
_ => make.expr_let(if_let_pat, scrutinee).into(),
279285
};
286+
let condition = if let Some(guard) = guard {
287+
make.expr_bin(condition, ast::BinaryOp::LogicOp(ast::LogicOp::And), guard).into()
288+
} else {
289+
condition
290+
};
280291
let then_expr = then_expr.clone_for_update();
281292
then_expr.reindent_to(IndentLevel::single());
282293
let then_block = make_block_expr(then_expr);
@@ -303,18 +314,23 @@ fn pick_pattern_and_expr_order(
303314
pat2: ast::Pat,
304315
expr: ast::Expr,
305316
expr2: ast::Expr,
306-
) -> Option<(ast::Pat, ast::Expr, ast::Expr)> {
317+
guard: Option<ast::MatchGuard>,
318+
guard2: Option<ast::MatchGuard>,
319+
) -> Option<(ast::Pat, Option<ast::MatchGuard>, ast::Expr, ast::Expr)> {
320+
if guard.is_some() && guard2.is_some() {
321+
return None;
322+
}
307323
let res = match (pat, pat2) {
308324
(ast::Pat::WildcardPat(_), _) => return None,
309-
(pat, ast::Pat::WildcardPat(_)) => (pat, expr, expr2),
310-
(pat, _) if is_empty_expr(&expr2) => (pat, expr, expr2),
311-
(_, pat) if is_empty_expr(&expr) => (pat, expr2, expr),
325+
(pat, ast::Pat::WildcardPat(_)) => (pat, guard, expr, expr2),
326+
(pat, _) if is_empty_expr(&expr2) => (pat, guard, expr, expr2),
327+
(_, pat) if is_empty_expr(&expr) => (pat, guard, expr2, expr),
312328
(pat, pat2) => match (binds_name(sema, &pat), binds_name(sema, &pat2)) {
313329
(true, true) => return None,
314-
(true, false) => (pat, expr, expr2),
315-
(false, true) => (pat2, expr2, expr),
316-
_ if is_sad_pat(sema, &pat) => (pat2, expr2, expr),
317-
(false, false) => (pat, expr, expr2),
330+
(true, false) => (pat, guard, expr, expr2),
331+
(false, true) => (pat2, guard2, expr2, expr),
332+
_ if is_sad_pat(sema, &pat) => (pat2, guard2, expr2, expr),
333+
(false, false) => (pat, guard, expr, expr2),
318334
},
319335
};
320336
Some(res)
@@ -1849,6 +1865,30 @@ fn main() {
18491865
code()
18501866
}
18511867
}
1868+
"#,
1869+
)
1870+
}
1871+
1872+
#[test]
1873+
fn test_replace_match_with_if_let_chain() {
1874+
check_assist(
1875+
replace_match_with_if_let,
1876+
r#"
1877+
fn main() {
1878+
match$0 Some(0) {
1879+
Some(n) if n % 2 == 0 && n != 6 => (),
1880+
_ => code(),
1881+
}
1882+
}
1883+
"#,
1884+
r#"
1885+
fn main() {
1886+
if let Some(n) = Some(0) && n % 2 == 0 && n != 6 {
1887+
()
1888+
} else {
1889+
code()
1890+
}
1891+
}
18521892
"#,
18531893
)
18541894
}

0 commit comments

Comments
 (0)