mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #20456 from A4-Tacks/match-with-if-let-guard
Add guard to let-chain for replace_match_with_if_let
This commit is contained in:
commit
83b852353a
@ -8,7 +8,7 @@ use ide_db::{
|
|||||||
ty_filter::TryEnum,
|
ty_filter::TryEnum,
|
||||||
};
|
};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
AstNode, T, TextRange,
|
AstNode, Edition, T, TextRange,
|
||||||
ast::{self, HasName, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory},
|
ast::{self, HasName, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ fn make_else_arm(
|
|||||||
|
|
||||||
// Assist: replace_match_with_if_let
|
// Assist: replace_match_with_if_let
|
||||||
//
|
//
|
||||||
// Replaces a binary `match` with a wildcard pattern and no guards with an `if let` expression.
|
// Replaces a binary `match` with a wildcard pattern with an `if let` expression.
|
||||||
//
|
//
|
||||||
// ```
|
// ```
|
||||||
// enum Action { Move { distance: u32 }, Stop }
|
// enum Action { Move { distance: u32 }, Stop }
|
||||||
@ -225,18 +225,24 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
|
|||||||
|
|
||||||
let mut arms = match_arm_list.arms();
|
let mut arms = match_arm_list.arms();
|
||||||
let (first_arm, second_arm) = (arms.next()?, arms.next()?);
|
let (first_arm, second_arm) = (arms.next()?, arms.next()?);
|
||||||
if arms.next().is_some() || first_arm.guard().is_some() || second_arm.guard().is_some() {
|
if arms.next().is_some() || second_arm.guard().is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if first_arm.guard().is_some() && ctx.edition() < Edition::Edition2024 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (if_let_pat, then_expr, else_expr) = pick_pattern_and_expr_order(
|
let (if_let_pat, guard, then_expr, else_expr) = pick_pattern_and_expr_order(
|
||||||
&ctx.sema,
|
&ctx.sema,
|
||||||
first_arm.pat()?,
|
first_arm.pat()?,
|
||||||
second_arm.pat()?,
|
second_arm.pat()?,
|
||||||
first_arm.expr()?,
|
first_arm.expr()?,
|
||||||
second_arm.expr()?,
|
second_arm.expr()?,
|
||||||
|
first_arm.guard(),
|
||||||
|
second_arm.guard(),
|
||||||
)?;
|
)?;
|
||||||
let scrutinee = match_expr.expr()?;
|
let scrutinee = match_expr.expr()?;
|
||||||
|
let guard = guard.and_then(|it| it.condition());
|
||||||
|
|
||||||
let let_ = match &if_let_pat {
|
let let_ = match &if_let_pat {
|
||||||
ast::Pat::LiteralPat(p)
|
ast::Pat::LiteralPat(p)
|
||||||
@ -277,6 +283,11 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
|
|||||||
}
|
}
|
||||||
_ => make.expr_let(if_let_pat, scrutinee).into(),
|
_ => make.expr_let(if_let_pat, scrutinee).into(),
|
||||||
};
|
};
|
||||||
|
let condition = if let Some(guard) = guard {
|
||||||
|
make.expr_bin(condition, ast::BinaryOp::LogicOp(ast::LogicOp::And), guard).into()
|
||||||
|
} else {
|
||||||
|
condition
|
||||||
|
};
|
||||||
let then_expr = then_expr.clone_for_update();
|
let then_expr = then_expr.clone_for_update();
|
||||||
then_expr.reindent_to(IndentLevel::single());
|
then_expr.reindent_to(IndentLevel::single());
|
||||||
let then_block = make_block_expr(then_expr);
|
let then_block = make_block_expr(then_expr);
|
||||||
@ -303,18 +314,23 @@ fn pick_pattern_and_expr_order(
|
|||||||
pat2: ast::Pat,
|
pat2: ast::Pat,
|
||||||
expr: ast::Expr,
|
expr: ast::Expr,
|
||||||
expr2: ast::Expr,
|
expr2: ast::Expr,
|
||||||
) -> Option<(ast::Pat, ast::Expr, ast::Expr)> {
|
guard: Option<ast::MatchGuard>,
|
||||||
|
guard2: Option<ast::MatchGuard>,
|
||||||
|
) -> Option<(ast::Pat, Option<ast::MatchGuard>, ast::Expr, ast::Expr)> {
|
||||||
|
if guard.is_some() && guard2.is_some() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let res = match (pat, pat2) {
|
let res = match (pat, pat2) {
|
||||||
(ast::Pat::WildcardPat(_), _) => return None,
|
(ast::Pat::WildcardPat(_), _) => return None,
|
||||||
(pat, ast::Pat::WildcardPat(_)) => (pat, expr, expr2),
|
(pat, ast::Pat::WildcardPat(_)) => (pat, guard, expr, expr2),
|
||||||
(pat, _) if is_empty_expr(&expr2) => (pat, expr, expr2),
|
(pat, _) if is_empty_expr(&expr2) => (pat, guard, expr, expr2),
|
||||||
(_, pat) if is_empty_expr(&expr) => (pat, expr2, expr),
|
(_, pat) if is_empty_expr(&expr) => (pat, guard, expr2, expr),
|
||||||
(pat, pat2) => match (binds_name(sema, &pat), binds_name(sema, &pat2)) {
|
(pat, pat2) => match (binds_name(sema, &pat), binds_name(sema, &pat2)) {
|
||||||
(true, true) => return None,
|
(true, true) => return None,
|
||||||
(true, false) => (pat, expr, expr2),
|
(true, false) => (pat, guard, expr, expr2),
|
||||||
(false, true) => (pat2, expr2, expr),
|
(false, true) => (pat2, guard2, expr2, expr),
|
||||||
_ if is_sad_pat(sema, &pat) => (pat2, expr2, expr),
|
_ if is_sad_pat(sema, &pat) => (pat2, guard2, expr2, expr),
|
||||||
(false, false) => (pat, expr, expr2),
|
(false, false) => (pat, guard, expr, expr2),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Some(res)
|
Some(res)
|
||||||
@ -1849,6 +1865,30 @@ fn main() {
|
|||||||
code()
|
code()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_replace_match_with_if_let_chain() {
|
||||||
|
check_assist(
|
||||||
|
replace_match_with_if_let,
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
match$0 Some(0) {
|
||||||
|
Some(n) if n % 2 == 0 && n != 6 => (),
|
||||||
|
_ => code(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
if let Some(n) = Some(0) && n % 2 == 0 && n != 6 {
|
||||||
|
()
|
||||||
|
} else {
|
||||||
|
code()
|
||||||
|
}
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user