1- use clippy_utils:: diagnostics:: span_lint_and_sugg ;
1+ use clippy_utils:: diagnostics:: span_lint_hir_and_then ;
22use clippy_utils:: source:: snippet;
33use hir:: def:: { DefKind , Res } ;
44use if_chain:: if_chain;
@@ -51,8 +51,9 @@ impl MacroRefData {
5151#[ derive( Default ) ]
5252#[ expect( clippy:: module_name_repetitions) ]
5353pub struct MacroUseImports {
54- /// the actual import path used and the span of the attribute above it.
55- imports : Vec < ( String , Span ) > ,
54+ /// the actual import path used and the span of the attribute above it. The value is
55+ /// the location, where the lint should be emitted.
56+ imports : Vec < ( String , Span , hir:: HirId ) > ,
5657 /// the span of the macro reference, kept to ensure only one reference is used per macro call.
5758 collected : FxHashSet < Span > ,
5859 mac_refs : Vec < MacroRefData > ,
@@ -91,7 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
9192 if_chain ! {
9293 if cx. sess( ) . opts. edition >= Edition :: Edition2018 ;
9394 if let hir:: ItemKind :: Use ( path, _kind) = & item. kind;
94- let attrs = cx. tcx. hir( ) . attrs( item. hir_id( ) ) ;
95+ let hir_id = item. hir_id( ) ;
96+ let attrs = cx. tcx. hir( ) . attrs( hir_id) ;
9597 if let Some ( mac_attr) = attrs. iter( ) . find( |attr| attr. has_name( sym:: macro_use) ) ;
9698 if let Res :: Def ( DefKind :: Mod , id) = path. res;
9799 if !id. is_local( ) ;
@@ -100,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
100102 if let Res :: Def ( DefKind :: Macro ( _mac_type) , mac_id) = kid. res {
101103 let span = mac_attr. span;
102104 let def_path = cx. tcx. def_path_str( mac_id) ;
103- self . imports. push( ( def_path, span) ) ;
105+ self . imports. push( ( def_path, span, hir_id ) ) ;
104106 }
105107 }
106108 } else {
@@ -138,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
138140 fn check_crate_post ( & mut self , cx : & LateContext < ' _ > ) {
139141 let mut used = FxHashMap :: default ( ) ;
140142 let mut check_dup = vec ! [ ] ;
141- for ( import, span) in & self . imports {
143+ for ( import, span, hir_id ) in & self . imports {
142144 let found_idx = self . mac_refs . iter ( ) . position ( |mac| import. ends_with ( & mac. name ) ) ;
143145
144146 if let Some ( idx) = found_idx {
@@ -151,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
151153 [ ] | [ _] => return ,
152154 [ root, item] => {
153155 if !check_dup. contains ( & ( * item) . to_string ( ) ) {
154- used. entry ( ( ( * root) . to_string ( ) , span) )
156+ used. entry ( ( ( * root) . to_string ( ) , span, hir_id ) )
155157 . or_insert_with ( Vec :: new)
156158 . push ( ( * item) . to_string ( ) ) ;
157159 check_dup. push ( ( * item) . to_string ( ) ) ;
@@ -169,13 +171,13 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
169171 }
170172 } )
171173 . collect :: < Vec < _ > > ( ) ;
172- used. entry ( ( ( * root) . to_string ( ) , span) )
174+ used. entry ( ( ( * root) . to_string ( ) , span, hir_id ) )
173175 . or_insert_with ( Vec :: new)
174176 . push ( filtered. join ( "::" ) ) ;
175177 check_dup. extend ( filtered) ;
176178 } else {
177179 let rest = rest. to_vec ( ) ;
178- used. entry ( ( ( * root) . to_string ( ) , span) )
180+ used. entry ( ( ( * root) . to_string ( ) , span, hir_id ) )
179181 . or_insert_with ( Vec :: new)
180182 . push ( rest. join ( "::" ) ) ;
181183 check_dup. extend ( rest. iter ( ) . map ( ToString :: to_string) ) ;
@@ -186,27 +188,33 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
186188 }
187189
188190 let mut suggestions = vec ! [ ] ;
189- for ( ( root, span) , path) in used {
191+ for ( ( root, span, hir_id ) , path) in used {
190192 if path. len ( ) == 1 {
191- suggestions. push ( ( span, format ! ( "{}::{}" , root, path[ 0 ] ) ) ) ;
193+ suggestions. push ( ( span, format ! ( "{}::{}" , root, path[ 0 ] ) , hir_id ) ) ;
192194 } else {
193- suggestions. push ( ( span, format ! ( "{}::{{{}}}" , root, path. join( ", " ) ) ) ) ;
195+ suggestions. push ( ( span, format ! ( "{}::{{{}}}" , root, path. join( ", " ) ) , hir_id ) ) ;
194196 }
195197 }
196198
197199 // If mac_refs is not empty we have encountered an import we could not handle
198200 // such as `std::prelude::v1::foo` or some other macro that expands to an import.
199201 if self . mac_refs . is_empty ( ) {
200- for ( span, import) in suggestions {
202+ for ( span, import, hir_id ) in suggestions {
201203 let help = format ! ( "use {};" , import) ;
202- span_lint_and_sugg (
204+ span_lint_hir_and_then (
203205 cx,
204206 MACRO_USE_IMPORTS ,
207+ * hir_id,
205208 * span,
206209 "`macro_use` attributes are no longer needed in the Rust 2018 edition" ,
207- "remove the attribute and import the macro directly, try" ,
208- help,
209- Applicability :: MaybeIncorrect ,
210+ |diag| {
211+ diag. span_suggestion (
212+ * span,
213+ "remove the attribute and import the macro directly, try" ,
214+ help,
215+ Applicability :: MaybeIncorrect ,
216+ ) ;
217+ } ,
210218 ) ;
211219 }
212220 }
0 commit comments