Add bind_unused_param assistant.
This commit is contained in:
parent
029baaad22
commit
e457759cbb
130
crates/ide-assists/src/handlers/bind_unused_param.rs
Normal file
130
crates/ide-assists/src/handlers/bind_unused_param.rs
Normal file
@ -0,0 +1,130 @@
|
||||
use crate::assist_context::{AssistContext, Assists};
|
||||
use ide_db::{
|
||||
assists::{AssistId, AssistKind},
|
||||
defs::Definition,
|
||||
LineIndexDatabase,
|
||||
};
|
||||
use syntax::{
|
||||
ast::{self, edit_in_place::Indent},
|
||||
AstNode,
|
||||
};
|
||||
|
||||
use super::remove_unused_param::is_trait_impl;
|
||||
|
||||
// Assist: bind_unused_param
|
||||
//
|
||||
// Binds unused function parameter to an underscore.
|
||||
//
|
||||
// ```
|
||||
// fn some_function(x: i32$0) {}
|
||||
// ```
|
||||
// ->
|
||||
// ```
|
||||
// fn some_function(x: i32) {
|
||||
// let _ = x;
|
||||
// }
|
||||
// ```
|
||||
pub(crate) fn bind_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)?;
|
||||
if is_trait_impl(&func) {
|
||||
cov_mark::hit!(trait_impl);
|
||||
return None;
|
||||
}
|
||||
|
||||
let param_def = {
|
||||
let local = ctx.sema.to_def(&ident_pat)?;
|
||||
Definition::Local(local)
|
||||
};
|
||||
if param_def.usages(&ctx.sema).at_least_one() {
|
||||
cov_mark::hit!(keep_used);
|
||||
return None;
|
||||
}
|
||||
|
||||
let line_index = ctx.db().line_index(ctx.file_id());
|
||||
|
||||
let mut indent = func.indent_level();
|
||||
indent.0 += 1;
|
||||
let mut text = format!("\n{indent}let _ = {ident_pat};");
|
||||
|
||||
let stmt_list = func.body()?.stmt_list()?;
|
||||
let l_curly_range = stmt_list.l_curly_token()?.text_range();
|
||||
let r_curly_range = stmt_list.r_curly_token()?.text_range();
|
||||
let left_line = line_index.line_col(l_curly_range.end()).line;
|
||||
let right_line = line_index.line_col(r_curly_range.start()).line;
|
||||
|
||||
if left_line == right_line {
|
||||
text.push('\n');
|
||||
}
|
||||
|
||||
acc.add(
|
||||
AssistId("bind_unused_param", AssistKind::Refactor),
|
||||
&format!("Bind as `let _ = {};`", &ident_pat),
|
||||
param.syntax().text_range(),
|
||||
|builder| {
|
||||
builder.insert(l_curly_range.end(), text);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::check_assist;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn bind_unused_empty_block() {
|
||||
check_assist(
|
||||
bind_unused_param,
|
||||
r#"
|
||||
fn foo($0y: i32) {}
|
||||
"#,
|
||||
r#"
|
||||
fn foo(y: i32) {
|
||||
let _ = y;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bind_unused_empty_block_with_newline() {
|
||||
check_assist(
|
||||
bind_unused_param,
|
||||
r#"
|
||||
fn foo($0y: i32) {
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo(y: i32) {
|
||||
let _ = y;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bind_unused_generic() {
|
||||
check_assist(
|
||||
bind_unused_param,
|
||||
r#"
|
||||
fn foo<T>($0y: T)
|
||||
where T : Default {
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo<T>(y: T)
|
||||
where T : Default {
|
||||
let _ = y;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
@ -42,13 +42,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
||||
param.syntax().parent()?.children().find_map(ast::SelfParam::cast).is_some();
|
||||
|
||||
// check if fn is in impl Trait for ..
|
||||
if func
|
||||
.syntax()
|
||||
.parent() // AssocItemList
|
||||
.and_then(|x| x.parent())
|
||||
.and_then(ast::Impl::cast)
|
||||
.map_or(false, |imp| imp.trait_().is_some())
|
||||
{
|
||||
if is_trait_impl(&func) {
|
||||
cov_mark::hit!(trait_impl);
|
||||
return None;
|
||||
}
|
||||
@ -87,6 +81,14 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) ->
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn is_trait_impl(func: &ast::Fn) -> bool {
|
||||
func.syntax()
|
||||
.parent() // AssocItemList
|
||||
.and_then(|x| x.parent())
|
||||
.and_then(ast::Impl::cast)
|
||||
.map_or(false, |imp| imp.trait_().is_some())
|
||||
}
|
||||
|
||||
fn process_usages(
|
||||
ctx: &AssistContext<'_>,
|
||||
builder: &mut SourceChangeBuilder,
|
||||
|
@ -114,6 +114,7 @@ mod handlers {
|
||||
mod add_turbo_fish;
|
||||
mod apply_demorgan;
|
||||
mod auto_import;
|
||||
mod bind_unused_param;
|
||||
mod change_visibility;
|
||||
mod convert_bool_then;
|
||||
mod convert_comment_block;
|
||||
@ -224,6 +225,7 @@ pub(crate) fn all() -> &'static [Handler] {
|
||||
add_turbo_fish::add_turbo_fish,
|
||||
apply_demorgan::apply_demorgan,
|
||||
auto_import::auto_import,
|
||||
bind_unused_param::bind_unused_param,
|
||||
change_visibility::change_visibility,
|
||||
convert_bool_then::convert_bool_then_to_if,
|
||||
convert_bool_then::convert_if_to_bool_then,
|
||||
|
@ -265,6 +265,21 @@ pub mod std { pub mod collections { pub struct HashMap { } } }
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_bind_unused_param() {
|
||||
check_doc_test(
|
||||
"bind_unused_param",
|
||||
r#####"
|
||||
fn some_function(x: i32$0) {}
|
||||
"#####,
|
||||
r#####"
|
||||
fn some_function(x: i32) {
|
||||
let _ = x;
|
||||
}
|
||||
"#####,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_change_visibility() {
|
||||
check_doc_test(
|
||||
|
Loading…
Reference in New Issue
Block a user