Auto merge of #16810 - Young-Flash:unused_var_fix, r=Veykril

feat: add fix for unused_variables

add a leading underscore for unused variable
This commit is contained in:
bors 2024-03-11 13:01:50 +00:00
commit 40ee359046
2 changed files with 115 additions and 16 deletions

View File

@ -413,7 +413,7 @@ fn main() {
fn main() { fn main() {
return; return;
let mut x = 2; let mut x = 2;
//^^^^^ warn: unused variable //^^^^^ 💡 warn: unused variable
&mut x; &mut x;
} }
"#, "#,
@ -423,7 +423,7 @@ fn main() {
fn main() { fn main() {
loop {} loop {}
let mut x = 2; let mut x = 2;
//^^^^^ warn: unused variable //^^^^^ 💡 warn: unused variable
&mut x; &mut x;
} }
"#, "#,
@ -444,7 +444,7 @@ fn main(b: bool) {
g(); g();
} }
let mut x = 2; let mut x = 2;
//^^^^^ warn: unused variable //^^^^^ 💡 warn: unused variable
&mut x; &mut x;
} }
"#, "#,
@ -459,7 +459,7 @@ fn main(b: bool) {
return; return;
} }
let mut x = 2; let mut x = 2;
//^^^^^ warn: unused variable //^^^^^ 💡 warn: unused variable
&mut x; &mut x;
} }
"#, "#,
@ -789,7 +789,7 @@ fn f() {
//^^ 💡 error: cannot mutate immutable variable `x` //^^ 💡 error: cannot mutate immutable variable `x`
_ = (x, y); _ = (x, y);
let x = Foo; let x = Foo;
//^ warn: unused variable //^ 💡 warn: unused variable
let x = Foo; let x = Foo;
let y: &mut (i32, u8) = &mut x; let y: &mut (i32, u8) = &mut x;
//^^^^^^ 💡 error: cannot mutate immutable variable `x` //^^^^^^ 💡 error: cannot mutate immutable variable `x`

View File

@ -1,3 +1,11 @@
use ide_db::{
assists::{Assist, AssistId, AssistKind},
base_db::FileRange,
label::Label,
source_change::SourceChange,
};
use text_edit::TextEdit;
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext}; use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
// Diagnostic: unused-variables // Diagnostic: unused-variables
@ -8,18 +16,38 @@ pub(crate) fn unused_variables(
d: &hir::UnusedVariable, d: &hir::UnusedVariable,
) -> Diagnostic { ) -> Diagnostic {
let ast = d.local.primary_source(ctx.sema.db).syntax_ptr(); let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
let diagnostic_range = ctx.sema.diagnostics_display_range(ast);
let var_name = d.local.primary_source(ctx.sema.db).syntax().to_string();
Diagnostic::new_with_syntax_node_ptr( Diagnostic::new_with_syntax_node_ptr(
ctx, ctx,
DiagnosticCode::RustcLint("unused_variables"), DiagnosticCode::RustcLint("unused_variables"),
"unused variable", "unused variable",
ast, ast,
) )
.with_fixes(fixes(&var_name, diagnostic_range, ast.file_id.is_macro()))
.experimental() .experimental()
} }
fn fixes(var_name: &String, diagnostic_range: FileRange, is_in_marco: bool) -> Option<Vec<Assist>> {
if is_in_marco {
return None;
}
Some(vec![Assist {
id: AssistId("unscore_unused_variable_name", AssistKind::QuickFix),
label: Label::new(format!("Rename unused {} to _{}", var_name, var_name)),
group: None,
target: diagnostic_range.range,
source_change: Some(SourceChange::from_text_edit(
diagnostic_range.file_id,
TextEdit::replace(diagnostic_range.range, format!("_{}", var_name)),
)),
trigger_signature_help: false,
}])
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::tests::check_diagnostics; use crate::tests::{check_diagnostics, check_fix, check_no_fix};
#[test] #[test]
fn unused_variables_simple() { fn unused_variables_simple() {
@ -29,23 +57,23 @@ mod tests {
struct Foo { f1: i32, f2: i64 } struct Foo { f1: i32, f2: i64 }
fn f(kkk: i32) {} fn f(kkk: i32) {}
//^^^ warn: unused variable //^^^ 💡 warn: unused variable
fn main() { fn main() {
let a = 2; let a = 2;
//^ warn: unused variable //^ 💡 warn: unused variable
let b = 5; let b = 5;
// note: `unused variable` implies `unused mut`, so we should not emit both at the same time. // note: `unused variable` implies `unused mut`, so we should not emit both at the same time.
let mut c = f(b); let mut c = f(b);
//^^^^^ warn: unused variable //^^^^^ 💡 warn: unused variable
let (d, e) = (3, 5); let (d, e) = (3, 5);
//^ warn: unused variable //^ 💡 warn: unused variable
let _ = e; let _ = e;
let f1 = 2; let f1 = 2;
let f2 = 5; let f2 = 5;
let f = Foo { f1, f2 }; let f = Foo { f1, f2 };
match f { match f {
Foo { f1, f2 } => { Foo { f1, f2 } => {
//^^ warn: unused variable //^^ 💡 warn: unused variable
_ = f2; _ = f2;
} }
} }
@ -53,7 +81,7 @@ fn main() {
if g {} if g {}
let h: fn() -> i32 = || 2; let h: fn() -> i32 = || 2;
let i = h(); let i = h();
//^ warn: unused variable //^ 💡 warn: unused variable
} }
"#, "#,
); );
@ -67,11 +95,11 @@ struct S {
} }
impl S { impl S {
fn owned_self(self, u: i32) {} fn owned_self(self, u: i32) {}
//^ warn: unused variable //^ 💡 warn: unused variable
fn ref_self(&self, u: i32) {} fn ref_self(&self, u: i32) {}
//^ warn: unused variable //^ 💡 warn: unused variable
fn ref_mut_self(&mut self, u: i32) {} fn ref_mut_self(&mut self, u: i32) {}
//^ warn: unused variable //^ 💡 warn: unused variable
fn owned_mut_self(mut self) {} fn owned_mut_self(mut self) {}
//^^^^^^^^ 💡 warn: variable does not need to be mutable //^^^^^^^^ 💡 warn: variable does not need to be mutable
@ -103,7 +131,78 @@ fn main() {
#[deny(unused)] #[deny(unused)]
fn main2() { fn main2() {
let x = 2; let x = 2;
//^ error: unused variable //^ 💡 error: unused variable
}
"#,
);
}
#[test]
fn fix_unused_variable() {
check_fix(
r#"
fn main() {
let x$0 = 2;
}
"#,
r#"
fn main() {
let _x = 2;
}
"#,
);
check_fix(
r#"
fn main() {
let ($0d, _e) = (3, 5);
}
"#,
r#"
fn main() {
let (_d, _e) = (3, 5);
}
"#,
);
check_fix(
r#"
struct Foo { f1: i32, f2: i64 }
fn main() {
let f = Foo { f1: 0, f2: 0 };
match f {
Foo { f1$0, f2 } => {
_ = f2;
}
}
}
"#,
r#"
struct Foo { f1: i32, f2: i64 }
fn main() {
let f = Foo { f1: 0, f2: 0 };
match f {
Foo { _f1, f2 } => {
_ = f2;
}
}
}
"#,
);
}
#[test]
fn no_fix_for_marco() {
check_no_fix(
r#"
macro_rules! my_macro {
() => {
let x = 3;
};
}
fn main() {
$0my_macro!();
} }
"#, "#,
); );