33#![ deny( clippy:: missing_docs_in_private_items) ]
44
55use crate :: ty:: is_type_diagnostic_item;
6- use crate :: { is_expn_of, last_path_segment, match_def_path, paths} ;
6+ use crate :: { is_expn_of, last_path_segment, match_def_path, paths, source :: snippet_with_applicability } ;
77use if_chain:: if_chain;
88use rustc_ast:: ast:: { self , LitKind } ;
9+ use rustc_errors:: Applicability ;
910use rustc_hir as hir;
1011use rustc_hir:: {
1112 Arm , Block , BorrowKind , Expr , ExprKind , HirId , LoopSource , MatchSource , Node , Pat , QPath , StmtKind , UnOp ,
1213} ;
1314use rustc_lint:: LateContext ;
1415use rustc_span:: { sym, symbol, ExpnKind , Span , Symbol } ;
1516
17+ use std:: borrow:: Cow ;
18+
1619/// The essential nodes of a desugared for loop as well as the entire span:
1720/// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, span)`.
1821pub struct ForLoop < ' tcx > {
@@ -419,8 +422,8 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
419422}
420423
421424/// A parsed
422- /// assert!`, `assert_eq!` or `assert_ne!`,
423- /// debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
425+ /// ` assert!`, `assert_eq!` or `assert_ne!`,
426+ /// ` debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
424427/// macro.
425428pub struct AssertExpn < ' tcx > {
426429 /// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
@@ -448,14 +451,33 @@ impl<'tcx> AssertExpn<'tcx> {
448451 if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
449452 // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
450453 if_chain ! {
451- if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
454+ if let Some ( If { cond, then , .. } ) = If :: hir( matchexpr) ;
452455 if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
453456 then {
454- return Some ( Self {
455- first_assert_argument: condition,
456- second_assert_argument: None ,
457- format_arg: None , // FIXME actually parse the aguments
458- } ) ;
457+ if_chain! {
458+ if let ExprKind :: Block ( block, _) = then. kind;
459+ if let [ statement, ..] = block. stmts;
460+ if let StmtKind :: Expr ( call_assert_failed)
461+ | StmtKind :: Semi ( call_assert_failed) = statement. kind;
462+ if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
463+ if !args_assert_failed. is_empty( ) ;
464+ if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 0 ] . kind;
465+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
466+ then {
467+ return Some ( Self {
468+ first_assert_argument: condition,
469+ second_assert_argument: None ,
470+ format_arg: Some ( format_arg_expn) , // FIXME actually parse the aguments
471+ } ) ;
472+ }
473+ else{
474+ return Some ( Self {
475+ first_assert_argument: condition,
476+ second_assert_argument: None ,
477+ format_arg: None ,
478+ } ) ;
479+ }
480+ }
459481 }
460482 }
461483
@@ -496,7 +518,7 @@ impl<'tcx> AssertExpn<'tcx> {
496518 if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
497519 if args_assert_failed. len( ) >= 4 ;
498520 if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 3 ] . kind;
499- if let Some ( format_arg_expn) = FormatArgsExpn :: parse( & arg) ;
521+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( arg) ;
500522 then {
501523 return Some ( AssertExpn {
502524 first_assert_argument: lhs,
@@ -518,19 +540,49 @@ impl<'tcx> AssertExpn<'tcx> {
518540 None
519541 }
520542
521- /// Gives the argument as a vector
522- pub fn argument_vector ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
543+ /// Gives the argument in the comparaison as a vector leaving the format
544+ pub fn assert_arguments ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
523545 let mut expr_vec = vec ! [ self . first_assert_argument] ;
524546 if let Some ( sec_agr) = self . second_assert_argument {
525547 expr_vec. push ( sec_agr) ;
526548 }
527- if let Some ( ref format_arg) = self . format_arg {
528- expr_vec. push ( format_arg. format_string ) ;
529- for arg in & format_arg. value_args {
530- expr_vec. push ( arg)
549+ expr_vec
550+ }
551+
552+ /// Gives the argument passed to the macro as a string
553+ pub fn all_arguments_string (
554+ & self ,
555+ cx : & LateContext < ' _ > ,
556+ applicability : & mut Applicability ,
557+ ) -> Vec < Cow < ' static , str > > {
558+ let mut vec_arg = vec ! [ snippet_with_applicability(
559+ cx,
560+ self . first_assert_argument. span,
561+ ".." ,
562+ applicability,
563+ ) ] ;
564+ if let Some ( sec_agr) = self . second_assert_argument {
565+ vec_arg. push ( snippet_with_applicability ( cx, sec_agr. span , ".." , applicability) ) ;
566+ }
567+ vec_arg. append ( & mut self . format_arguments ( cx, applicability) ) ;
568+ vec_arg
569+ }
570+
571+ /// Returns only the format agruments
572+ pub fn format_arguments ( & self , cx : & LateContext < ' _ > , applicability : & mut Applicability ) -> Vec < Cow < ' static , str > > {
573+ let mut vec_arg = vec ! [ ] ;
574+ if let Some ( ref fmt_arg) = self . format_arg {
575+ vec_arg. push ( snippet_with_applicability (
576+ cx,
577+ fmt_arg. format_string_span ,
578+ ".." ,
579+ applicability,
580+ ) ) ;
581+ for arg in & fmt_arg. value_args {
582+ vec_arg. push ( snippet_with_applicability ( cx, arg. span , ".." , applicability) ) ;
531583 }
532584 }
533- expr_vec
585+ vec_arg
534586 }
535587}
536588
@@ -568,8 +620,6 @@ impl FormatExpn<'tcx> {
568620
569621/// A parsed `format_args!` expansion
570622pub struct FormatArgsExpn < ' tcx > {
571- /// The fist argument, the fromat string, as an expr
572- pub format_string : & ' tcx Expr < ' tcx > ,
573623 /// Span of the first argument, the format string
574624 pub format_string_span : Span ,
575625 /// Values passed after the format string
@@ -626,7 +676,6 @@ impl FormatArgsExpn<'tcx> {
626676 if let ExprKind :: Array ( args) = arm. body. kind;
627677 then {
628678 Some ( FormatArgsExpn {
629- format_string: strs_ref,
630679 format_string_span: strs_ref. span,
631680 value_args,
632681 format_string_parts,
0 commit comments