internal: Generally improve make::match_arm

`make::match_arm` should take a single `ast::Pat`, and callers can handle creating an `ast::OrPat` if need be. It should also take a proper `ast::MatchGuard`, instead of making one itself.
This commit is contained in:
Giga Bowser 2024-12-16 15:28:17 -05:00
parent 905e1e1fc0
commit 32ff06d51c
9 changed files with 53 additions and 56 deletions

View file

@ -212,8 +212,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
!hidden
})
.map(|(pat, _)| {
make::match_arm(iter::once(pat), None, make::ext::expr_todo())
.clone_for_update()
make::match_arm(pat, None, make::ext::expr_todo()).clone_for_update()
});
let catch_all_arm = new_match_arm_list
@ -243,12 +242,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
if needs_catch_all_arm && !has_catch_all_arm {
cov_mark::hit!(added_wildcard_pattern);
let arm = make::match_arm(
iter::once(make::wildcard_pat().into()),
None,
make::ext::expr_todo(),
)
.clone_for_update();
let arm =
make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo())
.clone_for_update();
todo_placeholders.push(arm.expr().unwrap());
added_arms.push(arm);
}

View file

@ -1554,12 +1554,12 @@ impl FlowHandler {
let value_pat = make::ext::simple_ident_pat(make::name(some_name));
let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
let value = make::expr_path(make::ext::ident_path(some_name));
make::match_arm(iter::once(pat.into()), None, value)
make::match_arm(pat.into(), None, value)
};
let none_arm = {
let path = make::ext::ident_path("None");
let pat = make::path_pat(path);
make::match_arm(iter::once(pat), None, none.make_result_handler(None))
make::match_arm(pat, None, none.make_result_handler(None))
};
let arms = make::match_arm_list(vec![some_arm, none_arm]);
make::expr_match(call_expr, arms)
@ -1573,18 +1573,14 @@ impl FlowHandler {
let value_pat = make::ext::simple_ident_pat(make::name(ok_name));
let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
let value = make::expr_path(make::ext::ident_path(ok_name));
make::match_arm(iter::once(pat.into()), None, value)
make::match_arm(pat.into(), None, value)
};
let err_arm = {
let path = make::ext::ident_path("Err");
let value_pat = make::ext::simple_ident_pat(make::name(err_name));
let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
let value = make::expr_path(make::ext::ident_path(err_name));
make::match_arm(
iter::once(pat.into()),
None,
err.make_result_handler(Some(value)),
)
make::match_arm(pat.into(), None, err.make_result_handler(Some(value)))
};
let arms = make::match_arm_list(vec![ok_arm, err_arm]);
make::expr_match(call_expr, arms)

View file

@ -114,17 +114,15 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
let make_match_arm = |(pat, body): (_, ast::BlockExpr)| {
let body = body.reset_indent().indent(IndentLevel(1));
match pat {
Either::Left(pat) => {
make::match_arm(iter::once(pat), None, unwrap_trivial_block(body))
}
Either::Left(pat) => make::match_arm(pat, None, unwrap_trivial_block(body)),
Either::Right(_) if !pat_seen => make::match_arm(
iter::once(make::literal_pat("true").into()),
make::literal_pat("true").into(),
None,
unwrap_trivial_block(body),
),
Either::Right(expr) => make::match_arm(
iter::once(make::wildcard_pat().into()),
Some(expr),
make::wildcard_pat().into(),
Some(make::match_guard(expr)),
unwrap_trivial_block(body),
),
}
@ -181,7 +179,7 @@ fn make_else_arm(
};
(pattern, make::ext::expr_unit())
};
make::match_arm(iter::once(pattern), None, expr)
make::match_arm(pattern, None, expr)
}
// Assist: replace_match_with_if_let

View file

@ -71,13 +71,11 @@ pub(crate) fn replace_try_expr_with_match(
};
let happy_arm = make::match_arm(
iter::once(
try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()),
),
try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()),
None,
make::expr_path(make::ext::ident_path("it")),
);
let sad_arm = make::match_arm(iter::once(sad_pat), None, sad_expr);
let sad_arm = make::match_arm(sad_pat, None, sad_expr);
let match_arm_list = make::match_arm_list([happy_arm, sad_arm]);

View file

@ -54,13 +54,9 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
let pats_after = pipe_token
.siblings_with_tokens(Direction::Next)
.filter_map(|it| ast::Pat::cast(it.into_node()?));
// FIXME: We should add a leading pipe if the original arm has one.
let new_match_arm = make::match_arm(
pats_after,
match_arm.guard().and_then(|guard| guard.condition()),
match_arm_body,
)
.clone_for_update();
let new_pat = make::or_pat(pats_after, or_pat.leading_pipe().is_some());
let new_match_arm =
make::match_arm(new_pat, match_arm.guard(), match_arm_body).clone_for_update();
let mut pipe_index = pipe_token.index();
if pipe_token

View file

