From 5f79279b487fad2a74d21588c49af83a79d5fdec Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 6 Dec 2022 16:18:25 +0000 Subject: [PATCH] Add `remove_parentheses` assist --- .../src/handlers/remove_parentheses.rs | 86 +++++++++++++++++++ crates/ide-assists/src/lib.rs | 2 + crates/ide-assists/src/tests/generated.rs | 17 ++++ 3 files changed, 105 insertions(+) create mode 100644 crates/ide-assists/src/handlers/remove_parentheses.rs diff --git a/crates/ide-assists/src/handlers/remove_parentheses.rs b/crates/ide-assists/src/handlers/remove_parentheses.rs new file mode 100644 index 00000000000..9a1f9268d0e --- /dev/null +++ b/crates/ide-assists/src/handlers/remove_parentheses.rs @@ -0,0 +1,86 @@ +use syntax::{ast, AstNode, SyntaxKind, TextRange}; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: remove_parentheses +// +// Removes useless parentheses. +// +// ``` +// fn main() { +// _ = $0(2) + 2; +// } +// ``` +// -> +// ``` +// fn main() { +// _ = 2 + 2; +// } +// ``` +pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let parens = ctx.find_node_at_offset::()?; + let l_paren = parens.l_paren_token()?; + let r_paren = parens.r_paren_token()?; + + let cursor_in_range = l_paren.text_range().contains_range(ctx.selection_trimmed()) + || r_paren.text_range().contains_range(ctx.selection_trimmed()); + if !cursor_in_range { + return None; + } + + // FIXME: check that precedence is right + + let delete_from_l = l_paren.text_range().start(); + let delete_to_l = match l_paren.next_token() { + Some(it) if it.kind() == SyntaxKind::WHITESPACE => it.text_range().end(), + _ => l_paren.text_range().end(), + }; + + let delete_from_r = match r_paren.prev_token() { + Some(it) if it.kind() == SyntaxKind::WHITESPACE => it.text_range().start(), + _ => r_paren.text_range().start(), + }; + let delete_to_r = r_paren.text_range().end(); + + let target = parens.syntax().text_range(); + acc.add( + AssistId("remove_parentheses", AssistKind::Refactor), + "Remove parentheses", + target, + |builder| { + builder.delete(TextRange::new(delete_from_l, delete_to_l)); + builder.delete(TextRange::new(delete_from_r, delete_to_r)); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn remove_parens_simple() { + check_assist(remove_parentheses, r#"fn f() { $0(2) + 2; }"#, r#"fn f() { 2 + 2; }"#); + check_assist(remove_parentheses, r#"fn f() { ($02) + 2; }"#, r#"fn f() { 2 + 2; }"#); + check_assist(remove_parentheses, r#"fn f() { (2)$0 + 2; }"#, r#"fn f() { 2 + 2; }"#); + check_assist(remove_parentheses, r#"fn f() { (2$0) + 2; }"#, r#"fn f() { 2 + 2; }"#); + } + + // We should not permit assist here and yet + #[test] + fn remove_parens_wrong() { + check_assist( + remove_parentheses, + r#"fn f() { $0(2 + 2) * 8; }"#, + r#"fn f() { 2 + 2 * 8; }"#, + ); + } + + #[test] + fn remove_parens_doesnt_apply_with_cursor_not_on_paren() { + check_assist_not_applicable(remove_parentheses, r#"fn f() { (2 +$0 2) }"#); + check_assist_not_applicable(remove_parentheses, r#"fn f() {$0 (2 + 2) }"#); + } +} diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs index a55de800b39..8b1247c640a 100644 --- a/crates/ide-assists/src/lib.rs +++ b/crates/ide-assists/src/lib.rs @@ -179,6 +179,7 @@ mod handlers { mod remove_dbg; mod remove_mut; mod remove_unused_param; + mod remove_parentheses; mod reorder_fields; mod reorder_impl_items; mod replace_try_expr_with_match; @@ -280,6 +281,7 @@ mod handlers { remove_dbg::remove_dbg, remove_mut::remove_mut, remove_unused_param::remove_unused_param, + remove_parentheses::remove_parentheses, reorder_fields::reorder_fields, reorder_impl_items::reorder_impl_items, replace_try_expr_with_match::replace_try_expr_with_match, diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index ccd38119c4a..80b8c27c7c0 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -1978,6 +1978,23 @@ impl Walrus { ) } +#[test] +fn doctest_remove_parentheses() { + check_doc_test( + "remove_parentheses", + r#####" +fn main() { + _ = $0(2) + 2; +} +"#####, + r#####" +fn main() { + _ = 2 + 2; +} +"#####, + ) +} + #[test] fn doctest_remove_unused_param() { check_doc_test(