10
10
11
11
use ast;
12
12
use codemap:: { DUMMY_SP , dummy_spanned} ;
13
+ use ext:: base:: ExtCtxt ;
13
14
use ext:: expand:: { Expansion , ExpansionKind } ;
14
15
use fold:: * ;
15
16
use parse:: token:: keywords;
16
17
use ptr:: P ;
18
+ use util:: move_map:: MoveMap ;
17
19
use util:: small_vector:: SmallVector ;
18
20
19
21
use std:: collections:: HashMap ;
22
+ use std:: mem;
20
23
21
24
pub fn placeholder ( kind : ExpansionKind , id : ast:: NodeId ) -> Expansion {
22
25
fn mac_placeholder ( ) -> ast:: Mac {
@@ -69,13 +72,15 @@ pub fn macro_scope_placeholder() -> Expansion {
69
72
placeholder ( ExpansionKind :: Items , ast:: DUMMY_NODE_ID )
70
73
}
71
74
72
- pub struct PlaceholderExpander {
75
+ pub struct PlaceholderExpander < ' a , ' b : ' a > {
73
76
expansions : HashMap < ast:: NodeId , Expansion > ,
77
+ cx : & ' a mut ExtCtxt < ' b > ,
74
78
}
75
79
76
- impl PlaceholderExpander {
77
- pub fn new ( ) -> Self {
80
+ impl < ' a , ' b > PlaceholderExpander < ' a , ' b > {
81
+ pub fn new ( cx : & ' a mut ExtCtxt < ' b > ) -> Self {
78
82
PlaceholderExpander {
83
+ cx : cx,
79
84
expansions : HashMap :: new ( ) ,
80
85
}
81
86
}
@@ -89,7 +94,7 @@ impl PlaceholderExpander {
89
94
}
90
95
}
91
96
92
- impl Folder for PlaceholderExpander {
97
+ impl < ' a , ' b > Folder for PlaceholderExpander < ' a , ' b > {
93
98
fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
94
99
match item. node {
95
100
// Scope placeholder
@@ -155,6 +160,54 @@ impl Folder for PlaceholderExpander {
155
160
_ => noop_fold_ty ( ty, self ) ,
156
161
}
157
162
}
163
+
164
+ fn fold_block ( & mut self , block : P < ast:: Block > ) -> P < ast:: Block > {
165
+ noop_fold_block ( block, self ) . map ( |mut block| {
166
+ let mut macros = Vec :: new ( ) ;
167
+ let mut remaining_stmts = block. stmts . len ( ) ;
168
+
169
+ block. stmts = block. stmts . move_flat_map ( |mut stmt| {
170
+ remaining_stmts -= 1 ;
171
+
172
+ // Scope placeholder
173
+ if let ast:: StmtKind :: Item ( ref item) = stmt. node {
174
+ if let ast:: ItemKind :: Mac ( ..) = item. node {
175
+ macros. push ( item. ident . ctxt . data ( ) . outer_mark ) ;
176
+ return None ;
177
+ }
178
+ }
179
+
180
+ match stmt. node {
181
+ // Avoid wasting a node id on a trailing expression statement,
182
+ // which shares a HIR node with the expression itself.
183
+ ast:: StmtKind :: Expr ( ref expr) if remaining_stmts == 0 => stmt. id = expr. id ,
184
+
185
+ _ => {
186
+ assert_eq ! ( stmt. id, ast:: DUMMY_NODE_ID ) ;
187
+ stmt. id = self . cx . resolver . next_node_id ( ) ;
188
+ }
189
+ }
190
+
191
+ if !macros. is_empty ( ) {
192
+ let macros = mem:: replace ( & mut macros, Vec :: new ( ) ) ;
193
+ self . cx . resolver . add_expansions_at_stmt ( stmt. id , macros) ;
194
+ }
195
+
196
+ Some ( stmt)
197
+ } ) ;
198
+
199
+ block
200
+ } )
201
+ }
202
+
203
+ fn fold_mod ( & mut self , module : ast:: Mod ) -> ast:: Mod {
204
+ let mut module = noop_fold_mod ( module, self ) ;
205
+ module. items = module. items . move_flat_map ( |item| match item. node {
206
+ ast:: ItemKind :: Mac ( _) => None , // remove scope placeholders from modules
207
+ _ => Some ( item) ,
208
+ } ) ;
209
+ module
210
+ }
158
211
}
159
212
160
213
pub fn reconstructed_macro_rules ( def : & ast:: MacroDef , path : & ast:: Path ) -> Expansion {
0 commit comments