@@ -416,24 +416,73 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
416416 }
417417}
418418
419- /// Extract args from an assert-like macro.
420- /// Currently working with:
421- /// - `assert!`, `assert_eq!` and `assert_ne!`
422- /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
423- /// For example:
424- /// `assert!(expr)` will return `Some([expr])`
425- /// `debug_assert_eq!(a, b)` will return `Some([a, b])`
426- pub fn extract_assert_macro_args < ' tcx > ( e : & ' tcx Expr < ' tcx > ) -> Option < Vec < & ' tcx Expr < ' tcx > > > {
419+ /// A parsed
420+ /// assert!`, `assert_eq!` or `assert_ne!`,
421+ /// debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
422+ /// macro.
423+ pub struct AssertExpn < ' tcx > {
424+ /// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
425+ pub first_assert_argument : & ' tcx Expr < ' tcx > ,
426+ /// second argument of the asset for case `assert_eq!`,
427+ /// `assert_ne!` etc ... Eg var_2 in `debug_assert_eq!(x, var_2,..)`
428+ pub second_assert_argument : Option < & ' tcx Expr < ' tcx > > ,
429+ /// The format argument passed at the end of the macro
430+ pub format_arg : Option < FormatArgsExpn < ' tcx > > ,
431+ }
432+
433+ impl < ' tcx > AssertExpn < ' tcx > {
434+ /// Extract args from an assert-like macro.
435+ /// Currently working with:
436+ /// - `assert!`, `assert_eq!` and `assert_ne!`
437+ /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
438+ /// For example:
439+ /// `assert!(expr)` will return `Some(AssertExpn { first_assert_argument: expr,
440+ /// second_assert_argument: None, format_arg:None })` `debug_assert_eq!(a, b)` will return
441+ /// `Some(AssertExpn { first_assert_argument: a, second_assert_argument: Some(b),
442+ /// format_arg:None })`
443+ pub fn parse ( e : & ' tcx Expr < ' tcx > ) -> Option < Self > {
444+ if let ExprKind :: Block ( block, _) = e. kind {
445+ if block. stmts . len ( ) == 1 {
446+ if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
447+ // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
448+ if_chain ! {
449+ if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
450+ if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
451+ 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+ } ) ;
457+ }
458+ }
459+
460+ // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
461+ if_chain ! {
462+ if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
463+ if let Some ( matchblock_expr) = matchblock. expr;
464+ then {
465+ return Self :: ast_matchblock( matchblock_expr) ;
466+ }
467+ }
468+ }
469+ } else if let Some ( matchblock_expr) = block. expr {
470+ // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
471+ return Self :: ast_matchblock ( matchblock_expr) ;
472+ }
473+ }
474+ None
475+ }
476+
427477 /// Try to match the AST for a pattern that contains a match, for example when two args are
428478 /// compared
429- fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Vec < & Expr < ' _ > > > {
479+ fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Self > {
430480 if_chain ! {
431481 if let ExprKind :: Match ( headerexpr, arms, _) = & matchblock_expr. kind;
432482 if let ExprKind :: Tup ( [ lhs, rhs] ) = & headerexpr. kind;
433483 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, lhs) = lhs. kind;
434484 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, rhs) = rhs. kind;
435485 then {
436- let mut vec_arg = vec![ lhs, rhs] ;
437486 if_chain! {
438487 if !arms. is_empty( ) ;
439488 if let ExprKind :: Block ( Block { expr: Some ( if_expr) , ..} , _) = arms[ 0 ] . body. kind;
@@ -444,47 +493,43 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
444493 | StmtKind :: Semi ( call_assert_failed) = stmts_if_block[ 1 ] . kind;
445494 if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
446495 if args_assert_failed. len( ) >= 4 ;
447- if let ExprKind :: Call ( _, args) = args_assert_failed[ 3 ] . kind;
448- if !args. is_empty( ) ;
449- if let Some ( mut format_arg_expn) = FormatArgsExpn :: parse( & args[ 0 ] ) ;
496+ if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 3 ] . kind;
497+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( & arg) ;
450498 then {
451- vec_arg. push( format_arg_expn. format_string) ;
452- vec_arg. append( & mut format_arg_expn. value_args) ;
499+ return Some ( AssertExpn {
500+ first_assert_argument: lhs,
501+ second_assert_argument: Some ( rhs) ,
502+ format_arg: Some ( format_arg_expn)
503+ } ) ;
504+ }
505+ else {
506+ return Some ( AssertExpn {
507+ first_assert_argument: lhs,
508+ second_assert_argument:
509+ Some ( rhs) ,
510+ format_arg: None
511+ } ) ;
453512 }
454513 }
455- return Some ( vec_arg) ;
456514 }
457515 }
458516 None
459517 }
460518
461- if let ExprKind :: Block ( block, _) = e. kind {
462- if block. stmts . len ( ) == 1 {
463- if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
464- // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
465- if_chain ! {
466- if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
467- if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
468- then {
469- return Some ( vec![ condition] ) ;
470- }
471- }
472-
473- // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
474- if_chain ! {
475- if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
476- if let Some ( matchblock_expr) = matchblock. expr;
477- then {
478- return ast_matchblock( matchblock_expr) ;
479- }
480- }
519+ /// Gives the argument as a vector
520+ pub fn argument_vector ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
521+ let mut expr_vec = vec ! [ self . first_assert_argument] ;
522+ if let Some ( sec_agr) = self . second_assert_argument {
523+ expr_vec. push ( sec_agr) ;
524+ }
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)
481529 }
482- } else if let Some ( matchblock_expr) = block. expr {
483- // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
484- return ast_matchblock ( matchblock_expr) ;
485530 }
531+ expr_vec
486532 }
487- None
488533}
489534
490535/// A parsed `format!` expansion
0 commit comments