fix(ide-assists): unwrap block when it parent is let stmt

This commit is contained in:
bvanjoi 2023-01-23 23:53:30 +08:00
parent 8fa69f9f7d
commit 90b1222b0b

View File

@ -2,6 +2,7 @@
ast::{ ast::{
self, self,
edit::{AstNodeEdit, IndentLevel}, edit::{AstNodeEdit, IndentLevel},
make,
}, },
AstNode, SyntaxKind, TextRange, T, AstNode, SyntaxKind, TextRange, T,
}; };
@ -37,61 +38,89 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
parent = parent.ancestors().find(|it| ast::MatchExpr::can_cast(it.kind()))? parent = parent.ancestors().find(|it| ast::MatchExpr::can_cast(it.kind()))?
} }
if matches!(parent.kind(), SyntaxKind::STMT_LIST | SyntaxKind::EXPR_STMT | SyntaxKind::LET_STMT) let kind = parent.kind();
{ if matches!(kind, SyntaxKind::STMT_LIST | SyntaxKind::EXPR_STMT) {
return acc.add(assist_id, assist_label, target, |builder| { acc.add(assist_id, assist_label, target, |builder| {
builder.replace(block.syntax().text_range(), update_expr_string(block.to_string())); builder.replace(block.syntax().text_range(), update_expr_string(block.to_string()));
}); })
} } else if matches!(kind, SyntaxKind::LET_STMT) {
let parent = ast::LetStmt::cast(parent)?;
let pattern = ast::Pat::cast(parent.syntax().first_child()?)?;
let ty = parent.ty();
let list = block.stmt_list()?;
let replaced = match list.syntax().last_child() {
Some(last) => {
let stmts: Vec<ast::Stmt> = list.statements().collect();
let initializer = ast::Expr::cast(last.clone())?;
let let_stmt = make::let_stmt(pattern, ty, Some(initializer));
if stmts.len() > 0 {
let block = make::block_expr(stmts, None);
format!(
"{}\n {}",
update_expr_string(block.to_string()),
let_stmt.to_string()
)
} else {
let_stmt.to_string()
}
}
None => {
let empty_tuple = make::expr_tuple([]);
make::let_stmt(pattern, ty, Some(empty_tuple)).to_string()
}
};
acc.add(assist_id, assist_label, target, |builder| {
builder.replace(parent.syntax().text_range(), replaced);
})
} else {
let parent = ast::Expr::cast(parent)?;
match parent.clone() {
ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) | ast::Expr::LoopExpr(_) => (),
ast::Expr::MatchExpr(_) => block = block.dedent(IndentLevel(1)),
ast::Expr::IfExpr(if_expr) => {
let then_branch = if_expr.then_branch()?;
if then_branch == block {
if let Some(ancestor) = if_expr.syntax().parent().and_then(ast::IfExpr::cast) {
// For `else if` blocks
let ancestor_then_branch = ancestor.then_branch()?;
let parent = ast::Expr::cast(parent)?; return acc.add(assist_id, assist_label, target, |edit| {
let range_to_del_else_if = TextRange::new(
match parent.clone() { ancestor_then_branch.syntax().text_range().end(),
ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) | ast::Expr::LoopExpr(_) => (), l_curly_token.text_range().start(),
ast::Expr::MatchExpr(_) => block = block.dedent(IndentLevel(1)), );
ast::Expr::IfExpr(if_expr) => { let range_to_del_rest = TextRange::new(
let then_branch = if_expr.then_branch()?; then_branch.syntax().text_range().end(),
if then_branch == block { if_expr.syntax().text_range().end(),
if let Some(ancestor) = if_expr.syntax().parent().and_then(ast::IfExpr::cast) { );
// For `else if` blocks
let ancestor_then_branch = ancestor.then_branch()?;
edit.delete(range_to_del_rest);
edit.delete(range_to_del_else_if);
edit.replace(
target,
update_expr_string_without_newline(then_branch.to_string()),
);
});
}
} else {
return acc.add(assist_id, assist_label, target, |edit| { return acc.add(assist_id, assist_label, target, |edit| {
let range_to_del_else_if = TextRange::new( let range_to_del = TextRange::new(
ancestor_then_branch.syntax().text_range().end(), then_branch.syntax().text_range().end(),
l_curly_token.text_range().start(), l_curly_token.text_range().start(),
); );
let range_to_del_rest = TextRange::new(
then_branch.syntax().text_range().end(),
if_expr.syntax().text_range().end(),
);
edit.delete(range_to_del_rest); edit.delete(range_to_del);
edit.delete(range_to_del_else_if); edit.replace(target, update_expr_string_without_newline(block.to_string()));
edit.replace(
target,
update_expr_string_without_newline(then_branch.to_string()),
);
}); });
} }
} else {
return acc.add(assist_id, assist_label, target, |edit| {
let range_to_del = TextRange::new(
then_branch.syntax().text_range().end(),
l_curly_token.text_range().start(),
);
edit.delete(range_to_del);
edit.replace(target, update_expr_string_without_newline(block.to_string()));
});
} }
} _ => return None,
_ => return None, };
};
acc.add(assist_id, assist_label, target, |builder| { acc.add(assist_id, assist_label, target, |builder| {
builder.replace(parent.syntax().text_range(), update_expr_string(block.to_string())); builder.replace(parent.syntax().text_range(), update_expr_string(block.to_string()));
}) })
}
} }
fn update_expr_string(expr_string: String) -> String { fn update_expr_string(expr_string: String) -> String {
@ -724,6 +753,19 @@ fn unwrap_block_in_let_initializers() {
check_assist( check_assist(
unwrap_block, unwrap_block,
r#" r#"
fn main() {
let x = {$0};
}
"#,
r#"
fn main() {
let x = ();
}
"#,
);
check_assist(
unwrap_block,
r#"
fn main() { fn main() {
let x = {$0 let x = {$0
bar bar
@ -734,6 +776,34 @@ fn main() {
fn main() { fn main() {
let x = bar; let x = bar;
} }
"#,
);
check_assist(
unwrap_block,
r#"
fn main() -> i32 {
let _ = {$01; 2};
}
"#,
r#"
fn main() -> i32 {
1;
let _ = 2;
}
"#,
);
check_assist(
unwrap_block,
r#"
fn main() -> i32 {
let mut a = {$01; 2};
}
"#,
r#"
fn main() -> i32 {
1;
let mut a = 2;
}
"#, "#,
); );
} }