about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/single_component_path_imports.rs150
-rw-r--r--tests/ui/single_component_path_imports.fixed7
-rw-r--r--tests/ui/single_component_path_imports.rs7
-rw-r--r--tests/ui/single_component_path_imports.stderr12
5 files changed, 96 insertions, 82 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 97557fefe3e..f013613119c 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -1232,7 +1232,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| box as_conversions::AsConversions);
     store.register_late_pass(|| box let_underscore::LetUnderscore);
     store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
-    store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports::default());
+    store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
     let max_fn_params_bools = conf.max_fn_params_bools;
     let max_struct_bools = conf.max_struct_bools;
     store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools));
diff --git a/clippy_lints/src/single_component_path_imports.rs b/clippy_lints/src/single_component_path_imports.rs
index 901f7642a12..adf0d7998f8 100644
--- a/clippy_lints/src/single_component_path_imports.rs
+++ b/clippy_lints/src/single_component_path_imports.rs
@@ -1,12 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::in_macro;
-use rustc_ast::{Crate, Item, ItemKind, ModKind, UseTreeKind};
+use rustc_ast::{ptr::P, Crate, Item, ItemKind, ModKind, UseTreeKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::edition::Edition;
-use rustc_span::symbol::kw;
-use rustc_span::{Span, Symbol};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{edition::Edition, symbol::kw, Span, Symbol};
 
 declare_clippy_lint! {
     /// **What it does:** Checking for imports with single component use path.
@@ -36,94 +34,96 @@ declare_clippy_lint! {
     "imports with single component path are redundant"
 }
 
-#[derive(Default)]
-pub struct SingleComponentPathImports {
-    /// keep track of imports reused with `self` keyword,
-    /// such as `self::crypto_hash` in the example below
-    ///
-    /// ```rust,ignore
-    /// use self::crypto_hash::{Algorithm, Hasher};
-    /// ```
-    imports_reused_with_self: Vec<Symbol>,
-    /// keep track of single use statements
-    /// such as `crypto_hash` in the example below
-    ///
-    /// ```rust,ignore
-    /// use crypto_hash;
-    /// ```
-    single_use_usages: Vec<(Symbol, Span)>,
-}
-
-impl_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]);
+declare_lint_pass!(SingleComponentPathImports => [SINGLE_COMPONENT_PATH_IMPORTS]);
 
 impl EarlyLintPass for SingleComponentPathImports {
     fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
         if cx.sess.opts.edition < Edition::Edition2018 {
             return;
         }
-        for item in &krate.items {
-            self.track_uses(&item);
-        }
-        for single_use in &self.single_use_usages {
-            if !self.imports_reused_with_self.contains(&single_use.0) {
-                span_lint_and_sugg(
-                    cx,
-                    SINGLE_COMPONENT_PATH_IMPORTS,
-                    single_use.1,
-                    "this import is redundant",
-                    "remove it entirely",
-                    String::new(),
-                    Applicability::MachineApplicable,
-                );
-            }
-        }
+        check_mod(cx, &krate.items);
     }
 }
 
