@@ -418,24 +418,73 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
418418 }
419419}
420420
421- /// Extract args from an assert-like macro.
422- /// Currently working with:
423- /// - `assert!`, `assert_eq!` and `assert_ne!`
424- /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
425- /// For example:
426- /// `assert!(expr)` will return `Some([expr])`
427- /// `debug_assert_eq!(a, b)` will return `Some([a, b])`
428- pub fn extract_assert_macro_args < ' tcx > ( e : & ' tcx Expr < ' tcx > ) -> Option < Vec < & ' tcx Expr < ' tcx > > > {
421+ /// A parsed
422+ /// assert!`, `assert_eq!` or `assert_ne!`,
423+ /// debug_assert!`, `debug_assert_eq!` or `debug_assert_ne!`
424+ /// macro.
425+ pub struct AssertExpn < ' tcx > {
426+ /// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
427+ pub first_assert_argument : & ' tcx Expr < ' tcx > ,
428+ /// second argument of the asset for case `assert_eq!`,
429+ /// `assert_ne!` etc ... Eg var_2 in `debug_assert_eq!(x, var_2,..)`
430+ pub second_assert_argument : Option < & ' tcx Expr < ' tcx > > ,
431+ /// The format argument passed at the end of the macro
432+ pub format_arg : Option < FormatArgsExpn < ' tcx > > ,
433+ }
434+
435+ impl < ' tcx > AssertExpn < ' tcx > {
436+ /// Extract args from an assert-like macro.
437+ /// Currently working with:
438+ /// - `assert!`, `assert_eq!` and `assert_ne!`
439+ /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
440+ /// For example:
441+ /// `assert!(expr)` will return `Some(AssertExpn { first_assert_argument: expr,
442+ /// second_assert_argument: None, format_arg:None })` `debug_assert_eq!(a, b)` will return
443+ /// `Some(AssertExpn { first_assert_argument: a, second_assert_argument: Some(b),
444+ /// format_arg:None })`
445+ pub fn parse ( e : & ' tcx Expr < ' tcx > ) -> Option < Self > {
446+ if let ExprKind :: Block ( block, _) = e. kind {
447+ if block. stmts . len ( ) == 1 {
448+ if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
449+ // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
450+ if_chain ! {
451+ if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
452+ if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
453+ 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+ } ) ;
459+ }
460+ }
461+
462+ // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
463+ if_chain ! {
464+ if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
465+ if let Some ( matchblock_expr) = matchblock. expr;
466+ then {
467+ return Self :: ast_matchblock( matchblock_expr) ;
468+ }
469+ }
470+ }
471+ } else if let Some ( matchblock_expr) = block. expr {
472+ // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
473+ return Self :: ast_matchblock ( matchblock_expr) ;
474+ }
475+ }
476+ None
477+ }
478+
429479 /// Try to match the AST for a pattern that contains a match, for example when two args are
430480 /// compared
431- fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Vec < & Expr < ' _ > > > {
481+ fn ast_matchblock ( matchblock_expr : & ' tcx Expr < ' tcx > ) -> Option < Self > {
432482 if_chain ! {
433483 if let ExprKind :: Match ( headerexpr, arms, _) = & matchblock_expr. kind;
434484 if let ExprKind :: Tup ( [ lhs, rhs] ) = & headerexpr. kind;
435485 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, lhs) = lhs. kind;
436486 if let ExprKind :: AddrOf ( BorrowKind :: Ref , _, rhs) = rhs. kind;
437487 then {
438- let mut vec_arg = vec![ lhs, rhs] ;
439488 if_chain! {
440489 if !arms. is_empty( ) ;
441490 if let ExprKind :: Block ( Block { expr: Some ( if_expr) , ..} , _) = arms[ 0 ] . body. kind;
@@ -446,58 +495,43 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
446495 | StmtKind :: Semi ( call_assert_failed) = stmts_if_block[ 1 ] . kind;
447496 if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
448497 if args_assert_failed. len( ) >= 4 ;
449- if let ExprKind :: Call ( _, args) = args_assert_failed[ 3 ] . kind;
450- if !args. is_empty( ) ;
451- if let ExprKind :: Call ( _, args_fmt) = args[ 0 ] . kind;
452- if !args_fmt. is_empty( ) ;
498+ if let ExprKind :: Call ( _, [ arg, ..] ) = args_assert_failed[ 3 ] . kind;
499+ if let Some ( format_arg_expn) = FormatArgsExpn :: parse( & arg) ;
453500 then {
454- vec_arg. push( & args_fmt[ 0 ] ) ;
455- if_chain! {
456- if args_fmt. len( ) >= 2 ;
457- if let ExprKind :: AddrOf ( _, _, expr_match) = args_fmt[ 1 ] . kind;
458- if let ExprKind :: Match ( tup_match, _, _) = expr_match. kind;
459- if let ExprKind :: Tup ( tup_args_list) = tup_match. kind;
460- then{
461- for arg in tup_args_list {
462- vec_arg. push( arg) ;
463- }
464- }
465- }
501+ return Some ( AssertExpn {
502+ first_assert_argument: lhs,
503+ second_assert_argument: Some ( rhs) ,
504+ format_arg: Some ( format_arg_expn)
505+ } ) ;
506+ }
507+ else {
508+ return Some ( AssertExpn {
509+ first_assert_argument: lhs,
510+ second_assert_argument:
511+ Some ( rhs) ,
512+ format_arg: None
513+ } ) ;
466514 }
467515 }
468- return Some ( vec_arg) ;
469516 }
470517 }
471518 None
472519 }
473520
474- if let ExprKind :: Block ( block, _) = e. kind {
475- if block. stmts . len ( ) == 1 {
476- if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
477- // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
478- if_chain ! {
479- if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
480- if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
481- then {
482- return Some ( vec![ condition] ) ;
483- }
484- }
485-
486- // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
487- if_chain ! {
488- if let ExprKind :: Block ( matchblock, _) = matchexpr. kind;
489- if let Some ( matchblock_expr) = matchblock. expr;
490- then {
491- return ast_matchblock( matchblock_expr) ;
492- }
493- }
521+ /// Gives the argument as a vector
522+ pub fn argument_vector ( & self ) -> Vec < & ' tcx Expr < ' tcx > > {
523+ let mut expr_vec = vec ! [ self . first_assert_argument] ;
524+ if let Some ( sec_agr) = self . second_assert_argument {
525+ expr_vec. push ( sec_agr) ;
526+ }
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)
494531 }
495- } else if let Some ( matchblock_expr) = block. expr {
496- // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
497- return ast_matchblock ( matchblock_expr) ;
498532 }
533+ expr_vec
499534 }
500- None
501535}
502536
503537/// A parsed `format!` expansion
0 commit comments