1 use clippy_utils::diagnostics::span_lint;
2 use clippy_utils::{is_expn_of, match_panic_call};
3 use if_chain::if_chain;
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
11 /// Checks for usage of `panic!`.
13 /// ### Why is this bad?
14 /// `panic!` will stop the execution of the executable
18 /// panic!("even with a good reason");
22 "usage of the `panic!` macro"
25 declare_clippy_lint! {
27 /// Checks for usage of `unimplemented!`.
29 /// ### Why is this bad?
30 /// This macro should not be present in production code
38 "`unimplemented!` should not be present in production code"
41 declare_clippy_lint! {
43 /// Checks for usage of `todo!`.
45 /// ### Why is this bad?
46 /// This macro should not be present in production code
54 "`todo!` should not be present in production code"
57 declare_clippy_lint! {
59 /// Checks for usage of `unreachable!`.
61 /// ### Why is this bad?
62 /// This macro can cause code to panic
70 "usage of the `unreachable!` macro"
73 declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
75 impl<'tcx> LateLintPass<'tcx> for PanicUnimplemented {
76 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
77 if match_panic_call(cx, expr).is_some()
78 && (is_expn_of(expr.span, "debug_assert").is_none() && is_expn_of(expr.span, "assert").is_none())
80 let span = get_outer_span(expr);
81 if is_expn_of(expr.span, "unimplemented").is_some() {
86 "`unimplemented` should not be present in production code",
88 } else if is_expn_of(expr.span, "todo").is_some() {
89 span_lint(cx, TODO, span, "`todo` should not be present in production code");
90 } else if is_expn_of(expr.span, "unreachable").is_some() {
91 span_lint(cx, UNREACHABLE, span, "usage of the `unreachable!` macro");
92 } else if is_expn_of(expr.span, "panic").is_some() {
93 span_lint(cx, PANIC, span, "`panic` should not be present in production code");
99 fn get_outer_span(expr: &Expr<'_>) -> Span {
101 if expr.span.from_expansion();
102 let first = expr.span.ctxt().outer_expn_data().call_site;
103 if first.from_expansion();
105 first.ctxt().outer_expn_data().call_site