]> git.lizzy.rs Git - rust.git/commitdiff
Delete related whitespace when removing unused param
authorRüdiger Herrmann <ruediger.herrmann@gmx.de>
Sat, 5 Dec 2020 13:28:15 +0000 (14:28 +0100)
committerRüdiger Herrmann <ruediger.herrmann@gmx.de>
Mon, 21 Dec 2020 17:42:42 +0000 (18:42 +0100)
Include adjacent whitespace in the text edits to remove the
parameter declaration and its occurences in calling code.

https://github.com/rust-analyzer/rust-analyzer/issues/6663

crates/assists/src/handlers/remove_unused_param.rs

index 1ff5e92b04f4fbfcf83a3e9d55f595ba9d5dad5e..f72dd49edc6b913472ef1c6adb4ab28349f87e00 100644 (file)
@@ -2,9 +2,10 @@
 use syntax::{
     algo::find_node_at_range,
     ast::{self, ArgListOwner},
-    AstNode, SyntaxNode, TextRange, T,
+    AstNode, SyntaxKind, SyntaxNode, TextRange, T,
 };
 use test_utils::mark;
+use SyntaxKind::WHITESPACE;
 
 use crate::{
     assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists,
@@ -56,7 +57,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
         "Remove unused parameter",
         param.syntax().text_range(),
         |builder| {
-            builder.delete(range_with_coma(param.syntax()));
+            builder.delete(range_to_remove(param.syntax()));
             for usage in fn_def.usages(&ctx.sema).all() {
                 process_usage(ctx, builder, usage, param_position);
             }
@@ -80,19 +81,34 @@ fn process_usage(
     let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?;
 
     builder.edit_file(usage.file_range.file_id);
-    builder.delete(range_with_coma(arg.syntax()));
+    builder.delete(range_to_remove(arg.syntax()));
 
     Some(())
 }
 
-fn range_with_coma(node: &SyntaxNode) -> TextRange {
-    let up_to = next_prev().find_map(|dir| {
+fn range_to_remove(node: &SyntaxNode) -> TextRange {
+    let up_to_comma = next_prev().find_map(|dir| {
         node.siblings_with_tokens(dir)
             .filter_map(|it| it.into_token())
             .find(|it| it.kind() == T![,])
+            .map(|it| (dir, it))
     });
-    let up_to = up_to.map_or(node.text_range(), |it| it.text_range());
-    node.text_range().cover(up_to)
+    if let Some((dir, token)) = up_to_comma {
+        if node.next_sibling().is_some() {
+            let up_to_space = token
+                .siblings_with_tokens(dir)
+                .skip(1)
+                .take_while(|it| it.kind() == WHITESPACE)
+                .last()
+                .and_then(|it| it.into_token());
+            return node
+                .text_range()
+                .cover(up_to_space.map_or(token.text_range(), |it| it.text_range()));
+        }
+        node.text_range().cover(token.text_range())
+    } else {
+        node.text_range()
+    }
 }
 
 #[cfg(test)]
@@ -118,6 +134,57 @@ fn b() { foo(9, ) }
         );
     }
 
+    #[test]
+    fn remove_unused_first_param() {
+        check_assist(
+            remove_unused_param,
+            r#"
+fn foo(<|>x: i32, y: i32) { y; }
+fn a() { foo(1, 2) }
+fn b() { foo(1, 2,) }
+"#,
+            r#"
+fn foo(y: i32) { y; }
+fn a() { foo(2) }
+fn b() { foo(2,) }
+"#,
+        );
+    }
+
+    #[test]
+    fn remove_unused_single_param() {
+        check_assist(
+            remove_unused_param,
+            r#"
+fn foo(<|>x: i32) { 0; }
+fn a() { foo(1) }
+fn b() { foo(1, ) }
+"#,
+            r#"
+fn foo() { 0; }
+fn a() { foo() }
+fn b() { foo( ) }
+"#,
+        );
+    }
+
+    #[test]
+    fn remove_unused_surrounded_by_parms() {
+        check_assist(
+            remove_unused_param,
+            r#"
+fn foo(x: i32, <|>y: i32, z: i32) { x; }
+fn a() { foo(1, 2, 3) }
+fn b() { foo(1, 2, 3,) }
+"#,
+            r#"
+fn foo(x: i32, z: i32) { x; }
+fn a() { foo(1, 3) }
+fn b() { foo(1, 3,) }
+"#,
+        );
+    }
+
     #[test]
     fn remove_unused_qualified_call() {
         check_assist(