@@ -12,18 +12,28 @@ const PRELUDE: &[&str] = &[
12
12
"marker" , "ops" , "convert" , "iter" , "option" , "result" , "borrow" , "boxed" , "string" , "vec" ,
13
13
"macros"
14
14
] ;
15
-
16
- pub struct ImportData {
15
+ const BRACKETS : & [ char ] = & [ '<' , '>' ] ;
16
+ /// MacroRefData includes the name of the macro
17
+ /// and the path from `SourceMap::span_to_filename`.
18
+ pub struct MacroRefData {
17
19
name : String ,
18
20
path : String ,
19
21
}
20
22
21
- impl ImportData {
23
+ impl MacroRefData {
22
24
pub fn new ( name : String , span : Span , ecx : & EarlyContext < ' _ > ) -> Self {
23
- let path = ecx. sess . source_map ( ) . span_to_filename ( span) ;
24
- let path = ecx. sess . source_map ( ) . span_to_unmapped_path ( span) ;
25
- println ! ( "NEW {:?} {:?}" , name, path) ;
26
- Self { name : name. to_string ( ) , path : path. to_string ( ) , }
25
+ let mut path = ecx. sess . source_map ( ) . span_to_filename ( span) . to_string ( ) ;
26
+
27
+ // std lib paths are <::std::module::file type>
28
+ // so remove brackets and space
29
+ if path. contains ( '<' ) {
30
+ path = path. replace ( BRACKETS , "" ) ;
31
+ }
32
+ if path. contains ( ' ' ) {
33
+ path = path. split ( ' ' ) . next ( ) . unwrap ( ) . to_string ( ) ;
34
+ }
35
+ println ! ( "NEW {} {}" , name, path) ;
36
+ Self { name : name. to_string ( ) , path, }
27
37
}
28
38
}
29
39
@@ -47,17 +57,47 @@ declare_clippy_lint! {
47
57
48
58
#[ derive( Default ) ]
49
59
pub struct MacroUseImport {
60
+ /// the actual import path used and its span.
50
61
imports : Vec < ( String , Span ) > ,
51
- collected : FxHashMap < Span , ImportData > ,
62
+ /// the span of the macro reference and the `MacroRefData`
63
+ /// for the use of the macro.
64
+ collected : FxHashMap < Span , MacroRefData > ,
52
65
}
53
66
54
67
impl MacroUseImport {
55
- fn import_path_mac ( & self , name : & str ) -> String {
56
- println ! ( "END {:?}" , name) ;
57
- String :: default ( )
68
+ fn import_path_mac ( & self , use_path : & str ) -> String {
69
+ println ! ( "END {:?}" , use_path) ;
70
+
71
+ for mac in self . collected . values ( ) {
72
+ if paths_match ( mac, use_path) {
73
+ return make_path ( mac, use_path)
74
+ }
75
+ }
76
+ format ! ( "{}::<macro name>" , use_path)
58
77
}
59
78
}
60
79
80
+ fn paths_match ( mac : & MacroRefData , use_path : & str ) -> bool {
81
+ let segs = mac. path . split ( "::" )
82
+ . filter ( |s| * s == "" )
83
+ . collect :: < Vec < _ > > ( ) ;
84
+ if segs. starts_with ( & [ "std" ] ) {
85
+ return PRELUDE . iter ( ) . any ( |m| segs. contains ( m) )
86
+ }
87
+ false
88
+ }
89
+
90
+ fn make_path ( mac : & MacroRefData , use_path : & str ) -> String {
91
+ let mut res = String :: default ( ) ;
92
+
93
+ let segs = mac. path . split ( "::" )
94
+ . filter ( |s| * s == "" )
95
+ . collect :: < Vec < _ > > ( ) ;
96
+
97
+
98
+ res
99
+ }
100
+
61
101
impl_lint_pass ! ( MacroUseImport => [ MACRO_USE_IMPORT ] ) ;
62
102
63
103
impl EarlyLintPass for MacroUseImport {
@@ -85,7 +125,7 @@ impl EarlyLintPass for MacroUseImport {
85
125
self . collected . entry ( call_site)
86
126
. or_insert_with ( || {
87
127
println ! ( "EXPR {:?}" , name) ;
88
- ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
128
+ MacroRefData :: new ( name. to_string ( ) , callee. def_site , ecx)
89
129
} ) ;
90
130
}
91
131
}
@@ -98,7 +138,7 @@ impl EarlyLintPass for MacroUseImport {
98
138
self . collected . entry ( call_site)
99
139
. or_insert_with ( || {
100
140
println ! ( "STMT {:?}" , name) ;
101
- ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
141
+ MacroRefData :: new ( name. to_string ( ) , callee. def_site , ecx)
102
142
} ) ;
103
143
}
104
144
}
@@ -111,7 +151,7 @@ impl EarlyLintPass for MacroUseImport {
111
151
self . collected . entry ( call_site)
112
152
. or_insert_with ( || {
113
153
println ! ( "PAT {:?}" , name) ;
114
- ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
154
+ MacroRefData :: new ( name. to_string ( ) , callee. def_site , ecx)
115
155
} ) ;
116
156
}
117
157
}
@@ -123,15 +163,16 @@ impl EarlyLintPass for MacroUseImport {
123
163
self . collected . entry ( call_site)
124
164
. or_insert_with ( || {
125
165
println ! ( "MAC {:?}" , name) ;
126
- ImportData :: new ( name. to_string ( ) , callee. def_site , ecx)
166
+ MacroRefData :: new ( name. to_string ( ) , callee. def_site , ecx)
127
167
} ) ;
128
168
}
129
169
}
170
+
130
171
fn check_crate_post ( & mut self , ecx : & EarlyContext < ' _ > , krate : & ast:: Crate ) {
131
172
for ( name, span) in self . imports . iter ( ) {
132
173
let import_path = self . import_path_mac ( & name) ;
133
174
let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition" ;
134
- let help = format ! ( "use {}::{} " , import_path, name ) ;
175
+ let help = format ! ( "use {}" , import_path) ;
135
176
span_lint_and_sugg (
136
177
ecx,
137
178
MACRO_USE_IMPORT ,
0 commit comments