1
1
use clippy_utils:: diagnostics:: { span_lint, span_lint_and_then} ;
2
- use clippy_utils:: macros:: { root_macro_call_first_node, FormatArgsExpn , MacroCall } ;
2
+ use clippy_utils:: macros:: { root_macro_call_first_node, FormatArgsArg , FormatArgsExpn , MacroCall } ;
3
3
use clippy_utils:: source:: snippet_opt;
4
4
use rustc_ast:: LitKind ;
5
5
use rustc_errors:: Applicability ;
@@ -275,6 +275,9 @@ impl<'tcx> LateLintPass<'tcx> for Write {
275
275
}
276
276
277
277
let Some ( format_args) = FormatArgsExpn :: find_nested ( cx, expr, macro_call. expn ) else { return } ;
278
+ if format_args. format_string_span . from_expansion ( ) {
279
+ return ;
280
+ }
278
281
279
282
match diag_name {
280
283
sym:: print_macro | sym:: eprint_macro | sym:: write_macro => {
@@ -286,20 +289,11 @@ impl<'tcx> LateLintPass<'tcx> for Write {
286
289
_ => { } ,
287
290
}
288
291
289
- check_literal ( cx, & format_args, name) ;
292
+ let Some ( args) = format_args. args ( cx) else { return } ;
293
+ check_literal ( cx, & args, name, format_args. is_raw ( cx) ) ;
290
294
291
- if !self . in_debug_impl
292
- && format_args
293
- . formatters
294
- . iter ( )
295
- . any ( |& ( _, formatter) | formatter == sym:: Debug )
296
- {
297
- span_lint (
298
- cx,
299
- USE_DEBUG ,
300
- format_args. format_string_span ,
301
- "use of `Debug`-based formatting" ,
302
- ) ;
295
+ if !self . in_debug_impl {
296
+ check_use_debug ( cx, & args) ;
303
297
}
304
298
}
305
299
}
@@ -335,7 +329,6 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c
335
329
} ;
336
330
337
331
if_chain ! {
338
- if !format_string_span. from_expansion( ) ;
339
332
if last. as_str( ) . ends_with( '\n' ) ;
340
333
341
334
// ignore format strings with other internal vertical whitespace
@@ -401,9 +394,6 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma
401
394
let mut span = format_args. format_string_span;
402
395
403
396
if part. as_str( ) == "\n " ;
404
- // `println!()` is also represented with an "\n" format string part, but
405
- // its span is from an expansion
406
- if !span. from_expansion( ) ;
407
397
then {
408
398
let lint = if name == "writeln" {
409
399
span = expand_past_previous_comma( cx, span) ;
@@ -432,15 +422,9 @@ fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, ma
432
422
}
433
423
}
434
424
435
- fn check_literal < ' tcx > ( cx : & LateContext < ' tcx > , format_args : & FormatArgsExpn < ' tcx > , name : & str ) {
436
- if format_args. format_string_span . from_expansion ( ) {
437
- return ;
438
- }
439
- let raw = format_args. is_raw ( cx) ;
440
-
441
- let Some ( args) = format_args. args ( cx) else { return } ;
425
+ fn check_literal ( cx : & LateContext < ' _ > , args : & [ FormatArgsArg < ' _ > ] , name : & str , raw : bool ) {
442
426
let mut counts = HirIdMap :: < usize > :: default ( ) ;
443
- for arg in & args {
427
+ for arg in args {
444
428
* counts. entry ( arg. value . hir_id ) . or_default ( ) += 1 ;
445
429
}
446
430
@@ -505,3 +489,16 @@ fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
505
489
let extended = cx. sess ( ) . source_map ( ) . span_extend_to_prev_char ( span, ',' , true ) ;
506
490
extended. with_lo ( extended. lo ( ) - BytePos ( 1 ) )
507
491
}
492
+
493
+ fn check_use_debug ( cx : & LateContext < ' _ > , args : & [ FormatArgsArg < ' _ > ] ) {
494
+ for arg in args {
495
+ if arg. format_trait == sym:: Debug {
496
+ span_lint (
497
+ cx,
498
+ USE_DEBUG ,
499
+ arg. span ,
500
+ "use of `Debug`-based formatting" ,
501
+ ) ;
502
+ }
503
+ }
504
+ }
0 commit comments