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
+
1
9
use crate :: { Diagnostic , DiagnosticCode , DiagnosticsContext } ;
2
10
3
11
// Diagnostic: unused-variables
@@ -8,18 +16,38 @@ pub(crate) fn unused_variables(
8
16
d : & hir:: UnusedVariable ,
9
17
) -> Diagnostic {
10
18
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 ( ) ;
11
21
Diagnostic :: new_with_syntax_node_ptr (
12
22
ctx,
13
23
DiagnosticCode :: RustcLint ( "unused_variables" ) ,
14
24
"unused variable" ,
15
25
ast,
16
26
)
27
+ . with_fixes ( fixes ( & var_name, diagnostic_range, ast. file_id . is_macro ( ) ) )
17
28
. experimental ( )
18
29
}
19
30
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
+
20
48
#[ cfg( test) ]
21
49
mod tests {
22
- use crate :: tests:: check_diagnostics;
50
+ use crate :: tests:: { check_diagnostics, check_fix , check_no_fix } ;
23
51
24
52
#[ test]
25
53
fn unused_variables_simple ( ) {
@@ -29,31 +57,31 @@ mod tests {
29
57
struct Foo { f1: i32, f2: i64 }
30
58
31
59
fn f(kkk: i32) {}
32
- //^^^ warn: unused variable
60
+ //^^^ 💡 warn: unused variable
33
61
fn main() {
34
62
let a = 2;
35
- //^ warn: unused variable
63
+ //^ 💡 warn: unused variable
36
64
let b = 5;
37
65
// note: `unused variable` implies `unused mut`, so we should not emit both at the same time.
38
66
let mut c = f(b);
39
- //^^^^^ warn: unused variable
67
+ //^^^^^ 💡 warn: unused variable
40
68
let (d, e) = (3, 5);
41
- //^ warn: unused variable
69
+ //^ 💡 warn: unused variable
42
70
let _ = e;
43
71
let f1 = 2;
44
72
let f2 = 5;
45
73
let f = Foo { f1, f2 };
46
74
match f {
47
75
Foo { f1, f2 } => {
48
- //^^ warn: unused variable
76
+ //^^ 💡 warn: unused variable
49
77
_ = f2;
50
78
}
51
79
}
52
80
let g = false;
53
81
if g {}
54
82
let h: fn() -> i32 = || 2;
55
83
let i = h();
56
- //^ warn: unused variable
84
+ //^ 💡 warn: unused variable
57
85
}
58
86
"# ,
59
87
) ;
@@ -67,11 +95,11 @@ struct S {
67
95
}
68
96
impl S {
69
97
fn owned_self(self, u: i32) {}
70
- //^ warn: unused variable
98
+ //^ 💡 warn: unused variable
71
99
fn ref_self(&self, u: i32) {}
72
- //^ warn: unused variable
100
+ //^ 💡 warn: unused variable
73
101
fn ref_mut_self(&mut self, u: i32) {}
74
- //^ warn: unused variable
102
+ //^ 💡 warn: unused variable
75
103
fn owned_mut_self(mut self) {}
76
104
//^^^^^^^^ 💡 warn: variable does not need to be mutable
77
105
@@ -103,7 +131,78 @@ fn main() {
103
131
#[deny(unused)]
104
132
fn main2() {
105
133
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!();
107
206
}
108
207
"# ,
109
208
) ;
0 commit comments