mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-26 03:45:04 +00:00
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:
parent
905e1e1fc0
commit
32ff06d51c
9 changed files with 53 additions and 56 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")))),
|
||||
));
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue