@@ -4,10 +4,10 @@ use def_id::LOCAL_CRATE;
44use rustc_data_structures:: fx:: FxHashSet ;
55use rustc_errors:: Applicability ;
66use rustc_hir:: def:: Res ;
7- use rustc_hir:: { Item , ItemKind , def_id} ;
7+ use rustc_hir:: { Attribute , Item , ItemKind , UsePath , def_id} ;
88use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
99use rustc_session:: impl_lint_pass;
10- use rustc_span:: { BytePos , FileName , RealFileName , Symbol } ;
10+ use rustc_span:: { BytePos , FileName , RealFileName , Span , Symbol } ;
1111
1212declare_clippy_lint ! {
1313 /// ### What it does
@@ -53,94 +53,121 @@ declare_clippy_lint! {
5353
5454#[ derive( Clone , Default ) ]
5555pub struct UseCratePrefixForSelfImports < ' a , ' tcx > {
56- /// code block of `use <foo>` or `mod <foo>`
57- use_block : Vec < & ' a Item < ' tcx > > ,
56+ /// collect `use` in current block
57+ use_block : Vec < & ' a UsePath < ' tcx > > ,
58+ /// collect `mod` in current block
59+ mod_names : FxHashSet < Symbol > ,
60+ /// spans of `mod`, `use`, and attributes
61+ spans : Vec < Span > ,
5862}
5963
6064impl_lint_pass ! ( UseCratePrefixForSelfImports <' _, ' _> => [ USE_CRATE_PREFIX_FOR_SELF_IMPORTS ] ) ;
6165
6266impl < ' a , ' tcx > LateLintPass < ' tcx > for UseCratePrefixForSelfImports < ' a , ' tcx > {
6367 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' a Item < ' tcx > ) {
6468 let FileName :: Real ( RealFileName :: LocalPath ( p) ) = cx. sess ( ) . source_map ( ) . span_to_filename ( item. span ) else {
65- self . use_block . clear ( ) ;
69+ self . clear ( ) ;
6670 return ;
6771 } ;
6872 let Some ( file_name) = p. file_name ( ) else {
69- self . use_block . clear ( ) ;
73+ self . clear ( ) ;
7074 return ;
7175 } ;
7276 // only check `main.rs` and `lib.rs`
7377 if !( file_name == "main.rs" || file_name == "lib.rs" ) {
7478 return ;
7579 }
7680
77- match item. kind {
78- ItemKind :: Mod ( _) | ItemKind :: Use ( _, _) => { } ,
79- _ => return ,
81+ if self . in_same_block ( item. span ) {
82+ self . insert_item ( item) ;
83+ } else {
84+ self . deal ( cx) ;
85+ self . clear ( ) ;
86+ self . insert_item ( item) ;
8087 }
88+ }
8189
82- if self . in_same_block ( item) {
83- self . use_block . push ( item) ;
90+ fn check_attribute ( & mut self , cx : & LateContext < ' tcx > , attribute : & ' a Attribute ) {
91+ let FileName :: Real ( RealFileName :: LocalPath ( p) ) = cx. sess ( ) . source_map ( ) . span_to_filename ( attribute. span ) else {
92+ self . clear ( ) ;
93+ return ;
94+ } ;
95+ let Some ( file_name) = p. file_name ( ) else {
96+ self . clear ( ) ;
97+ return ;
98+ } ;
99+ // only check `main.rs` and `lib.rs`
100+ if !( file_name == "main.rs" || file_name == "lib.rs" ) {
101+ return ;
102+ }
103+
104+ if self . in_same_block ( attribute. span ) {
105+ self . spans . push ( attribute. span ) ;
84106 } else {
85107 self . deal ( cx) ;
86- self . use_block . clear ( ) ;
87- self . use_block . push ( item ) ;
108+ self . clear ( ) ;
109+ self . spans . push ( attribute . span ) ;
88110 }
89111 }
90112}
91113
92114impl < ' tcx > UseCratePrefixForSelfImports < ' _ , ' tcx > {
93- fn in_same_block ( & self , item : & Item < ' tcx > ) -> bool {
94- if self . use_block . is_empty ( ) {
115+ fn in_same_block ( & self , span : Span ) -> bool {
116+ if self . spans . is_empty ( ) {
95117 return true ;
96118 }
97- if self . use_block . iter ( ) . any ( |x| x. span . contains ( item . span ) ) {
119+ if self . spans . iter ( ) . any ( |x| x. contains ( span) ) {
98120 return true ;
99121 }
100- if self
101- . use_block
102- . iter ( )
103- . any ( |x| item. span . lo ( ) - x. span . hi ( ) == BytePos ( 1 ) )
104- {
122+ if self . spans . iter ( ) . any ( |x| span. lo ( ) - x. hi ( ) == BytePos ( 1 ) ) {
105123 return true ;
106124 }
107125 false
108126 }
109127
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 ( ) ;
128+ fn insert_item ( & mut self , item : & Item < ' tcx > ) {
129+ match item. kind {
130+ ItemKind :: Mod ( _) => {
131+ self . spans . push ( item. span ) ;
132+ self . mod_names . insert ( item. ident . name ) ;
133+ } ,
134+ ItemKind :: Use ( use_tree, _) => {
135+ self . spans . push ( item. span ) ;
136+ self . use_block . push ( use_tree) ;
137+ } ,
138+ _ => { } ,
139+ }
140+ }
119141
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
142+ fn deal ( & self , cx : & LateContext < ' tcx > ) {
143+ for use_path in & self . use_block {
144+ if let Some ( segment) = use_path. segments . first ( )
145+ && let Res :: Def ( _, def_id) = segment. res
146+ && def_id. krate == LOCAL_CRATE
147+ {
148+ let root = segment. ident . name ;
149+ if root != rustc_span:: symbol:: kw:: Crate
150+ && root != rustc_span:: symbol:: kw:: Super
151+ && root != rustc_span:: symbol:: kw:: SelfLower
152+ && !self . mod_names . contains ( & root)
125153 {
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- }
154+ span_lint_and_sugg (
155+ cx,
156+ USE_CRATE_PREFIX_FOR_SELF_IMPORTS ,
157+ segment. ident . span ,
158+ "this import is not clear" ,
159+ "prefix with `crate::`" ,
160+ format ! ( "crate::{}" , snippet_opt( cx, segment. ident. span) . unwrap( ) ) ,
161+ Applicability :: MachineApplicable ,
162+ ) ;
142163 }
143164 }
144165 }
145166 }
167+
168+ fn clear ( & mut self ) {
169+ self . use_block . clear ( ) ;
170+ self . mod_names . clear ( ) ;
171+ self . spans . clear ( ) ;
172+ }
146173}
0 commit comments