Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions crates/ide/src/join_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
//
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -990,6 +1034,55 @@ 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

I didn't realise that you can put several marks in a single block and have them do what you want them to!

check_join_lines(
r#"
fn foo() {
let foo = "bar";$0
foo = "bar";
}
"#,
r#"
fn foo() {
let foo = "bar";$0 foo = "bar";
}
"#,
);
}
Expand Down
3 changes: 3 additions & 0 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ config_data! {
joinLines_removeTrailingComma: bool = "true",
/// Join lines unwraps trivial blocks.
joinLines_unwrapTrivialBlock: bool = "true",
/// Join lines merges consecutive declaration and initialization of an assignment.
joinLines_joinAssignments: bool = "true",

/// Whether to show `Debug` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
Expand Down Expand Up @@ -786,6 +788,7 @@ impl Config {
join_else_if: self.data.joinLines_joinElseIf,
remove_trailing_comma: self.data.joinLines_removeTrailingComma,
unwrap_trivial_blocks: self.data.joinLines_unwrapTrivialBlock,
join_assignments: self.data.joinLines_joinAssignments,
}
}
pub fn call_info_full(&self) -> bool {
Expand Down
5 changes: 5 additions & 0 deletions docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,11 @@ Join lines removes trailing commas.
--
Join lines unwraps trivial blocks.
--
[[rust-analyzer.joinLines.joinAssignments]]rust-analyzer.joinLines.joinAssignments (default: `true`)::
+
--
Join lines merges consecutive declaration and initialization of an assignment.
--
[[rust-analyzer.lens.debug]]rust-analyzer.lens.debug (default: `true`)::
+
--
Expand Down
5 changes: 5 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,11 @@
"default": true,
"type": "boolean"
},
"rust-analyzer.joinLines.joinAssignments": {
"markdownDescription": "Join lines merges consecutive declaration and initialization of an assignment.",
"default": true,
"type": "boolean"
},
"rust-analyzer.lens.debug": {
"markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
"default": true,
Expand Down