1 use clippy_utils::{diagnostics::span_lint, is_test_module_or_function}; 2 use rustc_data_structures::fx::FxHashSet; 3 use rustc_hir::{Item, Pat, PatKind}; 4 use rustc_lint::{LateContext, LateLintPass}; 5 use rustc_session::{declare_tool_lint, impl_lint_pass}; 6 7 declare_clippy_lint! { 8 /// ### What it does 9 /// Checks for usage of disallowed names for variables, such 10 /// as `foo`. 11 /// 12 /// ### Why is this bad? 13 /// These names are usually placeholder names and should be 14 /// avoided. 15 /// 16 /// ### Example 17 /// ```rust 18 /// let foo = 3.14; 19 /// ``` 20 #[clippy::version = "pre 1.29.0"] 21 pub DISALLOWED_NAMES, 22 style, 23 "usage of a disallowed/placeholder name" 24 } 25 26 #[derive(Clone, Debug)] 27 pub struct DisallowedNames { 28 disallow: FxHashSet<String>, 29 test_modules_deep: u32, 30 } 31 32 impl DisallowedNames { new(disallow: FxHashSet<String>) -> Self33 pub fn new(disallow: FxHashSet<String>) -> Self { 34 Self { 35 disallow, 36 test_modules_deep: 0, 37 } 38 } 39 in_test_module(&self) -> bool40 fn in_test_module(&self) -> bool { 41 self.test_modules_deep != 0 42 } 43 } 44 45 impl_lint_pass!(DisallowedNames => [DISALLOWED_NAMES]); 46 47 impl<'tcx> LateLintPass<'tcx> for DisallowedNames { check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>)48 fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { 49 if is_test_module_or_function(cx.tcx, item) { 50 self.test_modules_deep = self.test_modules_deep.saturating_add(1); 51 } 52 } 53 check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>)54 fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) { 55 // Check whether we are under the `test` attribute. 56 if self.in_test_module() { 57 return; 58 } 59 60 if let PatKind::Binding(.., ident, _) = pat.kind { 61 if self.disallow.contains(&ident.name.to_string()) { 62 span_lint( 63 cx, 64 DISALLOWED_NAMES, 65 ident.span, 66 &format!("use of a disallowed/placeholder name `{}`", ident.name), 67 ); 68 } 69 } 70 } 71 check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>)72 fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { 73 if is_test_module_or_function(cx.tcx, item) { 74 self.test_modules_deep = self.test_modules_deep.saturating_sub(1); 75 } 76 } 77 } 78