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($0y: T) where T : Default { } "#, r#" fn foo(y: T) where T : Default { let _ = y; } "#, ); } }