diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index b26ef33e0569..8eb94f3c28e4 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -1,6 +1,6 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::{diagnostics::span_lint, is_test_module_or_function}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{Pat, PatKind}; +use rustc_hir::{Item, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -25,18 +25,37 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct BlacklistedName { blacklist: FxHashSet, + test_modules_deep: u32, } impl BlacklistedName { pub fn new(blacklist: FxHashSet) -> Self { - Self { blacklist } + Self { + blacklist, + test_modules_deep: 0, + } + } + + fn in_test_module(&self) -> bool { + self.test_modules_deep != 0 } } impl_lint_pass!(BlacklistedName => [BLACKLISTED_NAME]); impl<'tcx> LateLintPass<'tcx> for BlacklistedName { + fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { + self.test_modules_deep = self.test_modules_deep.saturating_add(1); + } + } + fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { + // Check whether we are under the `test` attribute. + if self.in_test_module() { + return; + } + if let PatKind::Binding(.., ident, _) = pat.kind { if self.blacklist.contains(&ident.name.to_string()) { span_lint( @@ -48,4 +67,10 @@ impl<'tcx> LateLintPass<'tcx> for BlacklistedName { } } } + + fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { + self.test_modules_deep = self.test_modules_deep.saturating_sub(1); + } + } } diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 51c1117d2064..520586b3a1f4 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::in_macro; use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::{in_macro, is_test_module_or_function}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ @@ -106,7 +106,7 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if is_test_module_or_function(item) { + if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { @@ -183,8 +183,8 @@ impl LateLintPass<'_> for WildcardImports { } } - fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) { - if is_test_module_or_function(item) { + fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { + if is_test_module_or_function(cx.tcx, item) { self.test_modules_deep = self.test_modules_deep.saturating_sub(1); } } @@ -208,7 +208,3 @@ fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.name == kw::Super } - -fn is_test_module_or_function(item: &Item<'_>) -> bool { - matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") -} diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 66e75b0c2063..ef4854afc83c 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1727,3 +1727,15 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { } } } + +/// Checks whether item either has `test` attribute applied, or +/// is a module with `test` in its name. +pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { + if let Some(def_id) = tcx.hir().opt_local_def_id(item.hir_id()) { + if tcx.has_attr(def_id.to_def_id(), sym::test) { + return true; + } + } + + matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") +} diff --git a/tests/ui/blacklisted_name.rs b/tests/ui/blacklisted_name.rs index cb15bdd2f1b2..57d7139fef56 100644 --- a/tests/ui/blacklisted_name.rs +++ b/tests/ui/blacklisted_name.rs @@ -43,3 +43,15 @@ fn issue_1647_ref_mut() { let ref mut baz = 0; if let Some(ref mut quux) = Some(42) {} } + +mod tests { + fn issue_7305() { + // `blackisted_name` lint should not be triggered inside of the test code. + let foo = 0; + + // Check that even in nested functions warning is still not triggere. + fn nested() { + let foo = 0; + } + } +}