From dc23e42fb696b1106d44371170a5fb61c1d725c6 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Thu, 2 Feb 2023 15:11:31 +0000 Subject: [PATCH] Add `format_args_collector` internal lint --- clippy_lints/src/lib.rs | 2 +- .../src/utils/format_args_collector.rs | 23 +++++++++++++++++++ clippy_lints/src/utils/mod.rs | 1 + clippy_lints/src/write.rs | 12 ++-------- clippy_utils/src/macros.rs | 16 ++++++------- 5 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 clippy_lints/src/utils/format_args_collector.rs diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a025e3cc12a..f6d14b31fef 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -533,6 +533,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: .collect(), )) }); + store.register_early_pass(|| Box::new(utils::format_args_collector::FormatArgsCollector)); store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir)); store.register_late_pass(|_| Box::new(utils::author::Author)); let await_holding_invalid_types = conf.await_holding_invalid_types.clone(); @@ -870,7 +871,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let allow_dbg_in_tests = conf.allow_dbg_in_tests; store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests))); let allow_print_in_tests = conf.allow_print_in_tests; - store.register_early_pass(move || Box::new(write::Write::new(allow_print_in_tests))); store.register_late_pass(move |_| Box::new(write::Write::new(allow_print_in_tests))); let cargo_ignore_publish = conf.cargo_ignore_publish; store.register_late_pass(move |_| { diff --git a/clippy_lints/src/utils/format_args_collector.rs b/clippy_lints/src/utils/format_args_collector.rs new file mode 100644 index 00000000000..be56b842b98 --- /dev/null +++ b/clippy_lints/src/utils/format_args_collector.rs @@ -0,0 +1,23 @@ +use clippy_utils::macros::collect_ast_format_args; +use rustc_ast::{Expr, ExprKind}; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Collects [`rustc_ast::FormatArgs`] so that future late passes can call + /// [`clippy_utils::macros::find_format_args`] + pub FORMAT_ARGS_COLLECTOR, + internal_warn, + "collects `format_args` AST nodes for use in later lints" +} + +declare_lint_pass!(FormatArgsCollector => [FORMAT_ARGS_COLLECTOR]); + +impl EarlyLintPass for FormatArgsCollector { + fn check_expr(&mut self, _: &EarlyContext<'_>, expr: &Expr) { + if let ExprKind::FormatArgs(args) = &expr.kind { + collect_ast_format_args(expr.span, args); + } + } +} diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 787e9fd982c..dc647af264c 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,5 +1,6 @@ pub mod author; pub mod conf; pub mod dump_hir; +pub mod format_args_collector; #[cfg(feature = "internal")] pub mod internal_lints; diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index ce419ec9373..8114a8463fa 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -1,14 +1,12 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; -use clippy_utils::macros::{ - find_format_args, format_arg_removal_span, populate_ast_format_args, root_macro_call_first_node, MacroCall, -}; +use clippy_utils::macros::{find_format_args, format_arg_removal_span, root_macro_call_first_node, MacroCall}; use clippy_utils::source::{expand_past_previous_comma, snippet_opt}; use clippy_utils::{is_in_cfg_test, is_in_test_function}; use rustc_ast::token::LitKind; use rustc_ast::{FormatArgPosition, FormatArgs, FormatArgsPiece, FormatOptions, FormatPlaceholder, FormatTrait}; use rustc_errors::Applicability; use rustc_hir::{Expr, Impl, Item, ItemKind}; -use rustc_lint::{EarlyLintPass, LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{sym, BytePos}; @@ -260,12 +258,6 @@ pub fn new(allow_print_in_tests: bool) -> Self { WRITE_LITERAL, ]); -impl EarlyLintPass for Write { - fn check_expr(&mut self, _: &rustc_lint::EarlyContext<'_>, expr: &rustc_ast::Expr) { - populate_ast_format_args(expr); - } -} - impl<'tcx> LateLintPass<'tcx> for Write { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if is_debug_impl(cx, item) { diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index 8e0edd72f92..ab1c26fb9ad 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -19,7 +19,7 @@ use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Pos, Span, SpanData, Symbol}; use std::cell::RefCell; use std::iter::{once, zip}; -use std::ops::{ControlFlow, Deref}; +use std::ops::ControlFlow; use std::sync::atomic::{AtomicBool, Ordering}; const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[ @@ -361,14 +361,12 @@ fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) -> }; } -/// Record [`rustc_ast::FormatArgs`] for use in late lint passes, this only needs to be called by -/// one lint pass. -pub fn populate_ast_format_args(expr: &rustc_ast::Expr) { - if let rustc_ast::ExprKind::FormatArgs(args) = &expr.kind { - AST_FORMAT_ARGS.with(|ast_format_args| { - ast_format_args.borrow_mut().insert(expr.span, args.deref().clone()); - }); - } +/// Record [`rustc_ast::FormatArgs`] for use in late lint passes, this should only be called by +/// `FormatArgsCollector` +pub fn collect_ast_format_args(span: Span, format_args: &FormatArgs) { + AST_FORMAT_ARGS.with(|ast_format_args| { + ast_format_args.borrow_mut().insert(span, format_args.clone()); + }); } /// Calls `callback` with an AST [`FormatArgs`] node if one is found