2023-01-20 12:47:23 -06:00
|
|
|
use syntax::{
|
|
|
|
ast::{self, edit::AstNodeEdit, make},
|
|
|
|
AstNode,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|
|
|
|
|
|
|
// Assist: add_braces
|
|
|
|
//
|
2023-01-20 13:00:38 -06:00
|
|
|
// Adds braces to lambda and match arm expressions.
|
2023-01-20 12:47:23 -06:00
|
|
|
//
|
|
|
|
// ```
|
|
|
|
// fn foo(n: i32) -> i32 {
|
|
|
|
// match n {
|
|
|
|
// 1 =>$0 n + 1,
|
|
|
|
// _ => 0
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// ```
|
|
|
|
// ->
|
|
|
|
// ```
|
|
|
|
// fn foo(n: i32) -> i32 {
|
|
|
|
// match n {
|
|
|
|
// 1 => {
|
|
|
|
// n + 1
|
|
|
|
// },
|
|
|
|
// _ => 0
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// ```
|
|
|
|
pub(crate) fn add_braces(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
|
|
|
|
let (expr_type, expr) = get_replacement_node(ctx)?;
|
|
|
|
|
|
|
|
acc.add(
|
|
|
|
AssistId("wrap_with_braces", AssistKind::RefactorRewrite),
|
|
|
|
match expr_type {
|
2023-01-20 13:00:38 -06:00
|
|
|
ParentType::ClosureExpr => "Add braces to lambda expression",
|
2023-01-20 12:47:23 -06:00
|
|
|
ParentType::MatchArmExpr => "Add braces to arm expression",
|
|
|
|
},
|
|
|
|
expr.syntax().text_range(),
|
|
|
|
|builder| {
|
|
|
|
let block_expr = AstNodeEdit::indent(
|
|
|
|
&make::block_expr(None, Some(expr.clone())),
|
|
|
|
AstNodeEdit::indent_level(&expr),
|
|
|
|
);
|
|
|
|
|
|
|
|
builder.replace(expr.syntax().text_range(), block_expr.syntax().text());
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
Some(())
|
|
|
|
}
|
|
|
|
|
2023-01-20 13:00:38 -06:00
|
|
|
enum ParentType {
|
|
|
|
MatchArmExpr,
|
|
|
|
ClosureExpr,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_replacement_node(ctx: &AssistContext<'_>) -> Option<(ParentType, ast::Expr)> {
|
|
|
|
if let Some(match_arm) = ctx.find_node_at_offset::<ast::MatchArm>() {
|
|
|
|
let match_arm_expr = match_arm.syntax().children().find_map(ast::Expr::cast)?;
|
|
|
|
|
|
|
|
if matches!(match_arm_expr, ast::Expr::BlockExpr(_)) {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Some((ParentType::MatchArmExpr, match_arm_expr));
|
|
|
|
} else if let Some(closure_expr) = ctx.find_node_at_offset::<ast::ClosureExpr>() {
|
|
|
|
let body = closure_expr.body()?;
|
|
|
|
|
|
|
|
if matches!(body, ast::Expr::BlockExpr(_)) {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Some((ParentType::ClosureExpr, body));
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2023-01-20 12:47:23 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::tests::{check_assist, check_assist_not_applicable};
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn suggest_add_braces_for_closure() {
|
|
|
|
check_assist(
|
|
|
|
add_braces,
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
t(|n|$0 n + 100);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
t(|n| {
|
|
|
|
n + 100
|
|
|
|
});
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_assist_for_closures_with_braces() {
|
|
|
|
check_assist_not_applicable(
|
|
|
|
add_braces,
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
t(|n|$0 { n + 100 });
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn suggest_add_braces_for_match() {
|
|
|
|
check_assist(
|
|
|
|
add_braces,
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
match n {
|
|
|
|
Some(n) $0=> 29,
|
|
|
|
_ => ()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
match n {
|
|
|
|
Some(n) => {
|
|
|
|
29
|
|
|
|
},
|
|
|
|
_ => ()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_assist_for_match_with_braces() {
|
|
|
|
check_assist_not_applicable(
|
|
|
|
add_braces,
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
match n {
|
|
|
|
Some(n) $0=> { return 29; },
|
|
|
|
_ => ()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|