11//! A group of attributes that can be attached to Rust code in order
22//! to generate a clippy lint detecting said code automatically.
33
4+ use clippy_utils:: macros:: { collect_format_args, is_format_macro, root_macro_call_first_node} ;
45use clippy_utils:: { get_attr, higher} ;
56use rustc_ast:: ast:: { LitFloatType , LitKind } ;
67use rustc_ast:: LitIntType ;
@@ -239,14 +240,14 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
239240 }
240241 }
241242
242- fn slice < T > ( & self , slice : & Binding < & [ T ] > , f : impl Fn ( & Binding < & T > ) ) {
243+ fn slice < T > ( & self , slice : & Binding < & [ T ] > , f : impl Fn ( Binding < & T > ) ) {
243244 if slice. value . is_empty ( ) {
244245 chain ! ( self , "{slice}.is_empty()" ) ;
245246 } else {
246247 chain ! ( self , "{slice}.len() == {}" , slice. value. len( ) ) ;
247248 for ( i, value) in slice. value . iter ( ) . enumerate ( ) {
248249 let name = format ! ( "{slice}[{i}]" ) ;
249- f ( & Binding { name, value } ) ;
250+ f ( Binding { name, value } ) ;
250251 }
251252 }
252253 }
@@ -333,6 +334,24 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
333334
334335 #[ allow( clippy:: too_many_lines) ]
335336 fn expr ( & self , expr : & Binding < & hir:: Expr < ' _ > > ) {
337+ if let Some ( macro_call) = root_macro_call_first_node ( self . cx , expr. value )
338+ && is_format_macro ( self . cx , macro_call. def_id )
339+ {
340+ let diag = self . cx . tcx . get_diagnostic_name ( macro_call. def_id ) . unwrap ( ) ;
341+ bind ! ( self , macro_call) ;
342+ chain ! ( self , "let Some({macro_call}) = macros::root_macro_call_first_node(cx, {expr})" ) ;
343+ chain ! ( self , "cx.tcx.is_diagnostic_item(sym::{diag}, {macro_call}.def_id)" ) ;
344+ let exprs = collect_format_args ( self . cx , expr. value , macro_call. value . expn ) ;
345+ let args = exprs. as_slice ( ) ;
346+ bind ! ( self , args) ;
347+ chain ! ( self , "let {args} = macros::collect_format_args(cx, {expr}, {macro_call}.expn)" ) ;
348+ self . slice ( args, |e| {
349+ let expr = Binding { name : e. name , value : * e. value } ;
350+ self . expr ( & expr) ;
351+ } ) ;
352+ return ;
353+ }
354+
336355 if let Some ( higher:: While { condition, body } ) = higher:: While :: hir ( expr. value ) {
337356 bind ! ( self , condition, body) ;
338357 chain ! (
@@ -398,25 +417,25 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
398417 ExprKind :: Array ( elements) => {
399418 bind ! ( self , elements) ;
400419 kind ! ( "Array({elements})" ) ;
401- self . slice ( elements, |e| self . expr ( e) ) ;
420+ self . slice ( elements, |e| self . expr ( & e) ) ;
402421 } ,
403422 ExprKind :: Call ( func, args) => {
404423 bind ! ( self , func, args) ;
405424 kind ! ( "Call({func}, {args})" ) ;
406425 self . expr ( func) ;
407- self . slice ( args, |e| self . expr ( e) ) ;
426+ self . slice ( args, |e| self . expr ( & e) ) ;
408427 } ,
409428 ExprKind :: MethodCall ( method_name, receiver, args, _) => {
410429 bind ! ( self , method_name, receiver, args) ;
411430 kind ! ( "MethodCall({method_name}, {receiver}, {args}, _)" ) ;
412431 self . ident ( field ! ( method_name. ident) ) ;
413432 self . expr ( receiver) ;
414- self . slice ( args, |e| self . expr ( e) ) ;
433+ self . slice ( args, |e| self . expr ( & e) ) ;
415434 } ,
416435 ExprKind :: Tup ( elements) => {
417436 bind ! ( self , elements) ;
418437 kind ! ( "Tup({elements})" ) ;
419- self . slice ( elements, |e| self . expr ( e) ) ;
438+ self . slice ( elements, |e| self . expr ( & e) ) ;
420439 } ,
421440 ExprKind :: Binary ( op, left, right) => {
422441 bind ! ( self , op, left, right) ;
@@ -469,7 +488,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
469488 bind ! ( self , scrutinee, arms) ;
470489 kind ! ( "Match({scrutinee}, {arms}, MatchSource::{des:?})" ) ;
471490 self . expr ( scrutinee) ;
472- self . slice ( arms, |arm| self . arm ( arm) ) ;
491+ self . slice ( arms, |arm| self . arm ( & arm) ) ;
473492 } ,
474493 ExprKind :: Closure ( & Closure {
475494 capture_clause,
@@ -593,7 +612,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
593612 }
594613
595614 fn block ( & self , block : & Binding < & hir:: Block < ' _ > > ) {
596- self . slice ( field ! ( block. stmts) , |stmt| self . stmt ( stmt) ) ;
615+ self . slice ( field ! ( block. stmts) , |stmt| self . stmt ( & stmt) ) ;
597616 self . option ( field ! ( block. expr) , "trailing_expr" , |expr| {
598617 self . expr ( expr) ;
599618 } ) ;
@@ -639,13 +658,13 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
639658 PatKind :: Or ( fields) => {
640659 bind ! ( self , fields) ;
641660 kind ! ( "Or({fields})" ) ;
642- self . slice ( fields, |pat| self . pat ( pat) ) ;
661+ self . slice ( fields, |pat| self . pat ( & pat) ) ;
643662 } ,
644663 PatKind :: TupleStruct ( ref qpath, fields, skip_pos) => {
645664 bind ! ( self , qpath, fields) ;
646665 kind ! ( "TupleStruct(ref {qpath}, {fields}, {skip_pos:?})" ) ;
647666 self . qpath ( qpath) ;
648- self . slice ( fields, |pat| self . pat ( pat) ) ;
667+ self . slice ( fields, |pat| self . pat ( & pat) ) ;
649668 } ,
650669 PatKind :: Path ( ref qpath) => {
651670 bind ! ( self , qpath) ;
@@ -655,7 +674,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
655674 PatKind :: Tuple ( fields, skip_pos) => {
656675 bind ! ( self , fields) ;
657676 kind ! ( "Tuple({fields}, {skip_pos:?})" ) ;
658- self . slice ( fields, |field| self . pat ( field) ) ;
677+ self . slice ( fields, |field| self . pat ( & field) ) ;
659678 } ,
660679 PatKind :: Box ( pat) => {
661680 bind ! ( self , pat) ;
@@ -683,8 +702,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
683702 opt_bind ! ( self , middle) ;
684703 kind ! ( "Slice({start}, {middle}, {end})" ) ;
685704 middle. if_some ( |p| self . pat ( p) ) ;
686- self . slice ( start, |pat| self . pat ( pat) ) ;
687- self . slice ( end, |pat| self . pat ( pat) ) ;
705+ self . slice ( start, |pat| self . pat ( & pat) ) ;
706+ self . slice ( end, |pat| self . pat ( & pat) ) ;
688707 } ,
689708 }
690709 }
0 commit comments