|
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