Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/join_lines.rs')
| -rw-r--r-- | crates/ide/src/join_lines.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs index 30334ffcc8..ec67c02757 100644 --- a/crates/ide/src/join_lines.rs +++ b/crates/ide/src/join_lines.rs @@ -15,6 +15,7 @@ pub struct JoinLinesConfig { pub join_else_if: bool, pub remove_trailing_comma: bool, pub unwrap_trivial_blocks: bool, + pub join_assignments: bool, } // Feature: Join Lines @@ -162,6 +163,12 @@ fn remove_newline( } } + if config.join_assignments { + if join_assignments(edit, &prev, &next).is_some() { + return; + } + } + if config.unwrap_trivial_blocks { // Special case that turns something like: // @@ -232,6 +239,41 @@ fn join_single_use_tree(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Opti Some(()) } +fn join_assignments( + edit: &mut TextEditBuilder, + prev: &SyntaxElement, + next: &SyntaxElement, +) -> Option<()> { + let let_stmt = ast::LetStmt::cast(prev.as_node()?.clone())?; + if let_stmt.eq_token().is_some() { + cov_mark::hit!(join_assignments_already_initialized); + return None; + } + let let_ident_pat = match let_stmt.pat()? { + ast::Pat::IdentPat(it) => it, + _ => return None, + }; + + let expr_stmt = ast::ExprStmt::cast(next.as_node()?.clone())?; + let bin_expr = match expr_stmt.expr()? { + ast::Expr::BinExpr(it) => it, + _ => return None, + }; + if !matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { op: None }) { + return None; + } + let lhs = bin_expr.lhs()?; + let name_ref = lhs.name_ref()?; + + if name_ref.to_string() != let_ident_pat.syntax().to_string() { + cov_mark::hit!(join_assignments_mismatch); + return None; + } + + edit.delete(let_stmt.semicolon_token()?.text_range().cover(lhs.syntax().text_range())); + Some(()) +} + fn as_if_expr(element: &SyntaxElement) -> Option<ast::IfExpr> { let mut node = element.as_node()?.clone(); if let Some(stmt) = ast::ExprStmt::cast(node.clone()) { @@ -275,6 +317,7 @@ mod tests { join_else_if: true, remove_trailing_comma: true, unwrap_trivial_blocks: true, + join_assignments: true, }; let (before_cursor_pos, before) = extract_offset(ra_fixture_before); @@ -300,6 +343,7 @@ mod tests { join_else_if: true, remove_trailing_comma: true, unwrap_trivial_blocks: true, + join_assignments: true, }; let (sel, before) = extract_range(ra_fixture_before); @@ -993,4 +1037,53 @@ fn main() { "#, ); } + + #[test] + fn join_assignments() { + check_join_lines( + r#" +fn foo() { + $0let foo; + foo = "bar"; +} +"#, + r#" +fn foo() { + $0let foo = "bar"; +} +"#, + ); + + cov_mark::check!(join_assignments_mismatch); + check_join_lines( + r#" +fn foo() { + let foo; + let qux;$0 + foo = "bar"; +} +"#, + r#" +fn foo() { + let foo; + let qux;$0 foo = "bar"; +} +"#, + ); + + cov_mark::check!(join_assignments_already_initialized); + check_join_lines( + r#" +fn foo() { + let foo = "bar";$0 + foo = "bar"; +} +"#, + r#" +fn foo() { + let foo = "bar";$0 foo = "bar"; +} +"#, + ); + } } |