2
2
3
3
#![ deny( clippy:: missing_docs_in_private_items) ]
4
4
5
- use crate :: { is_expn_of, match_def_path, paths} ;
5
+ use crate :: { is_expn_of, match_def_path, paths, source :: snippet_with_applicability } ;
6
6
use if_chain:: if_chain;
7
7
use rustc_ast:: ast:: { self , LitKind } ;
8
+ use rustc_errors:: Applicability ;
8
9
use rustc_hir as hir;
9
10
use rustc_hir:: { Arm , Block , BorrowKind , Expr , ExprKind , LoopSource , MatchSource , Node , Pat , StmtKind , UnOp } ;
10
11
use rustc_lint:: LateContext ;
11
12
use rustc_span:: { sym, ExpnKind , Span , Symbol } ;
12
13
14
+ use std:: borrow:: Cow ;
15
+
13
16
/// The essential nodes of a desugared for loop as well as the entire span:
14
17
/// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, span)`.
15
18
pub struct ForLoop < ' tcx > {
@@ -417,8 +420,8 @@ pub fn binop(op: hir::BinOpKind) -> ast::BinOpKind {
417
420
}
418
421
419
422
/// 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!`
422
425
/// macro.
423
426
pub struct AssertExpn < ' tcx > {
424
427
/// the first agrument of the assret e.g. `var` in element `assert!(var, ...)`
@@ -446,14 +449,33 @@ impl<'tcx> AssertExpn<'tcx> {
446
449
if let StmtKind :: Semi ( matchexpr) = block. stmts . get ( 0 ) ?. kind {
447
450
// macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
448
451
if_chain ! {
449
- if let Some ( If { cond, .. } ) = If :: hir( matchexpr) ;
452
+ if let Some ( If { cond, then , .. } ) = If :: hir( matchexpr) ;
450
453
if let ExprKind :: Unary ( UnOp :: Not , condition) = cond. kind;
451
454
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
+ }
457
479
}
458
480
}
459
481
@@ -494,7 +516,7 @@ impl<'tcx> AssertExpn<'tcx> {
494
516
if let ExprKind :: Call ( _, args_assert_failed) = call_assert_failed. kind;
495
517
if args_assert_failed. len( ) >= 4 ;
496
518
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) ;
498
520
then {
499
521
return Some ( AssertExpn {
500
522
first_assert_argument: lhs,
@@ -516,19 +538,49 @@ impl<'tcx> AssertExpn<'tcx> {
516
538
None
517
539
}
518
540
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 > > {
521
543
let mut expr_vec = vec ! [ self . first_assert_argument] ;
522
544
if let Some ( sec_agr) = self . second_assert_argument {
523
545
expr_vec. push ( sec_agr) ;
524
546
}
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) ) ;
529
581
}
530
582
}
531
- expr_vec
583
+ vec_arg
532
584
}
533
585
}
534
586
@@ -566,8 +618,6 @@ impl FormatExpn<'tcx> {
566
618
567
619
/// A parsed `format_args!` expansion
568
620
pub struct FormatArgsExpn < ' tcx > {
569
- /// The fist argument, the fromat string, as an expr
570
- pub format_string : & ' tcx Expr < ' tcx > ,
571
621
/// Span of the first argument, the format string
572
622
pub format_string_span : Span ,
573
623
/// Values passed after the format string
@@ -629,7 +679,6 @@ impl FormatArgsExpn<'tcx> {
629
679
. collect( ) ;
630
680
then {
631
681
Some ( FormatArgsExpn {
632
- format_string: strs_ref,
633
682
format_string_span: strs_ref. span,
634
683
value_args,
635
684
format_string_parts,
0 commit comments