1
1
mod let_unit_value;
2
+ mod unit_arg;
2
3
mod unit_cmp;
3
4
mod utils;
4
5
5
- use rustc_errors:: Applicability ;
6
- use rustc_hir as hir;
7
- use rustc_hir:: { Block , Expr , ExprKind , MatchSource , Node , Stmt , StmtKind } ;
6
+ use rustc_hir:: { Expr , Stmt } ;
8
7
use rustc_lint:: { LateContext , LateLintPass } ;
9
8
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
10
9
11
- use if_chain:: if_chain;
12
-
13
- use crate :: utils:: diagnostics:: span_lint_and_then;
14
- use crate :: utils:: source:: { indent_of, reindent_multiline, snippet_opt} ;
15
-
16
- use utils:: { is_unit, is_unit_literal} ;
17
-
18
10
declare_clippy_lint ! {
19
11
/// **What it does:** Checks for binding a unit value.
20
12
///
@@ -81,18 +73,6 @@ declare_clippy_lint! {
81
73
"comparing unit values"
82
74
}
83
75
84
- declare_lint_pass ! ( UnitTypes => [ LET_UNIT_VALUE , UNIT_CMP ] ) ;
85
-
86
- impl LateLintPass < ' _ > for UnitTypes {
87
- fn check_stmt ( & mut self , cx : & LateContext < ' _ > , stmt : & Stmt < ' _ > ) {
88
- let_unit_value:: check ( cx, stmt) ;
89
- }
90
-
91
- fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
92
- unit_cmp:: check ( cx, expr) ;
93
- }
94
- }
95
-
96
76
declare_clippy_lint ! {
97
77
/// **What it does:** Checks for passing a unit value as an argument to a function without using a
98
78
/// unit literal (`()`).
@@ -113,205 +93,15 @@ declare_clippy_lint! {
113
93
"passing unit to a function"
114
94
}
115
95
116
- declare_lint_pass ! ( UnitArg => [ UNIT_ARG ] ) ;
117
-
118
- impl < ' tcx > LateLintPass < ' tcx > for UnitArg {
119
- fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
120
- if expr. span . from_expansion ( ) {
121
- return ;
122
- }
123
-
124
- // apparently stuff in the desugaring of `?` can trigger this
125
- // so check for that here
126
- // only the calls to `Try::from_error` is marked as desugared,
127
- // so we need to check both the current Expr and its parent.
128
- if is_questionmark_desugar_marked_call ( expr) {
129
- return ;
130
- }
131
- if_chain ! {
132
- let map = & cx. tcx. hir( ) ;
133
- let opt_parent_node = map. find( map. get_parent_node( expr. hir_id) ) ;
134
- if let Some ( hir:: Node :: Expr ( parent_expr) ) = opt_parent_node;
135
- if is_questionmark_desugar_marked_call( parent_expr) ;
136
- then {
137
- return ;
138
- }
139
- }
140
-
141
- match expr. kind {
142
- ExprKind :: Call ( _, args) | ExprKind :: MethodCall ( _, _, args, _) => {
143
- let args_to_recover = args
144
- . iter ( )
145
- . filter ( |arg| {
146
- if is_unit ( cx. typeck_results ( ) . expr_ty ( arg) ) && !is_unit_literal ( arg) {
147
- !matches ! (
148
- & arg. kind,
149
- ExprKind :: Match ( .., MatchSource :: TryDesugar ) | ExprKind :: Path ( ..)
150
- )
151
- } else {
152
- false
153
- }
154
- } )
155
- . collect :: < Vec < _ > > ( ) ;
156
- if !args_to_recover. is_empty ( ) {
157
- lint_unit_args ( cx, expr, & args_to_recover) ;
158
- }
159
- } ,
160
- _ => ( ) ,
161
- }
162
- }
163
- }
96
+ declare_lint_pass ! ( UnitTypes => [ LET_UNIT_VALUE , UNIT_CMP , UNIT_ARG ] ) ;
164
97
165
- fn is_questionmark_desugar_marked_call ( expr : & Expr < ' _ > ) -> bool {
166
- use rustc_span:: hygiene:: DesugaringKind ;
167
- if let ExprKind :: Call ( ref callee, _) = expr. kind {
168
- callee. span . is_desugaring ( DesugaringKind :: QuestionMark )
169
- } else {
170
- false
98
+ impl LateLintPass < ' _ > for UnitTypes {
99
+ fn check_stmt ( & mut self , cx : & LateContext < ' _ > , stmt : & Stmt < ' _ > ) {
100
+ let_unit_value:: check ( cx, stmt) ;
171
101
}
172
- }
173
-
174
- fn lint_unit_args ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , args_to_recover : & [ & Expr < ' _ > ] ) {
175
- let mut applicability = Applicability :: MachineApplicable ;
176
- let ( singular, plural) = if args_to_recover. len ( ) > 1 {
177
- ( "" , "s" )
178
- } else {
179
- ( "a " , "" )
180
- } ;
181
- span_lint_and_then (
182
- cx,
183
- UNIT_ARG ,
184
- expr. span ,
185
- & format ! ( "passing {}unit value{} to a function" , singular, plural) ,
186
- |db| {
187
- let mut or = "" ;
188
- args_to_recover
189
- . iter ( )
190
- . filter_map ( |arg| {
191
- if_chain ! {
192
- if let ExprKind :: Block ( block, _) = arg. kind;
193
- if block. expr. is_none( ) ;
194
- if let Some ( last_stmt) = block. stmts. iter( ) . last( ) ;
195
- if let StmtKind :: Semi ( last_expr) = last_stmt. kind;
196
- if let Some ( snip) = snippet_opt( cx, last_expr. span) ;
197
- then {
198
- Some ( (
199
- last_stmt. span,
200
- snip,
201
- ) )
202
- }
203
- else {
204
- None
205
- }
206
- }
207
- } )
208
- . for_each ( |( span, sugg) | {
209
- db. span_suggestion (
210
- span,
211
- "remove the semicolon from the last statement in the block" ,
212
- sugg,
213
- Applicability :: MaybeIncorrect ,
214
- ) ;
215
- or = "or " ;
216
- applicability = Applicability :: MaybeIncorrect ;
217
- } ) ;
218
-
219
- let arg_snippets: Vec < String > = args_to_recover
220
- . iter ( )
221
- . filter_map ( |arg| snippet_opt ( cx, arg. span ) )
222
- . collect ( ) ;
223
- let arg_snippets_without_empty_blocks: Vec < String > = args_to_recover
224
- . iter ( )
225
- . filter ( |arg| !is_empty_block ( arg) )
226
- . filter_map ( |arg| snippet_opt ( cx, arg. span ) )
227
- . collect ( ) ;
228
-
229
- if let Some ( call_snippet) = snippet_opt ( cx, expr. span ) {
230
- let sugg = fmt_stmts_and_call (
231
- cx,
232
- expr,
233
- & call_snippet,
234
- & arg_snippets,
235
- & arg_snippets_without_empty_blocks,
236
- ) ;
237
102
238
- if arg_snippets_without_empty_blocks. is_empty ( ) {
239
- db. multipart_suggestion (
240
- & format ! ( "use {}unit literal{} instead" , singular, plural) ,
241
- args_to_recover
242
- . iter ( )
243
- . map ( |arg| ( arg. span , "()" . to_string ( ) ) )
244
- . collect :: < Vec < _ > > ( ) ,
245
- applicability,
246
- ) ;
247
- } else {
248
- let plural = arg_snippets_without_empty_blocks. len ( ) > 1 ;
249
- let empty_or_s = if plural { "s" } else { "" } ;
250
- let it_or_them = if plural { "them" } else { "it" } ;
251
- db. span_suggestion (
252
- expr. span ,
253
- & format ! (
254
- "{}move the expression{} in front of the call and replace {} with the unit literal `()`" ,
255
- or, empty_or_s, it_or_them
256
- ) ,
257
- sugg,
258
- applicability,
259
- ) ;
260
- }
261
- }
262
- } ,
263
- ) ;
264
- }
265
-
266
- fn is_empty_block ( expr : & Expr < ' _ > ) -> bool {
267
- matches ! (
268
- expr. kind,
269
- ExprKind :: Block (
270
- Block {
271
- stmts: & [ ] ,
272
- expr: None ,
273
- ..
274
- } ,
275
- _,
276
- )
277
- )
278
- }
279
-
280
- fn fmt_stmts_and_call (
281
- cx : & LateContext < ' _ > ,
282
- call_expr : & Expr < ' _ > ,
283
- call_snippet : & str ,
284
- args_snippets : & [ impl AsRef < str > ] ,
285
- non_empty_block_args_snippets : & [ impl AsRef < str > ] ,
286
- ) -> String {
287
- let call_expr_indent = indent_of ( cx, call_expr. span ) . unwrap_or ( 0 ) ;
288
- let call_snippet_with_replacements = args_snippets
289
- . iter ( )
290
- . fold ( call_snippet. to_owned ( ) , |acc, arg| acc. replacen ( arg. as_ref ( ) , "()" , 1 ) ) ;
291
-
292
- let mut stmts_and_call = non_empty_block_args_snippets
293
- . iter ( )
294
- . map ( |it| it. as_ref ( ) . to_owned ( ) )
295
- . collect :: < Vec < _ > > ( ) ;
296
- stmts_and_call. push ( call_snippet_with_replacements) ;
297
- stmts_and_call = stmts_and_call
298
- . into_iter ( )
299
- . map ( |v| reindent_multiline ( v. into ( ) , true , Some ( call_expr_indent) ) . into_owned ( ) )
300
- . collect ( ) ;
301
-
302
- let mut stmts_and_call_snippet = stmts_and_call. join ( & format ! ( "{}{}" , ";\n " , " " . repeat( call_expr_indent) ) ) ;
303
- // expr is not in a block statement or result expression position, wrap in a block
304
- let parent_node = cx. tcx . hir ( ) . find ( cx. tcx . hir ( ) . get_parent_node ( call_expr. hir_id ) ) ;
305
- if !matches ! ( parent_node, Some ( Node :: Block ( _) ) ) && !matches ! ( parent_node, Some ( Node :: Stmt ( _) ) ) {
306
- let block_indent = call_expr_indent + 4 ;
307
- stmts_and_call_snippet =
308
- reindent_multiline ( stmts_and_call_snippet. into ( ) , true , Some ( block_indent) ) . into_owned ( ) ;
309
- stmts_and_call_snippet = format ! (
310
- "{{\n {}{}\n {}}}" ,
311
- " " . repeat( block_indent) ,
312
- & stmts_and_call_snippet,
313
- " " . repeat( call_expr_indent)
314
- ) ;
103
+ fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
104
+ unit_cmp:: check ( cx, expr) ;
105
+ unit_arg:: check ( cx, expr) ;
315
106
}
316
- stmts_and_call_snippet
317
107
}
0 commit comments