11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: is_test_module_or_function;
33use clippy_utils:: source:: { snippet, snippet_with_applicability} ;
4+ use rustc_data_structures:: fx:: FxHashSet ;
45use rustc_errors:: Applicability ;
56use rustc_hir:: def:: { DefKind , Res } ;
67use rustc_hir:: { Item , ItemKind , PathSegment , UseKind } ;
@@ -100,13 +101,15 @@ declare_clippy_lint! {
100101pub struct WildcardImports {
101102 warn_on_all : bool ,
102103 test_modules_deep : u32 ,
104+ ignored_segments : Vec < String > ,
103105}
104106
105107impl WildcardImports {
106- pub fn new ( warn_on_all : bool ) -> Self {
108+ pub fn new ( warn_on_all : bool , ignored_wildcard_imports : Vec < String > ) -> Self {
107109 Self {
108110 warn_on_all,
109111 test_modules_deep : 0 ,
112+ ignored_segments : ignored_wildcard_imports,
110113 }
111114 }
112115}
@@ -190,6 +193,7 @@ impl WildcardImports {
190193 item. span . from_expansion ( )
191194 || is_prelude_import ( segments)
192195 || ( is_super_only_import ( segments) && self . test_modules_deep > 0 )
196+ || is_ignored_via_config ( segments, & self . ignored_segments )
193197 }
194198}
195199
@@ -198,10 +202,20 @@ impl WildcardImports {
198202fn is_prelude_import ( segments : & [ PathSegment < ' _ > ] ) -> bool {
199203 segments
200204 . iter ( )
201- . any ( |ps| ps. ident . name . as_str ( ) . contains ( sym:: prelude. as_str ( ) ) )
205+ . any ( |ps| ps. ident . as_str ( ) . contains ( sym:: prelude. as_str ( ) ) )
202206}
203207
204208// Allow "super::*" imports in tests.
205209fn is_super_only_import ( segments : & [ PathSegment < ' _ > ] ) -> bool {
206210 segments. len ( ) == 1 && segments[ 0 ] . ident . name == kw:: Super
207211}
212+
213+ // Allow skipping imports containing user configured segments,
214+ // i.e. "...::utils::...::*" if user put `ignored-wildcard-imports = ["utils"]` in `Clippy.toml`
215+ fn is_ignored_via_config ( segments : & [ PathSegment < ' _ > ] , ignored_segments : & [ String ] ) -> bool {
216+ let segments_set: FxHashSet < & str > = segments. iter ( ) . map ( |s| s. ident . as_str ( ) ) . collect ( ) ;
217+ let ignored_set: FxHashSet < & str > = ignored_segments. iter ( ) . map ( String :: as_str) . collect ( ) ;
218+ // segment matching need to be exact instead of using 'contains', in case user unintentionaly put
219+ // a single character in the config thus skipping most of the warnings.
220+ segments_set. intersection ( & ignored_set) . next ( ) . is_some ( )
221+ }
0 commit comments