]>
Commit | Line | Data |
---|---|---|
5e7ed085 | 1 | use clippy_utils::diagnostics::span_lint_and_sugg; |
5e7ed085 FG |
2 | use clippy_utils::macros::root_macro_call_first_node; |
3 | use clippy_utils::source::snippet_with_applicability; | |
923072b8 | 4 | use clippy_utils::{is_in_cfg_test, is_in_test_function}; |
f20569fa | 5 | use rustc_errors::Applicability; |
5e7ed085 FG |
6 | use rustc_hir::{Expr, ExprKind}; |
7 | use rustc_lint::{LateContext, LateLintPass}; | |
923072b8 | 8 | use rustc_session::{declare_tool_lint, impl_lint_pass}; |
5e7ed085 | 9 | use rustc_span::sym; |
f20569fa XL |
10 | |
11 | declare_clippy_lint! { | |
94222f64 XL |
12 | /// ### What it does |
13 | /// Checks for usage of dbg!() macro. | |
f20569fa | 14 | /// |
94222f64 XL |
15 | /// ### Why is this bad? |
16 | /// `dbg!` macro is intended as a debugging tool. It | |
f20569fa XL |
17 | /// should not be in version control. |
18 | /// | |
94222f64 | 19 | /// ### Example |
f20569fa | 20 | /// ```rust,ignore |
f20569fa | 21 | /// dbg!(true) |
923072b8 | 22 | /// ``` |
f20569fa | 23 | /// |
923072b8 FG |
24 | /// Use instead: |
25 | /// ```rust,ignore | |
f20569fa XL |
26 | /// true |
27 | /// ``` | |
a2a8927a | 28 | #[clippy::version = "1.34.0"] |
f20569fa XL |
29 | pub DBG_MACRO, |
30 | restriction, | |
31 | "`dbg!` macro is intended as a debugging tool" | |
32 | } | |
33 | ||
923072b8 FG |
34 | #[derive(Copy, Clone)] |
35 | pub struct DbgMacro { | |
36 | allow_dbg_in_tests: bool, | |
37 | } | |
38 | ||
39 | impl_lint_pass!(DbgMacro => [DBG_MACRO]); | |
40 | ||
41 | impl DbgMacro { | |
42 | pub fn new(allow_dbg_in_tests: bool) -> Self { | |
43 | DbgMacro { allow_dbg_in_tests } | |
44 | } | |
45 | } | |
f20569fa | 46 | |
5e7ed085 FG |
47 | impl LateLintPass<'_> for DbgMacro { |
48 | fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { | |
49 | let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return }; | |
50 | if cx.tcx.is_diagnostic_item(sym::dbg_macro, macro_call.def_id) { | |
923072b8 FG |
51 | // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml |
52 | if self.allow_dbg_in_tests | |
53 | && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) | |
54 | { | |
5e7ed085 | 55 | return; |
f20569fa | 56 | } |
5e7ed085 FG |
57 | let mut applicability = Applicability::MachineApplicable; |
58 | let suggestion = match expr.peel_drop_temps().kind { | |
59 | // dbg!() | |
60 | ExprKind::Block(_, _) => String::new(), | |
61 | // dbg!(1) | |
62 | ExprKind::Match(val, ..) => { | |
63 | snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string() | |
64 | }, | |
65 | // dbg!(2, 3) | |
66 | ExprKind::Tup( | |
67 | [ | |
68 | Expr { | |
69 | kind: ExprKind::Match(first, ..), | |
70 | .. | |
71 | }, | |
72 | .., | |
73 | Expr { | |
74 | kind: ExprKind::Match(last, ..), | |
75 | .. | |
76 | }, | |
77 | ], | |
78 | ) => { | |
79 | let snippet = snippet_with_applicability( | |
80 | cx, | |
81 | first.span.source_callsite().to(last.span.source_callsite()), | |
82 | "..", | |
83 | &mut applicability, | |
84 | ); | |
85 | format!("({snippet})") | |
86 | }, | |
87 | _ => return, | |
88 | }; | |
89 | ||
90 | span_lint_and_sugg( | |
91 | cx, | |
92 | DBG_MACRO, | |
93 | macro_call.span, | |
94 | "`dbg!` macro is intended as a debugging tool", | |
95 | "ensure to avoid having uses of it in version control", | |
96 | suggestion, | |
97 | applicability, | |
98 | ); | |
f20569fa XL |
99 | } |
100 | } | |
101 | } |