@@ -3,8 +3,9 @@ use if_chain::if_chain;
3
3
use rustc_ast:: { Item , ItemKind , UseTreeKind } ;
4
4
use rustc_errors:: Applicability ;
5
5
use rustc_lint:: { EarlyContext , EarlyLintPass } ;
6
- use rustc_session:: { declare_lint_pass , declare_tool_lint } ;
6
+ use rustc_session:: { declare_tool_lint , impl_lint_pass } ;
7
7
use rustc_span:: edition:: Edition ;
8
+ use rustc_span:: symbol:: { kw, Symbol } ;
8
9
9
10
declare_clippy_lint ! {
10
11
/// **What it does:** Checking for imports with single component use path.
@@ -34,10 +35,50 @@ declare_clippy_lint! {
34
35
"imports with single component path are redundant"
35
36
}
36
37
37
- declare_lint_pass ! ( SingleComponentPathImports => [ SINGLE_COMPONENT_PATH_IMPORTS ] ) ;
38
+ #[ derive( Default ) ]
39
+ pub struct SingleComponentPathImports {
40
+ /// detect imports reused with `self` keyword,
41
+ /// such as `self::crypto_hash` in the example below
42
+ ///
43
+ /// ```rust,ignore
44
+ /// use self::crypto_hash::{Algorithm, Hasher};
45
+ /// use crypto_hash;
46
+ /// ```
47
+ imports_as_use_self : Vec < Symbol > ,
48
+ }
49
+
50
+ impl_lint_pass ! ( SingleComponentPathImports => [ SINGLE_COMPONENT_PATH_IMPORTS ] ) ;
38
51
39
52
impl EarlyLintPass for SingleComponentPathImports {
40
53
fn check_item ( & mut self , cx : & EarlyContext < ' _ > , item : & Item ) {
54
+ if_chain ! {
55
+ if !in_macro( item. span) ;
56
+ if cx. sess. opts. edition >= Edition :: Edition2018 ;
57
+ if let ItemKind :: Use ( use_tree) = & item. kind;
58
+ if let segments = & use_tree. prefix. segments;
59
+ if segments[ 0 ] . ident. name == kw:: SelfLower ;
60
+
61
+ then {
62
+ // simple case such as `use self::module::SomeStruct`
63
+ if segments. len( ) > 1 {
64
+ self . imports_as_use_self. push( segments[ 1 ] . ident. name) ;
65
+ return ;
66
+ }
67
+
68
+ // nested case such as `use self::{module1::Struct1, module2::Struct2}`
69
+ if let UseTreeKind :: Nested ( trees) = & use_tree. kind {
70
+ for tree in trees {
71
+ let segments = & tree. 0 . prefix. segments;
72
+ if !segments. is_empty( ) {
73
+ self . imports_as_use_self. push( segments[ 0 ] . ident. name) ;
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ fn check_item_post ( & mut self , cx : & EarlyContext < ' _ > , item : & Item ) {
41
82
if_chain ! {
42
83
if !in_macro( item. span) ;
43
84
if cx. sess. opts. edition >= Edition :: Edition2018 ;
@@ -46,6 +87,8 @@ impl EarlyLintPass for SingleComponentPathImports {
46
87
if let segments = & use_tree. prefix. segments;
47
88
if segments. len( ) == 1 ;
48
89
if let UseTreeKind :: Simple ( None , _, _) = use_tree. kind;
90
+ if !self . imports_as_use_self. contains( & segments[ 0 ] . ident. name) ;
91
+
49
92
then {
50
93
span_lint_and_sugg(
51
94
cx,
0 commit comments