about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-11 13:01:50 +0000
committerbors <bors@rust-lang.org>2024-03-11 13:01:50 +0000
commit40ee35904667dceac4e2210d0cb99bae5e981349 (patch)
tree3428968f57a0578a8c7f826316665b1b8bd013ef
parent2320e1254166a2b121122cb1471ba9f395a6720a (diff)
parent562f4a2688d1c38cb1eafd463eb03ea0e80bcf87 (diff)
downloadrust-40ee35904667dceac4e2210d0cb99bae5e981349.tar.gz
rust-40ee35904667dceac4e2210d0cb99bae5e981349.zip
Auto merge of #16810 - Young-Flash:unused_var_fix, r=Veykril
feat: add fix for unused_variables

add a leading underscore for unused variable
-rw-r--r--crates/ide-diagnostics/src/handlers/mutability_errors.rs10
-rw-r--r--crates/ide-diagnostics/src/handlers/unused_variables.rs121
2 files changed, 115 insertions, 16 deletions
diff --git a/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 91f1058d65b..34a0038295f 100644
--- a/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -413,7 +413,7 @@ fn main() {
 fn main() {
     return;
     let mut x = 2;
-      //^^^^^ warn: unused variable
+      //^^^^^ 💡 warn: unused variable
     &mut x;
 }
 "#,
@@ -423,7 +423,7 @@ fn main() {
 fn main() {
     loop {}
     let mut x = 2;
-      //^^^^^ warn: unused variable
+      //^^^^^ 💡 warn: unused variable
     &mut x;
 }
 "#,
@@ -444,7 +444,7 @@ fn main(b: bool) {
         g();
     }
     let mut x = 2;
-      //^^^^^ warn: unused variable
+      //^^^^^ 💡 warn: unused variable
     &mut x;
 }
 "#,
@@ -459,7 +459,7 @@ fn main(b: bool) {
         return;
     }
     let mut x = 2;
-      //^^^^^ warn: unused variable
+      //^^^^^ 💡 warn: unused variable
     &mut x;
 }
 "#,
@@ -789,7 +789,7 @@ fn f() {
                //^^ 💡 error: cannot mutate immutable variable `x`
     _ = (x, y);
     let x = Foo;
-      //^ warn: unused variable
+      //^ 💡 warn: unused variable
     let x = Foo;
     let y: &mut (i32, u8) = &mut x;
                           //^^^^^^ 💡 error: cannot mutate immutable variable `x`
diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs
index 28ccf474b40..a9e1d07d7c5 100644
--- a/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -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};
 
 // Diagnostic: unused-variables
@@ -8,18 +16,38 @@ pub(crate) fn unused_variables(
     d: &hir::UnusedVariable,
 ) -> Diagnostic {
     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(
         ctx,
         DiagnosticCode::RustcLint("unused_variables"),
         "unused variable",
         ast,
     )
+    .with_fixes(fixes(&var_name, diagnostic_range, ast.file_id.is_macro()))
     .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)]
 mod tests {
-    use crate::tests::check_diagnostics;
+    use crate::tests::{check_diagnostics, check_fix, check_no_fix};
 
     #[test]
     fn unused_variables_simple() {
@@ -29,23 +57,23 @@ mod tests {
 struct Foo { f1: i32, f2: i64 }
 
 fn f(kkk: i32) {}
-   //^^^ warn: unused variable
+   //^^^ 💡 warn: unused variable
 fn main() {
     let a = 2;
-      //^ warn: unused variable
+      //^ 💡 warn: unused variable
     let b = 5;
     // note: `unused variable` implies `unused mut`, so we should not emit both at the same time.
     let mut c = f(b);
-      //^^^^^ warn: unused variable
+      //^^^^^ 💡 warn: unused variable
     let (d, e) = (3, 5);
-       //^ warn: unused variable
+       //^ 💡 warn: unused variable
     let _ = e;
     let f1 = 2;
     let f2 = 5;
     let f = Foo { f1, f2 };
     match f {
         Foo { f1, f2 } => {
-            //^^ warn: unused variable
+            //^^ 💡 warn: unused variable
             _ = f2;
         }
     }
@@ -53,7 +81,7 @@ fn main() {
     if g {}
     let h: fn() -> i32 = || 2;
     let i = h();
-      //^ warn: unused variable
+      //^ 💡 warn: unused variable
 }
 "#,
         );
@@ -67,11 +95,11 @@ struct S {
 }
 impl S {
     fn owned_self(self, u: i32) {}
-                      //^ warn: unused variable
+                      //^ 💡 warn: unused variable
     fn ref_self(&self, u: i32) {}
-                     //^ warn: unused variable
+                     //^ 💡 warn: unused variable
     fn ref_mut_self(&mut self, u: i32) {}
-                             //^ warn: unused variable
+                             //^ 💡 warn: unused variable
     fn owned_mut_self(mut self) {}
                     //^^^^^^^^ 💡 warn: variable does not need to be mutable
 
@@ -103,7 +131,78 @@ fn main() {
 #[deny(unused)]
 fn main2() {
     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!();
 }
 "#,
         );