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