1010
1111use ast;
1212use codemap:: { DUMMY_SP , dummy_spanned} ;
13+ use ext:: base:: ExtCtxt ;
1314use ext:: expand:: { Expansion , ExpansionKind } ;
1415use fold:: * ;
1516use parse:: token:: keywords;
1617use ptr:: P ;
18+ use util:: move_map:: MoveMap ;
1719use util:: small_vector:: SmallVector ;
1820
1921use std:: collections:: HashMap ;
22+ use std:: mem;
2023
2124pub fn placeholder ( kind : ExpansionKind , id : ast:: NodeId ) -> Expansion {
2225 fn mac_placeholder ( ) -> ast:: Mac {
@@ -69,13 +72,15 @@ pub fn macro_scope_placeholder() -> Expansion {
6972 placeholder ( ExpansionKind :: Items , ast:: DUMMY_NODE_ID )
7073}
7174
72- pub struct PlaceholderExpander {
75+ pub struct PlaceholderExpander < ' a , ' b : ' a > {
7376 expansions : HashMap < ast:: NodeId , Expansion > ,
77+ cx : & ' a mut ExtCtxt < ' b > ,
7478}
7579
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 {
7882 PlaceholderExpander {
83+ cx : cx,
7984 expansions : HashMap :: new ( ) ,
8085 }
8186 }
@@ -89,7 +94,7 @@ impl PlaceholderExpander {
8994 }
9095}
9196
92- impl Folder for PlaceholderExpander {
97+ impl < ' a , ' b > Folder for PlaceholderExpander < ' a , ' b > {
9398 fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
9499 match item. node {
95100 // Scope placeholder
@@ -155,6 +160,54 @@ impl Folder for PlaceholderExpander {
155160 _ => noop_fold_ty ( ty, self ) ,
156161 }
157162 }
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+ }
158211}
159212
160213pub fn reconstructed_macro_rules ( def : & ast:: MacroDef , path : & ast:: Path ) -> Expansion {
0 commit comments