22
33#![ deny( clippy:: missing_docs_in_private_items) ]
44
5- use crate :: { is_expn_of, match_def_path, paths} ;
5+ use crate :: { is_expn_of, match_def_path, paths, source :: snippet_with_applicability } ;
66use if_chain:: if_chain;
77use rustc_ast:: ast:: { self , LitKind } ;
8+ use rustc_errors:: Applicability ;
89use rustc_hir as hir;
910use rustc_hir:: { Arm , Block , BorrowKind , Expr , ExprKind , LoopSource , MatchSource , Node , Pat , StmtKind , UnOp } ;
1011use rustc_lint:: LateContext ;
1112use rustc_span:: { sym, ExpnKind , Span , Symbol } ;
1213
14+ use std:: borrow:: Cow ;
15+
1316/// The essential nodes of a desugared for loop as well as the entire span:
1417/// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, span)`.
1518pub struct ForLoop < ' tcx > {
@@ -417,8 +420,8 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
417420}
418421
419422/// A parsed
420- /// assert!`, `assert_eq!` or `assert_ne!`,
421- /// debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
423+ /// ` assert!`, `assert_eq!` or `assert_ne!`,
424+ /// ` debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
422425/// macro.
423426pub struct AssertExpn < ' tcx > {
424427 /// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
@@ -446,14 +449,33 @@ impl<'tcx> AssertExpn<'tcx> {
446449 if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
447450 // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
448451 if_chain ! {
449- if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
452+ if let Some ( If { cond, then , .. } ) = If :: hir( matchexpr) ;
450453 if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
451454 then {
452- return Some ( Self {
453- first_assert_argument: condition,
454- second_assert_argument: None ,
455- format_arg: None , // FIXME actually parse the aguments
456- } ) ;
455+ if_chain! {
456+ if let ExprKind :: Block ( block, _) = then. kind;
457+ if let [ statement, ..] = block. stmts;
458+ if let StmtKind :: Expr ( call_assert_failed)
459+ | StmtKind :: Semi ( call_assert_failed) = statement. kind;
460+ if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
461+ if !args_assert_failed. is_empty( ) ;
462+ if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 0 ] . kind;
463+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
464+ then {
465+ return Some ( Self {
466+ first_assert_argument: condition,
467+ second_assert_argument: None ,
468+ format_arg: Some ( format_arg_expn) , // FIXME actually parse the aguments
469+ } ) ;
470+ }
471+ else{
472+ return Some ( Self {
473+ first_assert_argument: condition,
474+ second_assert_argument: None ,
475+ format_arg: None ,
476+ } ) ;
477+ }
478+ }
457479 }
458480 }
459481
@@ -494,7 +516,7 @@ impl<'tcx> AssertExpn<'tcx> {
494516 if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
495517 if args_assert_failed. len( ) >= 4 ;
496518 if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 3 ] . kind;
497- if let Some ( format_arg_expn) = FormatArgsExpn :: parse( & arg) ;
519+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
498520 then {
499521 return Some ( AssertExpn {
500522 first_assert_argument: lhs,
@@ -516,19 +538,49 @@ impl<'tcx> AssertExpn<'tcx> {
516538 None
517539 }
518540
519- /// Gives the argument as a vector
520- pub fn argument_vector ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
541+ /// Gives the argument in the comparaison as a vector leaving the format
542+ pub fn assert_arguments ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
521543 let mut expr_vec = vec ! [ self . first_assert_argument] ;
522544 if let Some ( sec_agr) = self . second_assert_argument {
523545 expr_vec. push ( sec_agr) ;
524546 }
525- if let Some ( ref format_arg) = self . format_arg {
526- expr_vec. push ( format_arg. format_string ) ;
527- for arg in & format_arg. value_args {
528- expr_vec. push ( arg)
547+ expr_vec
548+ }
549+
550+ /// Gives the argument passed to the macro as a string
551+ pub fn all_arguments_string (
552+ & self ,
553+ cx : & LateContext < ' _ > ,
554+ applicability : & mut Applicability ,
555+ ) -> Vec < Cow < ' static , str > > {
556+ let mut vec_arg = vec ! [ snippet_with_applicability(
557+ cx,
558+ self . first_assert_argument. span,
559+ ".." ,
560+ applicability,
561+ ) ] ;
562+ if let Some ( sec_agr) = self . second_assert_argument {
563+ vec_arg. push ( snippet_with_applicability ( cx, sec_agr. span , ".." , applicability) ) ;
564+ }
565+ vec_arg. append ( & mut self . format_arguments ( cx, applicability) ) ;
566+ vec_arg
567+ }
568+
569+ /// Returns only the format agruments
570+ pub fn format_arguments ( & self , cx : & LateContext < ' _ > , applicability : & mut Applicability ) -> Vec < Cow < ' static , str > > {
571+ let mut vec_arg = vec ! [ ] ;
572+ if let Some ( ref fmt_arg) = self . format_arg {
573+ vec_arg. push ( snippet_with_applicability (
574+ cx,
575+ fmt_arg. format_string_span ,
576+ ".." ,
577+ applicability,
578+ ) ) ;
579+ for arg in & fmt_arg. value_args {
580+ vec_arg. push ( snippet_with_applicability ( cx, arg. span , ".." , applicability) ) ;
529581 }
530582 }
531- expr_vec
583+ vec_arg
532584 }
533585}
534586
@@ -566,8 +618,6 @@ impl FormatExpn<'tcx> {
566618
567619/// A parsed `format_args!` expansion
568620pub struct FormatArgsExpn < ' tcx > {
569- /// The fist argument, the fromat string, as an expr
570- pub format_string : & ' tcx Expr < ' tcx > ,
571621 /// Span of the first argument, the format string
572622 pub format_string_span : Span ,
573623 /// Values passed after the format string
@@ -629,7 +679,6 @@ impl FormatArgsExpn<'tcx> {
629679 . collect( ) ;
630680 then {
631681 Some ( FormatArgsExpn {
632- format_string: strs_ref,
633682 format_string_span: strs_ref. span,
634683 value_args,
635684 format_string_parts,
0 commit comments