-impl SingleComponentPathImports {
-    fn track_uses(&mut self, item: &Item) {
-        if in_macro(item.span) || item.vis.kind.is_pub() {
-            return;
+fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
+    // keep track of imports reused with `self` keyword,
+    // such as `self::crypto_hash` in the example below
+    // ```rust,ignore
+    // use self::crypto_hash::{Algorithm, Hasher};
+    // ```
+    let mut imports_reused_with_self = Vec::new();
+
+    // keep track of single use statements
+    // such as `crypto_hash` in the example below
+    // ```rust,ignore
+    // use crypto_hash;
+    // ```
+    let mut single_use_usages = Vec::new();
+
+    for item in items {
+        track_uses(cx, &item, &mut imports_reused_with_self, &mut single_use_usages);
+    }
+
+    for single_use in &single_use_usages {
+        if !imports_reused_with_self.contains(&single_use.0) {
+            span_lint_and_sugg(
+                cx,
+                SINGLE_COMPONENT_PATH_IMPORTS,
+                single_use.1,
+                "this import is redundant",
+                "remove it entirely",
+                String::new(),
+                Applicability::MachineApplicable,
+            );
         }
+    }
+}
+
+fn track_uses(
+    cx: &EarlyContext<'_>,
+    item: &Item,
+    imports_reused_with_self: &mut Vec<Symbol>,
+    single_use_usages: &mut Vec<(Symbol, Span)>,
+) {
+    if in_macro(item.span) || item.vis.kind.is_pub() {
+        return;
+    }
+
+    match &item.kind {
+        ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
+            check_mod(cx, &items);
+        },
+        ItemKind::Use(use_tree) => {
+            let segments = &use_tree.prefix.segments;
 
-        match &item.kind {
-            ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
-                for item in items.iter() {
-                    self.track_uses(&item);
+            // keep track of `use some_module;` usages
+            if segments.len() == 1 {
+                if let UseTreeKind::Simple(None, _, _) = use_tree.kind {
+                    let ident = &segments[0].ident;
+                    single_use_usages.push((ident.name, item.span));
                 }
-            },
-            ItemKind::Use(use_tree) => {
-                let segments = &use_tree.prefix.segments;
+                return;
+            }
 
-                // keep track of `use some_module;` usages
-                if segments.len() == 1 {
-                    if let UseTreeKind::Simple(None, _, _) = use_tree.kind {
-                        let ident = &segments[0].ident;
-                        self.single_use_usages.push((ident.name, item.span));
-                    }
+            // keep track of `use self::some_module` usages
+            if segments[0].ident.name == kw::SelfLower {
+                // simple case such as `use self::module::SomeStruct`
+                if segments.len() > 1 {
+                    imports_reused_with_self.push(segments[1].ident.name);
                     return;
                 }
 
-                // keep track of `use self::some_module` usages
-                if segments[0].ident.name == kw::SelfLower {
-                    // simple case such as `use self::module::SomeStruct`
-                    if segments.len() > 1 {
-                        self.imports_reused_with_self.push(segments[1].ident.name);
-                        return;
-                    }
-
-                    // nested case such as `use self::{module1::Struct1, module2::Struct2}`
-                    if let UseTreeKind::Nested(trees) = &use_tree.kind {
-                        for tree in trees {
-                            let segments = &tree.0.prefix.segments;
-                            if !segments.is_empty() {
-                                self.imports_reused_with_self.push(segments[0].ident.name);
-                            }
+                // nested case such as `use self::{module1::Struct1, module2::Struct2}`
+                if let UseTreeKind::Nested(trees) = &use_tree.kind {
+                    for tree in trees {
+                        let segments = &tree.0.prefix.segments;
+                        if !segments.is_empty() {
+                            imports_reused_with_self.push(segments[0].ident.name);
                         }
                     }
                 }
-            },
-            _ => {},
-        }
+            }
+        },
+        _ => {},
     }
 }
diff --git a/tests/ui/single_component_path_imports.fixed b/tests/ui/single_component_path_imports.fixed
index 226d2b315d7..f66b445b7b6 100644
--- a/tests/ui/single_component_path_imports.fixed
+++ b/tests/ui/single_component_path_imports.fixed
@@ -25,3 +25,10 @@ mod hello_mod {
     #[allow(dead_code)]
     fn hello_mod() {}
 }
+
+mod hi_mod {
+    use self::regex::{Regex, RegexSet};
+    use regex;
+    #[allow(dead_code)]
+    fn hi_mod() {}
+}
diff --git a/tests/ui/single_component_path_imports.rs b/tests/ui/single_component_path_imports.rs
index 88bf7f1fc5a..09d48658595 100644
--- a/tests/ui/single_component_path_imports.rs
+++ b/tests/ui/single_component_path_imports.rs
@@ -25,3 +25,10 @@ mod hello_mod {
     #[allow(dead_code)]
     fn hello_mod() {}
 }
+
+mod hi_mod {
+    use self::regex::{Regex, RegexSet};
+    use regex;
+    #[allow(dead_code)]
+    fn hi_mod() {}
+}
diff --git a/tests/ui/single_component_path_imports.stderr b/tests/ui/single_component_path_imports.stderr
index 646e6d3647a..7005fa8f125 100644
--- a/tests/ui/single_component_path_imports.stderr
+++ b/tests/ui/single_component_path_imports.stderr
@@ -1,16 +1,16 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:6:1
+  --> $DIR/single_component_path_imports.rs:24:5
    |
-LL | use regex;
-   | ^^^^^^^^^^ help: remove it entirely
+LL |     use regex;
+   |     ^^^^^^^^^^ help: remove it entirely
    |
    = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:24:5
+  --> $DIR/single_component_path_imports.rs:6:1
    |
-LL |     use regex;
-   |     ^^^^^^^^^^ help: remove it entirely
+LL | use regex;
+   | ^^^^^^^^^^ help: remove it entirely
 
 error: aborting due to 2 previous errors