|
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> { |
@@ -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.len() >= 1; |
| 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 |
|
@@ -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