|
1 | 1 | use crate::rustc_lint::LintContext; |
2 | 2 | use clippy_utils::diagnostics::span_lint_and_then; |
3 | | -use clippy_utils::macros::{root_macro_call, FormatArgsExpn}; |
4 | | -use clippy_utils::source::snippet_with_applicability; |
| 3 | +use clippy_utils::macros::root_macro_call; |
5 | 4 | use clippy_utils::{is_else_clause, peel_blocks_with_stmt, span_extract_comment, sugg}; |
6 | 5 | use rustc_errors::Applicability; |
7 | 6 | use rustc_hir::{Expr, ExprKind, UnOp}; |
@@ -38,57 +37,57 @@ declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]); |
38 | 37 |
|
39 | 38 | impl<'tcx> LateLintPass<'tcx> for ManualAssert { |
40 | 39 | fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { |
41 | | - if_chain! { |
42 | | - if let ExprKind::If(cond, then, None) = expr.kind; |
43 | | - if !matches!(cond.kind, ExprKind::Let(_)); |
44 | | - if !expr.span.from_expansion(); |
45 | | - let then = peel_blocks_with_stmt(then); |
46 | | - if let Some(macro_call) = root_macro_call(then.span); |
47 | | - if cx.tcx.item_name(macro_call.def_id) == sym::panic; |
48 | | - if !cx.tcx.sess.source_map().is_multiline(cond.span); |
49 | | - if let Some(format_args) = FormatArgsExpn::find_nested(cx, then, macro_call.expn); |
| 40 | + if let ExprKind::If(cond, then, None) = expr.kind |
| 41 | + && !matches!(cond.kind, ExprKind::Let(_)) |
| 42 | + && !expr.span.from_expansion() |
| 43 | + && let then = peel_blocks_with_stmt(then) |
| 44 | + && let Some(macro_call) = root_macro_call(then.span) |
| 45 | + && cx.tcx.item_name(macro_call.def_id) == sym::panic |
| 46 | + && !cx.tcx.sess.source_map().is_multiline(cond.span) |
| 47 | + && let Ok(panic_snippet) = cx.sess().source_map().span_to_snippet(macro_call.span) |
| 48 | + && let Some(panic_snippet) = panic_snippet.strip_suffix(')') |
| 49 | + && let Some((_, format_args_snip)) = panic_snippet.split_once('(') |
50 | 50 | // Don't change `else if foo { panic!(..) }` to `else { assert!(foo, ..) }` as it just |
51 | 51 | // shuffles the condition around. |
52 | 52 | // Should this have a config value? |
53 | | - if !is_else_clause(cx.tcx, expr); |
54 | | - then { |
55 | | - let mut applicability = Applicability::MachineApplicable; |
56 | | - let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability); |
57 | | - let cond = cond.peel_drop_temps(); |
58 | | - let mut comments = span_extract_comment(cx.sess().source_map(), expr.span); |
59 | | - if !comments.is_empty() { |
60 | | - comments += "\n"; |
61 | | - } |
62 | | - let (cond, not) = match cond.kind { |
63 | | - ExprKind::Unary(UnOp::Not, e) => (e, ""), |
64 | | - _ => (cond, "!"), |
65 | | - }; |
66 | | - let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par(); |
67 | | - let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});"); |
68 | | - // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block |
69 | | - span_lint_and_then( |
70 | | - cx, |
71 | | - MANUAL_ASSERT, |
72 | | - expr.span, |
73 | | - "only a `panic!` in `if`-then statement", |
74 | | - |diag| { |
75 | | - // comments can be noisy, do not show them to the user |
76 | | - if !comments.is_empty() { |
77 | | - diag.tool_only_span_suggestion( |
78 | | - expr.span.shrink_to_lo(), |
79 | | - "add comments back", |
80 | | - comments, |
81 | | - applicability); |
82 | | - } |
83 | | - diag.span_suggestion( |
84 | | - expr.span, |
85 | | - "try instead", |
86 | | - sugg, |
87 | | - applicability); |
88 | | - } |
89 | | - |
90 | | - ); |
| 53 | + && !is_else_clause(cx.tcx, expr) |
| 54 | + { |
| 55 | + let mut applicability = Applicability::MachineApplicable; |
| 56 | + let cond = cond.peel_drop_temps(); |
| 57 | + let mut comments = span_extract_comment(cx.sess().source_map(), expr.span); |
| 58 | + if !comments.is_empty() { |
| 59 | + comments += "\n"; |
91 | 60 | } |
| 61 | + let (cond, not) = match cond.kind { |
| 62 | + ExprKind::Unary(UnOp::Not, e) => (e, ""), |
| 63 | + _ => (cond, "!"), |
| 64 | + }; |
| 65 | + let cond_sugg = sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par(); |
| 66 | + let sugg = format!("assert!({not}{cond_sugg}, {format_args_snip});"); |
| 67 | + // we show to the user the suggestion without the comments, but when applicating the fix, include the comments in the block |
| 68 | + span_lint_and_then( |
| 69 | + cx, |
| 70 | + MANUAL_ASSERT, |
| 71 | + expr.span, |
| 72 | + "only a `panic!` in `if`-then statement", |
| 73 | + |diag| { |
| 74 | + // comments can be noisy, do not show them to the user |
| 75 | + if !comments.is_empty() { |
| 76 | + diag.tool_only_span_suggestion( |
| 77 | + expr.span.shrink_to_lo(), |
| 78 | + "add comments back", |
| 79 | + comments, |
| 80 | + applicability |
| 81 | + ); |
| 82 | + } |
| 83 | + diag.span_suggestion( |
| 84 | + expr.span, |
| 85 | + "try instead", |
| 86 | + sugg, |
| 87 | + applicability |
| 88 | + ); |
| 89 | + } |
| 90 | + ); |
92 | 91 | } |
93 | 92 | } |
94 | 93 | } |
0 commit comments