1+ use ide_db:: {
2+ assists:: { Assist , AssistId , AssistKind } ,
3+ base_db:: FileRange ,
4+ label:: Label ,
5+ source_change:: SourceChange ,
6+ } ;
7+ use text_edit:: TextEdit ;
8+
19use crate :: { Diagnostic , DiagnosticCode , DiagnosticsContext } ;
210
311// Diagnostic: unused-variables
@@ -8,18 +16,38 @@ pub(crate) fn unused_variables(
816 d : & hir:: UnusedVariable ,
917) -> Diagnostic {
1018 let ast = d. local . primary_source ( ctx. sema . db ) . syntax_ptr ( ) ;
19+ let diagnostic_range = ctx. sema . diagnostics_display_range ( ast) ;
20+ let var_name = d. local . primary_source ( ctx. sema . db ) . syntax ( ) . to_string ( ) ;
1121 Diagnostic :: new_with_syntax_node_ptr (
1222 ctx,
1323 DiagnosticCode :: RustcLint ( "unused_variables" ) ,
1424 "unused variable" ,
1525 ast,
1626 )
27+ . with_fixes ( fixes ( & var_name, diagnostic_range, ast. file_id . is_macro ( ) ) )
1728 . experimental ( )
1829}
1930
31+ fn fixes ( var_name : & String , diagnostic_range : FileRange , is_in_marco : bool ) -> Option < Vec < Assist > > {
32+ if is_in_marco {
33+ return None ;
34+ }
35+ Some ( vec ! [ Assist {
36+ id: AssistId ( "unscore_unused_variable_name" , AssistKind :: QuickFix ) ,
37+ label: Label :: new( format!( "Rename unused {} to _{}" , var_name, var_name) ) ,
38+ group: None ,
39+ target: diagnostic_range. range,
40+ source_change: Some ( SourceChange :: from_text_edit(
41+ diagnostic_range. file_id,
42+ TextEdit :: replace( diagnostic_range. range, format!( "_{}" , var_name) ) ,
43+ ) ) ,
44+ trigger_signature_help: false ,
45+ } ] )
46+ }
47+
2048#[ cfg( test) ]
2149mod tests {
22- use crate :: tests:: check_diagnostics;
50+ use crate :: tests:: { check_diagnostics, check_fix , check_no_fix } ;
2351
2452 #[ test]
2553 fn unused_variables_simple ( ) {
@@ -29,31 +57,31 @@ mod tests {
2957struct Foo { f1: i32, f2: i64 }
3058
3159fn f(kkk: i32) {}
32- //^^^ warn: unused variable
60+ //^^^ 💡 warn: unused variable
3361fn main() {
3462 let a = 2;
35- //^ warn: unused variable
63+ //^ 💡 warn: unused variable
3664 let b = 5;
3765 // note: `unused variable` implies `unused mut`, so we should not emit both at the same time.
3866 let mut c = f(b);
39- //^^^^^ warn: unused variable
67+ //^^^^^ 💡 warn: unused variable
4068 let (d, e) = (3, 5);
41- //^ warn: unused variable
69+ //^ 💡 warn: unused variable
4270 let _ = e;
4371 let f1 = 2;
4472 let f2 = 5;
4573 let f = Foo { f1, f2 };
4674 match f {
4775 Foo { f1, f2 } => {
48- //^^ warn: unused variable
76+ //^^ 💡 warn: unused variable
4977 _ = f2;
5078 }
5179 }
5280 let g = false;
5381 if g {}
5482 let h: fn() -> i32 = || 2;
5583 let i = h();
56- //^ warn: unused variable
84+ //^ 💡 warn: unused variable
5785}
5886"# ,
5987 ) ;
@@ -67,11 +95,11 @@ struct S {
6795}
6896impl S {
6997 fn owned_self(self, u: i32) {}
70- //^ warn: unused variable
98+ //^ 💡 warn: unused variable
7199 fn ref_self(&self, u: i32) {}
72- //^ warn: unused variable
100+ //^ 💡 warn: unused variable
73101 fn ref_mut_self(&mut self, u: i32) {}
74- //^ warn: unused variable
102+ //^ 💡 warn: unused variable
75103 fn owned_mut_self(mut self) {}
76104 //^^^^^^^^ 💡 warn: variable does not need to be mutable
77105
@@ -103,7 +131,78 @@ fn main() {
103131#[deny(unused)]
104132fn main2() {
105133 let x = 2;
106- //^ error: unused variable
134+ //^ 💡 error: unused variable
135+ }
136+ "# ,
137+ ) ;
138+ }
139+
140+ #[ test]
141+ fn fix_unused_variable ( ) {
142+ check_fix (
143+ r#"
144+ fn main() {
145+ let x$0 = 2;
146+ }
147+ "# ,
148+ r#"
149+ fn main() {
150+ let _x = 2;
151+ }
152+ "# ,
153+ ) ;
154+
155+ check_fix (
156+ r#"
157+ fn main() {
158+ let ($0d, _e) = (3, 5);
159+ }
160+ "# ,
161+ r#"
162+ fn main() {
163+ let (_d, _e) = (3, 5);
164+ }
165+ "# ,
166+ ) ;
167+
168+ check_fix (
169+ r#"
170+ struct Foo { f1: i32, f2: i64 }
171+ fn main() {
172+ let f = Foo { f1: 0, f2: 0 };
173+ match f {
174+ Foo { f1$0, f2 } => {
175+ _ = f2;
176+ }
177+ }
178+ }
179+ "# ,
180+ r#"
181+ struct Foo { f1: i32, f2: i64 }
182+ fn main() {
183+ let f = Foo { f1: 0, f2: 0 };
184+ match f {
185+ Foo { _f1, f2 } => {
186+ _ = f2;
187+ }
188+ }
189+ }
190+ "# ,
191+ ) ;
192+ }
193+
194+ #[ test]
195+ fn no_fix_for_marco ( ) {
196+ check_no_fix (
197+ r#"
198+ macro_rules! my_macro {
199+ () => {
200+ let x = 3;
201+ };
202+ }
203+
204+ fn main() {
205+ $0my_macro!();
107206}
108207"# ,
109208 ) ;
0 commit comments