use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::source::snippet_opt; use rustc_ast::ast; use rustc_ast::tokenstream::TokenStream; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; declare_clippy_lint! { /// **What it does:** Checks for usage of dbg!() macro. /// /// **Why is this bad?** `dbg!` macro is intended as a debugging tool. It /// should not be in version control. /// /// **Known problems:** None. /// /// **Example:** /// ```rust,ignore /// // Bad /// dbg!(true) /// /// // Good /// true /// ``` pub DBG_MACRO, restriction, "`dbg!` macro is intended as a debugging tool" } declare_lint_pass!(DbgMacro => [DBG_MACRO]); impl EarlyLintPass for DbgMacro { fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) { if mac.path == sym!(dbg) { if let Some(sugg) = tts_span(mac.args.inner_tokens()).and_then(|span| snippet_opt(cx, span)) { span_lint_and_sugg( cx, DBG_MACRO, mac.span(), "`dbg!` macro is intended as a debugging tool", "ensure to avoid having uses of it in version control", sugg, Applicability::MaybeIncorrect, ); } else { span_lint_and_help( cx, DBG_MACRO, mac.span(), "`dbg!` macro is intended as a debugging tool", None, "ensure to avoid having uses of it in version control", ); } } } } // Get span enclosing entire the token stream. fn tts_span(tts: TokenStream) -> Option { let mut cursor = tts.into_trees(); let first = cursor.next()?.span(); let span = cursor.last().map_or(first, |tree| first.to(tree.span())); Some(span) }