]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/panic_unimplemented.rs
Merge commit '4911ab124c481430672a3833b37075e6435ec34d' 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     "usage of the `unreachable!` macro"
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(cx, UNREACHABLE, span, "usage of the `unreachable!` macro");
89             } else if is_expn_of(expr.span, "panic").is_some() {
90                 span_lint(cx, PANIC, span, "`panic` should not be present in production code");
91             }
92         }
93     }
94 }
95
96 fn get_outer_span(expr: &Expr<'_>) -> Span {
97     if_chain! {
98         if expr.span.from_expansion();
99         let first = expr.span.ctxt().outer_expn_data();
100         if first.call_site.from_expansion();
101         let second = first.call_site.ctxt().outer_expn_data();
102         then {
103             second.call_site
104         } else {
105             expr.span
106         }
107     }
108 }