@ -66,7 +66,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
let pat = make::record_pat(variant_name.clone(), pats.into_iter());
let fields = make::record_expr_field_list(fields);
let record_expr = make::record_expr(variant_name, fields).into();
arms.push(make::match_arm(Some(pat.into()), None, record_expr));
arms.push(make::match_arm(pat.into(), None, record_expr));
}
// => match self { Self::Name(arg1) => Self::Name(arg1.clone()) }
@ -84,14 +84,14 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter());
let struct_name = make::expr_path(variant_name);
let tuple_expr = make::expr_call(struct_name, make::arg_list(fields));
arms.push(make::match_arm(Some(pat.into()), None, tuple_expr));
arms.push(make::match_arm(pat.into(), None, tuple_expr));
}
// => match self { Self::Name => Self::Name }
None => {
let pattern = make::path_pat(variant_name.clone());
let variant_expr = make::expr_path(variant_name);
arms.push(make::match_arm(Some(pattern), None, variant_expr));
arms.push(make::match_arm(pattern, None, variant_expr));
}
}
}
@ -190,7 +190,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
// => MyStruct { fields.. } => f.debug_struct("MyStruct")...finish(),
let pat = make::record_pat(variant_name.clone(), pats.into_iter());
arms.push(make::match_arm(Some(pat.into()), None, expr));
arms.push(make::match_arm(pat.into(), None, expr));
}
Some(ast::FieldList::TupleFieldList(list)) => {
// => f.debug_tuple(name)
@ -223,7 +223,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
// => MyStruct (fields..) => f.debug_tuple("MyStruct")...finish(),
let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter());
arms.push(make::match_arm(Some(pat.into()), None, expr));
arms.push(make::match_arm(pat.into(), None, expr));
}
None => {
let fmt_string = make::expr_literal(&(format!("\"{name}\""))).into();
@ -232,7 +232,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
let macro_call = make::expr_macro_call(macro_name, args);
let variant_name = make::path_pat(variant_name);
arms.push(make::match_arm(Some(variant_name), None, macro_call));
arms.push(make::match_arm(variant_name, None, macro_call));
}
}
}
@ -485,7 +485,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -
let tuple = make::tuple_pat(vec![left.into(), right.into()]);
if let Some(expr) = expr {
arms.push(make::match_arm(Some(tuple.into()), None, expr));
arms.push(make::match_arm(tuple.into(), None, expr));
}
}
@ -518,7 +518,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -
let tuple = make::tuple_pat(vec![left.into(), right.into()]);
if let Some(expr) = expr {
arms.push(make::match_arm(Some(tuple.into()), None, expr));
arms.push(make::match_arm(tuple.into(), None, expr));
}
}
None => continue,
@ -538,7 +538,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -
} else {
eq_check
};
arms.push(make::match_arm(Some(lhs), None, rhs));
arms.push(make::match_arm(lhs, None, rhs));
}
let match_target = make::expr_tuple([lhs_name, rhs_name]).into();
@ -599,10 +599,10 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>)
let variant_name =
make::path_pat(make::ext::path_from_idents(["core", "cmp", "Ordering", "Equal"])?);
let lhs = make::tuple_struct_pat(make::ext::path_from_idents(["Some"])?, [variant_name]);
arms.push(make::match_arm(Some(lhs.into()), None, make::expr_empty_block()));
arms.push(make::match_arm(lhs.into(), None, make::expr_empty_block()));
arms.push(make::match_arm(
[make::ident_pat(false, false, make::name("ord")).into()],
make::ident_pat(false, false, make::name("ord")).into(),
None,
make::expr_return(Some(make::expr_path(make::ext::ident_path("ord")))),
));

View file

@ -153,8 +153,7 @@ impl<N: AstNode + Clone> AstNodeEdit for N {}
#[test]
fn test_increase_indent() {
let arm_list = {
let arm =
make::match_arm(iter::once(make::wildcard_pat().into()), None, make::ext::expr_unit());
let arm = make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_unit());
make::match_arm_list([arm.clone(), arm])
};
assert_eq!(

View file

@ -787,15 +787,21 @@ pub fn path_pat(path: ast::Path) -> ast::Pat {
}
}
pub fn match_arm(
pats: impl IntoIterator<Item = ast::Pat>,
guard: Option<ast::Expr>,
expr: ast::Expr,
) -> ast::MatchArm {
let pats_str = pats.into_iter().join(" | ");
/// Returns a `Pat` if the path has just one segment, an `OrPat` otherwise.
pub fn or_pat(pats: impl IntoIterator<Item = ast::Pat>, leading_pipe: bool) -> ast::Pat {
let leading_pipe = if leading_pipe { "| " } else { "" };
let pats = pats.into_iter().join(" | ");
return from_text(&format!("{leading_pipe}{pats}"));
fn from_text(text: &str) -> ast::Pat {
ast_from_text(&format!("fn f({text}: ())"))
}
}
pub fn match_arm(pat: ast::Pat, guard: Option<ast::MatchGuard>, expr: ast::Expr) -> ast::MatchArm {
return match guard {
Some(guard) => from_text(&format!("{pats_str} if {guard} => {expr}")),
None => from_text(&format!("{pats_str} => {expr}")),
Some(guard) => from_text(&format!("{pat} {guard} => {expr}")),
None => from_text(&format!("{pat} => {expr}")),
};
fn from_text(text: &str) -> ast::MatchArm {
@ -816,6 +822,14 @@ pub fn match_arm_with_guard(
}
}
pub fn match_guard(condition: ast::Expr) -> ast::MatchGuard {
return from_text(&format!("if {condition}"));
fn from_text(text: &str) -> ast::MatchGuard {
ast_from_text(&format!("fn f() {{ match () {{() {text} => () }}"))
}
}
pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| {
let needs_comma = arm.expr().is_none_or(|it| !it.is_block_like());

View file

@ -335,7 +335,7 @@ mod tests {
#[test]
fn basic_usage() {
let root = make::match_arm(
[make::wildcard_pat().into()],
make::wildcard_pat().into(),
None,
make::expr_tuple([
make::expr_bin_op(