From 4b5b55f6f3d1879cd974f290e2f0d92f487acc4b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 19 Aug 2020 18:44:33 +0200 Subject: **Remove Unused Parameter** refactoring --- crates/assists/src/handlers/merge_imports.rs | 5 +- crates/assists/src/handlers/remove_dbg.rs | 3 +- crates/assists/src/handlers/remove_unused_param.rs | 131 +++++++++++++++++++++ crates/assists/src/lib.rs | 2 + crates/assists/src/tests/generated.rs | 21 ++++ crates/assists/src/utils.rs | 6 +- 6 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 crates/assists/src/handlers/remove_unused_param.rs (limited to 'crates/assists') diff --git a/crates/assists/src/handlers/merge_imports.rs b/crates/assists/src/handlers/merge_imports.rs index 47d465404..35b884206 100644 --- a/crates/assists/src/handlers/merge_imports.rs +++ b/crates/assists/src/handlers/merge_imports.rs @@ -8,6 +8,7 @@ use syntax::{ use crate::{ assist_context::{AssistContext, Assists}, + utils::next_prev, AssistId, AssistKind, }; @@ -66,10 +67,6 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<() ) } -fn next_prev() -> impl Iterator { - [Direction::Next, Direction::Prev].iter().copied() -} - fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option { let lhs_path = old.path()?; let rhs_path = new.path()?; diff --git a/crates/assists/src/handlers/remove_dbg.rs b/crates/assists/src/handlers/remove_dbg.rs index f3dcca534..4e252edf0 100644 --- a/crates/assists/src/handlers/remove_dbg.rs +++ b/crates/assists/src/handlers/remove_dbg.rs @@ -82,9 +82,10 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Optiondbg!(1 + 1)", "1 + 1"); diff --git a/crates/assists/src/handlers/remove_unused_param.rs b/crates/assists/src/handlers/remove_unused_param.rs new file mode 100644 index 000000000..5fccca54b --- /dev/null +++ b/crates/assists/src/handlers/remove_unused_param.rs @@ -0,0 +1,131 @@ +use ide_db::{defs::Definition, search::Reference}; +use syntax::{ + algo::find_node_at_range, + ast::{self, ArgListOwner}, + AstNode, SyntaxNode, TextRange, T, +}; +use test_utils::mark; + +use crate::{ + assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists, +}; + +// Assist: remove_unused_param +// +// Removes unused function parameter. +// +// ``` +// fn frobnicate(x: i32<|>) {} +// +// fn main() { +// frobnicate(92); +// } +// ``` +// -> +// ``` +// fn frobnicate() {} +// +// fn main() { +// frobnicate(); +// } +// ``` +pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { + let param: ast::Param = ctx.find_node_at_offset()?; + let ident_pat = match param.pat()? { + ast::Pat::IdentPat(it) => it, + _ => return None, + }; + let func = param.syntax().ancestors().find_map(ast::Fn::cast)?; + let param_position = func.param_list()?.params().position(|it| it == param)?; + + let fn_def = { + let func = ctx.sema.to_def(&func)?; + Definition::ModuleDef(func.into()) + }; + + let param_def = { + let local = ctx.sema.to_def(&ident_pat)?; + Definition::Local(local) + }; + if param_def.usages(&ctx.sema).at_least_one() { + mark::hit!(keep_used); + return None; + } + acc.add( + AssistId("remove_unused_param", AssistKind::Refactor), + "Remove unused parameter", + param.syntax().text_range(), + |builder| { + builder.delete(range_with_coma(param.syntax())); + for usage in fn_def.usages(&ctx.sema).all() { + process_usage(ctx, builder, usage, param_position); + } + }, + ) +} + +fn process_usage( + ctx: &AssistContext, + builder: &mut AssistBuilder, + usage: Reference, + arg_to_remove: usize, +) -> Option<()> { + let source_file = ctx.sema.parse(usage.file_range.file_id); + let call_expr: ast::CallExpr = + find_node_at_range(source_file.syntax(), usage.file_range.range)?; + if call_expr.expr()?.syntax().text_range() != usage.file_range.range { + return None; + } + 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())); + + Some(()) +} + +fn range_with_coma(node: &SyntaxNode) -> TextRange { + let up_to = next_prev().find_map(|dir| { + node.siblings_with_tokens(dir) + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == T![,]) + }); + let up_to = up_to.map_or(node.text_range(), |it| it.text_range()); + node.text_range().cover(up_to) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn remove_unused() { + check_assist( + remove_unused_param, + r#" +fn a() { foo(9, 2) } +fn foo(x: i32, <|>y: i32) { x; } +fn b() { foo(9, 2,) } +"#, + r#" +fn a() { foo(9) } +fn foo(x: i32) { x; } +fn b() { foo(9, ) } +"#, + ); + } + + #[test] + fn keep_used() { + mark::check!(keep_used); + check_assist_not_applicable( + remove_unused_param, + r#" +fn foo(x: i32, <|>y: i32) { y; } +fn main() { foo(9, 2) } +"#, + ); + } +} diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index 14834480a..2e0d191a6 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs @@ -152,6 +152,7 @@ mod handlers { mod raw_string; mod remove_dbg; mod remove_mut; + mod remove_unused_param; mod reorder_fields; mod replace_if_let_with_match; mod replace_let_with_if_let; @@ -198,6 +199,7 @@ mod handlers { raw_string::remove_hash, remove_dbg::remove_dbg, remove_mut::remove_mut, + remove_unused_param::remove_unused_param, reorder_fields::reorder_fields, replace_if_let_with_match::replace_if_let_with_match, replace_let_with_if_let::replace_let_with_if_let, diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index 173567003..04c8fd1f9 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs @@ -750,6 +750,27 @@ impl Walrus { ) } +#[test] +fn doctest_remove_unused_param() { + check_doc_test( + "remove_unused_param", + r#####" +fn frobnicate(x: i32<|>) {} + +fn main() { + frobnicate(92); +} +"#####, + r#####" +fn frobnicate() {} + +fn main() { + frobnicate(); +} +"#####, + ) +} + #[test] fn doctest_reorder_fields() { check_doc_test( diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 84ccacafe..d071d6502 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs @@ -9,7 +9,7 @@ use itertools::Itertools; use rustc_hash::FxHashSet; use syntax::{ ast::{self, make, NameOwner}, - AstNode, + AstNode, Direction, SyntaxKind::*, SyntaxNode, TextSize, T, }; @@ -311,3 +311,7 @@ pub use prelude::*; Some(def) } } + +pub(crate) fn next_prev() -> impl Iterator { + [Direction::Next, Direction::Prev].iter().copied() +} -- cgit v1.2.3