]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/panic_unimplemented.rs
dc28874c16e67febf474f13cda31f1dcb38e5711
[rust.git] / clippy_lints / src / panic_unimplemented.rs
1 use clippy_utils::diagnostics::span_lint;
2 use clippy_utils::{is_expn_of, match_panic_call};
3 use if_chain::if_chain;
4 use rustc_hir::Expr;
5 use rustc_lint::{LateContext, LateLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7 use rustc_span::Span;
8
9 declare_clippy_lint! {
10     /// **What it does:** Checks for usage of `panic!`.
11     ///
12     /// **Why is this bad?** `panic!` will stop the execution of the executable
13     ///
14     /// **Known problems:** None.
15     ///
16     /// **Example:**
17     /// ```no_run
18     /// panic!("even with a good reason");
19     /// ```
20     pub PANIC,
21     restriction,
22     "usage of the `panic!` macro"
23 }
24
25 declare_clippy_lint! {
26     /// **What it does:** Checks for usage of `unimplemented!`.
27     ///
28     /// **Why is this bad?** This macro should not be present in production code
29     ///
30     /// **Known problems:** None.
31     ///
32     /// **Example:**
33     /// ```no_run
34     /// unimplemented!();
35     /// ```
36     pub UNIMPLEMENTED,
37     restriction,
38     "`unimplemented!` should not be present in production code"
39 }
40
41 declare_clippy_lint! {
42     /// **What it does:** Checks for usage of `todo!`.
43     ///
44     /// **Why is this bad?** This macro should not be present in production code
45     ///
46     /// **Known problems:** None.
47     ///
48     /// **Example:**
49     /// ```no_run
50     /// todo!();
51     /// ```
52     pub TODO,
53     restriction,
54     "`todo!` should not be present in production code"
55 }
56
57 declare_clippy_lint! {
58     /// **What it does:** Checks for usage of `unreachable!`.
59     ///
60     /// **Why is this bad?** This macro can cause code to panic
61     ///
62     /// **Known problems:** None.
63     ///
64     /// **Example:**
65     /// ```no_run
66     /// unreachable!();
67     /// ```
68     pub UNREACHABLE,
69     restriction,
70     "usage of the `unreachable!` macro"
71 }
72
73 declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
74
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())
79         {
80             let span = get_outer_span(expr);
81             if is_expn_of(expr.span, "unimplemented").is_some() {
82                 span_lint(
83                     cx,
84                     UNIMPLEMENTED,
85                     span,
86                     "`unimplemented` should not be present in production code",
87                 );
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");
94             }
95         }
96     }
97 }
98
99 fn get_outer_span(expr: &Expr<'_>) -> Span {
100     if_chain! {
101         if expr.span.from_expansion();
102         let first = expr.span.ctxt().outer_expn_data().call_site;
103         if first.from_expansion();
104         then {
105             first.ctxt().outer_expn_data().call_site
106         } else {
107             expr.span
108         }
109     }
110 }