1
1
use crate :: utils:: { snippet, span_lint_and_sugg, in_macro} ;
2
2
use if_chain:: if_chain;
3
3
use rustc_ast:: ast;
4
- use rustc_data_structures:: fx:: FxHashSet ;
4
+ use rustc_data_structures:: fx:: FxHashMap ;
5
5
use rustc_errors:: Applicability ;
6
- use rustc_lint:: { EarlyContext , EarlyLintPass } ;
6
+ use rustc_lint:: { EarlyContext , EarlyLintPass , LintContext , Lint } ;
7
7
use rustc_session:: { impl_lint_pass, declare_tool_lint} ;
8
8
use 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
+ }
9
32
10
33
declare_clippy_lint ! {
11
34
/// **What it does:** Checks for `#[macro_use] use...`.
@@ -27,13 +50,20 @@ declare_clippy_lint! {
27
50
28
51
#[ derive( Default ) ]
29
52
pub 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
+ }
31
62
}
32
63
33
64
impl_lint_pass ! ( MacroUseImport => [ MACRO_USE_IMPORT ] ) ;
34
65
35
66
impl EarlyLintPass for MacroUseImport {
36
-
37
67
fn check_item ( & mut self , ecx : & EarlyContext < ' _ > , item : & ast:: Item ) {
38
68
if_chain ! {
39
69
if ecx. sess. opts. edition == Edition :: Edition2018 ;
@@ -44,58 +74,77 @@ impl EarlyLintPass for MacroUseImport {
44
74
. find( |attr| attr. ident( ) . map( |s| s. to_string( ) ) == Some ( "macro_use" . to_string( ) ) ) ;
45
75
then {
46
76
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) ) ;
60
79
}
61
80
}
62
81
}
63
82
64
83
fn check_expr ( & mut self , ecx : & EarlyContext < ' _ > , expr : & ast:: Expr ) {
65
84
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, '!' ) , "_" ) ;
67
87
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
+ } ) ;
71
93
}
72
94
}
73
95
}
74
96
fn check_stmt ( & mut self , ecx : & EarlyContext < ' _ > , stmt : & ast:: Stmt ) {
75
97
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, '!' ) , "_" ) ;
77
100
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
+ } ) ;
79
106
}
80
107
}
81
108
}
82
109
fn check_pat ( & mut self , ecx : & EarlyContext < ' _ > , pat : & ast:: Pat ) {
83
110
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, '!' ) , "_" ) ;
85
113
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
+ } ) ;
87
119
}
88
120
}
89
121
}
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
+ } ) ;
96
131
}
97
132
}
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
+ }
100
149
}
101
150
}
0 commit comments