@@ -6,7 +6,7 @@ use rustc_hir::{
66 Item , ItemKind , PathSegment , UseKind ,
77} ;
88use rustc_lint:: { LateContext , LateLintPass } ;
9- use rustc_session:: { declare_lint_pass , declare_tool_lint } ;
9+ use rustc_session:: { declare_tool_lint , impl_lint_pass } ;
1010use rustc_span:: BytePos ;
1111
1212declare_clippy_lint ! {
@@ -73,18 +73,38 @@ declare_clippy_lint! {
7373 "lint `use _::*` statements"
7474}
7575
76- declare_lint_pass ! ( WildcardImports => [ ENUM_GLOB_USE , WILDCARD_IMPORTS ] ) ;
76+ #[ derive( Default ) ]
77+ pub struct WildcardImports {
78+ warn_on_all : bool ,
79+ is_test_module : bool ,
80+ test_modules_deep : u32 ,
81+ }
82+
83+ impl WildcardImports {
84+ pub fn new ( warn_on_all : bool ) -> Self {
85+ Self {
86+ warn_on_all,
87+ is_test_module : false ,
88+ test_modules_deep : 0 ,
89+ }
90+ }
91+ }
92+
93+ impl_lint_pass ! ( WildcardImports => [ ENUM_GLOB_USE , WILDCARD_IMPORTS ] ) ;
7794
7895impl LateLintPass < ' _ , ' _ > for WildcardImports {
7996 fn check_item ( & mut self , cx : & LateContext < ' _ , ' _ > , item : & Item < ' _ > ) {
8097 if item. vis . node . is_pub ( ) || item. vis . node . is_pub_restricted ( ) {
8198 return ;
8299 }
100+ if is_test_module ( item) {
101+ self . is_test_module = true ;
102+ self . test_modules_deep += 1 ;
103+ }
83104 if_chain ! {
84105 if !in_macro( item. span) ;
85106 if let ItemKind :: Use ( use_path, UseKind :: Glob ) = & item. kind;
86- if !is_prelude_import( use_path. segments) ;
87- if !( is_super_only_import( use_path. segments) && is_in_test_module( cx, item) ) ;
107+ if self . warn_on_all || !self . check_exceptions( use_path. segments) ;
88108 let used_imports = cx. tcx. names_imported_by_glob_use( item. hir_id. owner) ;
89109 if !used_imports. is_empty( ) ; // Already handled by `unused_imports`
90110 then {
@@ -152,6 +172,19 @@ impl LateLintPass<'_, '_> for WildcardImports {
152172 }
153173 }
154174 }
175+
176+ fn check_item_post ( & mut self , _: & LateContext < ' _ , ' _ > , _: & Item < ' _ > ) {
177+ if self . is_test_module {
178+ self . is_test_module = false ;
179+ self . test_modules_deep -= 1 ;
180+ }
181+ }
182+ }
183+
184+ impl WildcardImports {
185+ fn check_exceptions ( & self , segments : & [ PathSegment < ' _ > ] ) -> bool {
186+ is_prelude_import ( segments) || ( is_super_only_import ( segments) && self . test_modules_deep > 0 )
187+ }
155188}
156189
157190// Allow "...prelude::*" imports.
@@ -168,9 +201,6 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool {
168201 segments. len ( ) == 1 && segments[ 0 ] . ident . as_str ( ) == "super"
169202}
170203
171- fn is_in_test_module ( cx : & LateContext < ' _ , ' _ > , item : & Item < ' _ > ) -> bool {
172- let parent = cx. tcx . hir ( ) . get_parent_node ( item. hir_id ) ;
173- let parent_item = cx. tcx . hir ( ) . expect_item ( parent) ;
174- let parent_name = parent_item. ident . name . as_str ( ) ;
175- parent_name. contains ( "test" )
204+ fn is_test_module ( item : & Item < ' _ > ) -> bool {
205+ item. ident . name . as_str ( ) . contains ( "test" )
176206}
0 commit comments