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