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