11use crate :: utils:: { snippet, span_lint_and_sugg, in_macro} ;
22use if_chain:: if_chain;
33use rustc_ast:: ast;
4- use rustc_data_structures:: fx:: FxHashSet ;
4+ use rustc_data_structures:: fx:: FxHashMap ;
55use rustc_errors:: Applicability ;
6- use rustc_lint:: { EarlyContext , EarlyLintPass } ;
6+ use rustc_lint:: { EarlyContext , EarlyLintPass , LintContext , Lint } ;
77use rustc_session:: { impl_lint_pass, declare_tool_lint} ;
88use rustc_span:: { edition:: Edition , Span } ;
9+ use rustc_hir as hir;
10+
11+ const PRELUDE : & [ & str ] = & [
12+ "marker" , "ops" , "convert" , "iter" , "option" , "result" , "borrow" , "boxed" , "string" , "vec" ,
13+ "macros"
14+ ] ;
15+
16+ pub type SuggFn = Box < dyn FnOnce ( EarlyContext < ' _ > , & ' static Lint , Span , & str , & str , String , Applicability ) > ;
17+ pub type SaveFn = Box < dyn FnOnce ( ) > ;
18+
19+ pub struct ImportData {
20+ name : String ,
21+ path : String ,
22+ }
23+
24+ impl ImportData {
25+ pub fn new ( name : String , span : Span , ecx : & EarlyContext < ' _ > ) -> Self {
26+ let path = ecx. sess . source_map ( ) . span_to_filename ( span) ;
27+ let path = ecx. sess . source_map ( ) . span_to_unmapped_path ( span) ;
28+ println ! ( "{:?} {:?}" , name, path) ;
29+ Self { name : name. to_string ( ) , path : path. to_string ( ) , }
30+ }
31+ }
932
1033declare_clippy_lint ! {
1134 /// **What it does:** Checks for `#[macro_use] use...`.
@@ -27,13 +50,20 @@ declare_clippy_lint! {
2750
2851#[ derive( Default ) ]
2952pub struct MacroUseImport {
30- collected : FxHashSet < Span > ,
53+ imports : Vec < ( String , Span ) > ,
54+ collected : FxHashMap < Span , ImportData > ,
55+ }
56+
57+ impl MacroUseImport {
58+ fn import_path_mac ( & self , name : & str ) -> String {
59+ println ! ( "{:?}" , name) ;
60+ String :: default ( )
61+ }
3162}
3263
3364impl_lint_pass ! ( MacroUseImport => [ MACRO_USE_IMPORT ] ) ;
3465
3566impl EarlyLintPass for MacroUseImport {
36-
3767 fn check_item ( & mut self , ecx : & EarlyContext < ' _ > , item : & ast:: Item ) {
3868 if_chain ! {
3969 if ecx. sess. opts. edition == Edition :: Edition2018 ;
@@ -44,58 +74,77 @@ impl EarlyLintPass for MacroUseImport {
4474 . find( |attr| attr. ident( ) . map( |s| s. to_string( ) ) == Some ( "macro_use" . to_string( ) ) ) ;
4575 then {
4676 let import_path = snippet( ecx, use_tree. span, "_" ) ;
47- let mac_names = find_used_macros( ecx, & import_path) ;
48- let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition" ;
49- let help = format!( "use {}::<macro name>" , import_path) ;
50- span_lint_and_sugg(
51- ecx,
52- MACRO_USE_IMPORT ,
53- mac_attr. span,
54- msg,
55- // "remove the attribute and import the macro directly, try",
56- "" ,
57- help,
58- Applicability :: HasPlaceholders ,
59- ) ;
77+ let span = mac_attr. span. clone( ) ;
78+ self . imports. push( ( import_path. to_string( ) , span) ) ;
6079 }
6180 }
6281 }
6382
6483 fn check_expr ( & mut self , ecx : & EarlyContext < ' _ > , expr : & ast:: Expr ) {
6584 if in_macro ( expr. span ) {
66- let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( expr. span . source_callsite ( ) , '!' ) , "_" ) ;
85+ let call_site = expr. span . source_callsite ( ) ;
86+ let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( call_site, '!' ) , "_" ) ;
6787 if let Some ( callee) = expr. span . source_callee ( ) {
68- if self . collected . insert ( callee. def_site ) {
69- println ! ( "EXPR {:#?}" , name) ;
70- }
88+ self . collected . entry ( call_site)
89+ . or_insert_with ( || {
90+ println ! ( "EXPR {:?}" , name) ;
91+ ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
92+ } ) ;
7193 }
7294 }
7395 }
7496 fn check_stmt ( & mut self , ecx : & EarlyContext < ' _ > , stmt : & ast:: Stmt ) {
7597 if in_macro ( stmt. span ) {
76- let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( stmt. span . source_callsite ( ) , '!' ) , "_" ) ;
98+ let call_site = stmt. span . source_callsite ( ) ;
99+ let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( call_site, '!' ) , "_" ) ;
77100 if let Some ( callee) = stmt. span . source_callee ( ) {
78- println ! ( "EXPR {:#?}" , name) ;
101+ self . collected . entry ( call_site)
102+ . or_insert_with ( || {
103+ println ! ( "STMT {:?}" , name) ;
104+ ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
105+ } ) ;
79106 }
80107 }
81108 }
82109 fn check_pat ( & mut self , ecx : & EarlyContext < ' _ > , pat : & ast:: Pat ) {
83110 if in_macro ( pat. span ) {
84- let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( pat. span . source_callsite ( ) , '!' ) , "_" ) ;
111+ let call_site = pat. span . source_callsite ( ) ;
112+ let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( call_site, '!' ) , "_" ) ;
85113 if let Some ( callee) = pat. span . source_callee ( ) {
86- println ! ( "EXPR {:#?}" , name) ;
114+ self . collected . entry ( call_site)
115+ . or_insert_with ( || {
116+ println ! ( "PAT {:?}" , name) ;
117+ ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
118+ } ) ;
87119 }
88120 }
89121 }
90- }
91-
92- fn find_used_macros ( ecx : & EarlyContext < ' _ > , path : & str ) {
93- for it in ecx. krate . module . items . iter ( ) {
94- if in_macro ( it. span ) {
95- // println!("{:#?}", it)
122+ fn check_mac ( & mut self , ecx : & EarlyContext < ' _ > , mac : & ast:: Mac ) {
123+ let call_site = mac. span ( ) . source_callsite ( ) ;
124+ let name = snippet ( ecx, ecx. sess . source_map ( ) . span_until_char ( call_site, '!' ) , "_" ) ;
125+ if let Some ( callee) = mac. span ( ) . source_callee ( ) {
126+ self . collected . entry ( call_site)
127+ . or_insert_with ( || {
128+ println ! ( "MAC {:?}" , name) ;
129+ ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
130+ } ) ;
96131 }
97132 }
98- for x in ecx. sess . imported_macro_spans . borrow ( ) . iter ( ) {
99- // println!("{:?}", x);
133+ fn check_crate_post ( & mut self , ecx : & EarlyContext < ' _ > , krate : & ast:: Crate ) {
134+ for ( name, span) in self . imports . iter ( ) {
135+ let import_path = self . import_path_mac ( & name) ;
136+ let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition" ;
137+ let help = format ! ( "use {}::{}" , import_path, name) ;
138+ span_lint_and_sugg (
139+ ecx,
140+ MACRO_USE_IMPORT ,
141+ * span,
142+ msg,
143+ // "remove the attribute and import the macro directly, try",
144+ "" ,
145+ help,
146+ Applicability :: HasPlaceholders ,
147+ )
148+ }
100149 }
101150}
0 commit comments