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.rs93
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";
+}
+"#,
+ );
+ }
}