]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/dbg_macro.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / clippy / clippy_lints / src / dbg_macro.rs
CommitLineData
5e7ed085 1use clippy_utils::diagnostics::span_lint_and_sugg;
31ef2f64 2use clippy_utils::is_in_test;
e8be2606 3use clippy_utils::macros::{macro_backtrace, MacroCall};
5e7ed085 4use clippy_utils::source::snippet_with_applicability;
e8be2606 5use rustc_data_structures::fx::FxHashSet;
f20569fa 6use rustc_errors::Applicability;
31ef2f64 7use rustc_hir::{Expr, ExprKind, Node};
49aad941 8use rustc_lint::{LateContext, LateLintPass, LintContext};
e8be2606 9use rustc_middle::lint::in_external_macro;
4b012472 10use rustc_session::impl_lint_pass;
e8be2606 11use rustc_span::{sym, Span, SyntaxContext};
f20569fa
XL
12
13declare_clippy_lint! {
94222f64 14 /// ### What it does
9c376795 15 /// Checks for usage of the [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro.
f20569fa 16 ///
31ef2f64 17 /// ### Why restrict this?
9c376795
FG
18 /// The `dbg!` macro is intended as a debugging tool. It should not be present in released
19 /// software or committed to a version control system.
f20569fa 20 ///
94222f64 21 /// ### Example
f20569fa 22 /// ```rust,ignore
f20569fa 23 /// dbg!(true)
923072b8 24 /// ```
f20569fa 25 ///
923072b8
FG
26 /// Use instead:
27 /// ```rust,ignore
f20569fa
XL
28 /// true
29 /// ```
a2a8927a 30 #[clippy::version = "1.34.0"]
f20569fa
XL
31 pub DBG_MACRO,
32 restriction,
33 "`dbg!` macro is intended as a debugging tool"
34}
35
e8be2606 36#[derive(Clone)]
923072b8
FG
37pub struct DbgMacro {
38 allow_dbg_in_tests: bool,
e8be2606
FG
39 /// Tracks the `dbg!` macro callsites that are already checked.
40 checked_dbg_call_site: FxHashSet<Span>,
41 /// Tracks the previous `SyntaxContext`, to avoid walking the same context chain.
42 prev_ctxt: SyntaxContext,
923072b8
FG
43}
44
45impl_lint_pass!(DbgMacro => [DBG_MACRO]);
46
47impl DbgMacro {
48 pub fn new(allow_dbg_in_tests: bool) -> Self {
e8be2606
FG
49 DbgMacro {
50 allow_dbg_in_tests,
51 checked_dbg_call_site: FxHashSet::default(),
52 prev_ctxt: SyntaxContext::root(),
53 }
923072b8
FG
54 }
55}
f20569fa 56
5e7ed085
FG
57impl LateLintPass<'_> for DbgMacro {
58 fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
e8be2606
FG
59 let cur_syntax_ctxt = expr.span.ctxt();
60
61 if cur_syntax_ctxt != self.prev_ctxt &&
62 let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) &&
63 !in_external_macro(cx.sess(), macro_call.span) &&
64 self.checked_dbg_call_site.insert(macro_call.span) &&
923072b8 65 // allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
31ef2f64 66 !(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
e8be2606 67 {
5e7ed085 68 let mut applicability = Applicability::MachineApplicable;
49aad941
FG
69
70 let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
5e7ed085 71 // dbg!()
49aad941
FG
72 ExprKind::Block(..) => {
73 // If the `dbg!` macro is a "free" statement and not contained within other expressions,
74 // remove the whole statement.
c620b35d 75 if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
4b012472 76 && let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
49aad941 77 {
4b012472 78 (macro_call.span.to(semi_span), String::new())
49aad941
FG
79 } else {
80 (macro_call.span, String::from("()"))
81 }
5e7ed085 82 },
49aad941
FG
83 // dbg!(1)
84 ExprKind::Match(val, ..) => (
85 macro_call.span,
86 snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
87 ),
5e7ed085
FG
88 // dbg!(2, 3)
89 ExprKind::Tup(
90 [
91 Expr {
92 kind: ExprKind::Match(first, ..),
93 ..
94 },
95 ..,
96 Expr {
97 kind: ExprKind::Match(last, ..),
98 ..
99 },
100 ],
101 ) => {
102 let snippet = snippet_with_applicability(
103 cx,
104 first.span.source_callsite().to(last.span.source_callsite()),
105 "..",
106 &mut applicability,
107 );
49aad941 108 (macro_call.span, format!("({snippet})"))
5e7ed085
FG
109 },
110 _ => return,
111 };
112
e8be2606
FG
113 self.prev_ctxt = cur_syntax_ctxt;
114
5e7ed085
FG
115 span_lint_and_sugg(
116 cx,
117 DBG_MACRO,
49aad941 118 sugg_span,
9c376795
FG
119 "the `dbg!` macro is intended as a debugging tool",
120 "remove the invocation before committing it to a version control system",
5e7ed085
FG
121 suggestion,
122 applicability,
123 );
f20569fa
XL
124 }
125 }
e8be2606
FG
126
127 fn check_crate_post(&mut self, _: &LateContext<'_>) {
128 self.checked_dbg_call_site = FxHashSet::default();
129 }
130}
131
e8be2606
FG
132fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
133 macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
f20569fa 134}