]> git.lizzy.rs Git - rust.git/blobdiff - crates/ra_assists/src/introduce_variable.rs
ra_assists: assist "providers" can produce multiple assists
[rust.git] / crates / ra_assists / src / introduce_variable.rs
index 934d1d6b3ca2b5a5be12f768eae62ede6045d6ef..f0e012105f5ecb5008756fac6397eb208f631dfc 100644 (file)
@@ -8,7 +8,7 @@
 
 use crate::{AssistCtx, Assist};
 
-pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
+pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let node = ctx.covering_node();
     if !valid_covering_node(node) {
         return None;
@@ -19,7 +19,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Ass
     if indent.kind() != WHITESPACE {
         return None;
     }
-    ctx.build("introduce variable", move |edit| {
+    ctx.add_action("introduce variable", move |edit| {
         let mut buf = String::new();
 
         let cursor_offset = if wrap_in_block {
@@ -44,7 +44,22 @@ pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Ass
             edit.replace(expr.syntax().range(), buf);
         } else {
             buf.push_str(";");
-            indent.text().push_to(&mut buf);
+
+            // We want to maintain the indent level,
+            // but we do not want to duplicate possible
+            // extra newlines in the indent block
+            for chunk in indent.text().chunks() {
+                if chunk.starts_with("\r\n") {
+                    buf.push_str("\r\n");
+                    buf.push_str(chunk.trim_start_matches("\r\n"));
+                } else if chunk.starts_with("\n") {
+                    buf.push_str("\n");
+                    buf.push_str(chunk.trim_start_matches("\n"));
+                } else {
+                    buf.push_str(chunk);
+                }
+            }
+
             edit.target(expr.syntax().range());
             edit.replace(expr.syntax().range(), "var_name".to_string());
             edit.insert(anchor_stmt.range().start(), buf);
@@ -53,7 +68,9 @@ pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Ass
             }
         }
         edit.set_cursor(anchor_stmt.range().start() + cursor_offset);
-    })
+    });
+
+    ctx.build()
 }
 
 fn valid_covering_node(node: &SyntaxNode) -> bool {
@@ -337,6 +354,70 @@ fn foo() -> u32 {
 ",
             "
 fn foo() -> u32 {
+    let <|>var_name = 2 + 2;
+    return var_name;
+}
+",
+        );
+    }
+
+    #[test]
+    fn test_introduce_var_does_not_add_extra_whitespace() {
+        check_assist(
+            introduce_variable,
+            "
+fn foo() -> u32 {
+
+
+    r<|>eturn 2 + 2;
+}
+",
+            "
+fn foo() -> u32 {
+
+
+    let <|>var_name = 2 + 2;
+    return var_name;
+}
+",
+        );
+
+        check_assist(
+            introduce_variable,
+            "
+fn foo() -> u32 {
+
+        r<|>eturn 2 + 2;
+}
+",
+            "
+fn foo() -> u32 {
+
+        let <|>var_name = 2 + 2;
+        return var_name;
+}
+",
+        );
+
+        check_assist(
+            introduce_variable,
+            "
+fn foo() -> u32 {
+    let foo = 1;
+
+    // bar
+
+
+    r<|>eturn 2 + 2;
+}
+",
+            "
+fn foo() -> u32 {
+    let foo = 1;
+
+    // bar
+
+
     let <|>var_name = 2 + 2;
     return var_name;
 }