@@ -4,10 +4,10 @@ use def_id::LOCAL_CRATE;
4
4
use rustc_data_structures:: fx:: FxHashSet ;
5
5
use rustc_errors:: Applicability ;
6
6
use rustc_hir:: def:: Res ;
7
- use rustc_hir:: { Item , ItemKind , def_id} ;
7
+ use rustc_hir:: { Attribute , Item , ItemKind , UsePath , def_id} ;
8
8
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
9
9
use rustc_session:: impl_lint_pass;
10
- use rustc_span:: { BytePos , FileName , RealFileName , Symbol } ;
10
+ use rustc_span:: { BytePos , FileName , RealFileName , Span , Symbol } ;
11
11
12
12
declare_clippy_lint ! {
13
13
/// ### What it does
@@ -54,93 +54,119 @@ declare_clippy_lint! {
54
54
#[ derive( Clone , Default ) ]
55
55
pub struct UseCratePrefixForSelfImports < ' a , ' tcx > {
56
56
/// code block of `use <foo>` or `mod <foo>`
57
- use_block : Vec < & ' a Item < ' tcx > > ,
57
+ use_block : Vec < & ' a UsePath < ' tcx > > ,
58
+ mod_names : FxHashSet < Symbol > ,
59
+ /// spans of `mod`, `use`, and attributes
60
+ spans : Vec < Span > ,
58
61
}
59
62
60
63
impl_lint_pass ! ( UseCratePrefixForSelfImports <' _, ' _> => [ USE_CRATE_PREFIX_FOR_SELF_IMPORTS ] ) ;
61
64
62
65
impl < ' a , ' tcx > LateLintPass < ' tcx > for UseCratePrefixForSelfImports < ' a , ' tcx > {
63
66
fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' a Item < ' tcx > ) {
64
67
let FileName :: Real ( RealFileName :: LocalPath ( p) ) = cx. sess ( ) . source_map ( ) . span_to_filename ( item. span ) else {
65
- self . use_block . clear ( ) ;
68
+ self . clear ( ) ;
66
69
return ;
67
70
} ;
68
71
let Some ( file_name) = p. file_name ( ) else {
69
- self . use_block . clear ( ) ;
72
+ self . clear ( ) ;
70
73
return ;
71
74
} ;
72
75
// only check `main.rs` and `lib.rs`
73
76
if !( file_name == "main.rs" || file_name == "lib.rs" ) {
74
77
return ;
75
78
}
76
79
77
- match item. kind {
78
- ItemKind :: Mod ( _) | ItemKind :: Use ( _, _) => { } ,
79
- _ => return ,
80
+ if self . in_same_block ( item. span ) {
81
+ self . insert_item ( item) ;
82
+ } else {
83
+ self . deal ( cx) ;
84
+ self . clear ( ) ;
85
+ self . insert_item ( item) ;
80
86
}
87
+ }
81
88
82
- if self . in_same_block ( item) {
83
- self . use_block . push ( item) ;
89
+ fn check_attribute ( & mut self , cx : & LateContext < ' tcx > , attribute : & ' a Attribute ) {
90
+ let FileName :: Real ( RealFileName :: LocalPath ( p) ) = cx. sess ( ) . source_map ( ) . span_to_filename ( attribute. span ) else {
91
+ self . clear ( ) ;
92
+ return ;
93
+ } ;
94
+ let Some ( file_name) = p. file_name ( ) else {
95
+ self . clear ( ) ;
96
+ return ;
97
+ } ;
98
+ // only check `main.rs` and `lib.rs`
99
+ if !( file_name == "main.rs" || file_name == "lib.rs" ) {
100
+ return ;
101
+ }
102
+
103
+ if self . in_same_block ( attribute. span ) {
104
+ self . spans . push ( attribute. span ) ;
84
105
} else {
85
106
self . deal ( cx) ;
86
- self . use_block . clear ( ) ;
87
- self . use_block . push ( item ) ;
107
+ self . clear ( ) ;
108
+ self . spans . push ( attribute . span ) ;
88
109
}
89
110
}
90
111
}
91
112
92
113
impl < ' tcx > UseCratePrefixForSelfImports < ' _ , ' tcx > {
93
- fn in_same_block ( & self , item : & Item < ' tcx > ) -> bool {
94
- if self . use_block . is_empty ( ) {
114
+ fn in_same_block ( & self , span : Span ) -> bool {
115
+ if self . spans . is_empty ( ) {
95
116
return true ;
96
117
}
97
- if self . use_block . iter ( ) . any ( |x| x. span . contains ( item . span ) ) {
118
+ if self . spans . iter ( ) . any ( |x| x. contains ( span) ) {
98
119
return true ;
99
120
}
100
- if self
101
- . use_block
102
- . iter ( )
103
- . any ( |x| item. span . lo ( ) - x. span . hi ( ) == BytePos ( 1 ) )
104
- {
121
+ if self . spans . iter ( ) . any ( |x| span. lo ( ) - x. hi ( ) == BytePos ( 1 ) ) {
105
122
return true ;
106
123
}
107
124
false
108
125
}
109
126
110
- fn deal ( & self , cx : & LateContext < ' tcx > ) {
111
- let mod_names: FxHashSet < Symbol > = self
112
- . use_block
113
- . iter ( )
114
- . filter_map ( |item| match item. kind {
115
- ItemKind :: Mod ( _) => Some ( item. ident . name ) ,
116
- _ => None ,
117
- } )
118
- . collect ( ) ;
127
+ fn insert_item ( & mut self , item : & Item < ' tcx > ) {
128
+ match item. kind {
129
+ ItemKind :: Mod ( _) => {
130
+ self . spans . push ( item. span ) ;
131
+ self . mod_names . insert ( item. ident . name ) ;
132
+ } ,
133
+ ItemKind :: Use ( use_tree, _) => {
134
+ self . spans . push ( item. span ) ;
135
+ self . use_block . push ( use_tree) ;
136
+ } ,
137
+ _ => { } ,
138
+ }
139
+ }
119
140
120
- for item in & self . use_block {
121
- if let ItemKind :: Use ( use_path, _) = & item. kind {
122
- if let Some ( segment) = use_path. segments . first ( )
123
- && let Res :: Def ( _, def_id) = segment. res
124
- && def_id. krate == LOCAL_CRATE
141
+ fn deal ( & self , cx : & LateContext < ' tcx > ) {
142
+ for use_path in & self . use_block {
143
+ if let Some ( segment) = use_path. segments . first ( )
144
+ && let Res :: Def ( _, def_id) = segment. res
145
+ && def_id. krate == LOCAL_CRATE
146
+ {
147
+ let root = segment. ident . name ;
148
+ if root != rustc_span:: symbol:: kw:: Crate
149
+ && root != rustc_span:: symbol:: kw:: Super
150
+ && root != rustc_span:: symbol:: kw:: SelfLower
151
+ && !self . mod_names . contains ( & root)
125
152
{
126
- let root = segment. ident . name ;
127
- if root != rustc_span:: symbol:: kw:: Crate
128
- && root != rustc_span:: symbol:: kw:: Super
129
- && root != rustc_span:: symbol:: kw:: SelfLower
130
- && !mod_names. contains ( & root)
131
- {
132
- span_lint_and_sugg (
133
- cx,
134
- USE_CRATE_PREFIX_FOR_SELF_IMPORTS ,
135
- segment. ident . span ,
136
- "this import is not clear" ,
137
- "prefix with `crate::`" ,
138
- format ! ( "crate::{}" , snippet_opt( cx, segment. ident. span) . unwrap( ) ) ,
139
- Applicability :: MachineApplicable ,
140
- ) ;
141
- }
153
+ span_lint_and_sugg (
154
+ cx,
155
+ USE_CRATE_PREFIX_FOR_SELF_IMPORTS ,
156
+ segment. ident . span ,
157
+ "this import is not clear" ,
158
+ "prefix with `crate::`" ,
159
+ format ! ( "crate::{}" , snippet_opt( cx, segment. ident. span) . unwrap( ) ) ,
160
+ Applicability :: MachineApplicable ,
161
+ ) ;
142
162
}
143
163
}
144
164
}
145
165
}
166
+
167
+ fn clear ( & mut self ) {
168
+ self . use_block . clear ( ) ;
169
+ self . mod_names . clear ( ) ;
170
+ self . spans . clear ( ) ;
171
+ }
146
172
}
0 commit comments