Unnamed repository; edit this file 'description' to name the repository.
Merge #9993
9993: feat: join lines merges assignments r=matklad a=unexge Closes https://github.com/rust-analyzer/rust-analyzer/issues/9967. ![Peek 2021-08-22 21-46](https://user-images.githubusercontent.com/16212576/130366571-3ebb1753-f8d5-4884-be8f-222cda71a2a7.gif) Co-authored-by: unexge <[email protected]>
bors[bot] 2021-08-24
parent 68279e3 · parent 3a9ba0e · commit 49c02b9
-rw-r--r--crates/ide/src/join_lines.rs93
-rw-r--r--crates/rust-analyzer/src/config.rs3
-rw-r--r--docs/user/generated_config.adoc5
-rw-r--r--editors/code/package.json5
4 files changed, 106 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";
+}
+"#,
+ );
+ }
}
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index e71513034c..22da92779e 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -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.
@@ -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 {
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index c40b6d6936..f73e542037 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -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`)::
+
--
diff --git a/editors/code/package.json b/editors/code/package.json
index 453abb6b1c..33bc4dc9a9 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -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,