1 use crate::utils::{is_expn_of, match_panic_call, span_lint};
2 use if_chain::if_chain;
4 use rustc_lint::{LateContext, LateLintPass};
5 use rustc_session::{declare_lint_pass, declare_tool_lint};
9 /// **What it does:** Checks for usage of `panic!`.
11 /// **Why is this bad?** `panic!` will stop the execution of the executable
13 /// **Known problems:** None.
17 /// panic!("even with a good reason");
21 "usage of the `panic!` macro"
24 declare_clippy_lint! {
25 /// **What it does:** Checks for usage of `unimplemented!`.
27 /// **Why is this bad?** This macro should not be present in production code
29 /// **Known problems:** None.
37 "`unimplemented!` should not be present in production code"
40 declare_clippy_lint! {
41 /// **What it does:** Checks for usage of `todo!`.
43 /// **Why is this bad?** This macro should not be present in production code
45 /// **Known problems:** None.
53 "`todo!` should not be present in production code"
56 declare_clippy_lint! {
57 /// **What it does:** Checks for usage of `unreachable!`.
59 /// **Why is this bad?** This macro can cause code to panic
61 /// **Known problems:** None.
69 "`unreachable!` should not be present in production code"
72 declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
74 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
75 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
76 if let Some(_) = match_panic_call(cx, expr) {
77 let span = get_outer_span(expr);
78 if is_expn_of(expr.span, "unimplemented").is_some() {
83 "`unimplemented` should not be present in production code",
85 } else if is_expn_of(expr.span, "todo").is_some() {
86 span_lint(cx, TODO, span, "`todo` should not be present in production code");
87 } else if is_expn_of(expr.span, "unreachable").is_some() {
92 "`unreachable` should not be present in production code",
94 } else if is_expn_of(expr.span, "panic").is_some() {
95 span_lint(cx, PANIC, span, "`panic` should not be present in production code");
101 fn get_outer_span(expr: &Expr<'_>) -> Span {
103 if expr.span.from_expansion();
104 let first = expr.span.ctxt().outer_expn_data();
105 if first.call_site.from_expansion();
106 let second = first.call_site.ctxt().outer_expn_data();