]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
1 | use crate::base::ExtCtxt; |
2 | use crate::expand::{AstFragment, AstFragmentKind}; | |
3 | ||
74b04a01 XL |
4 | use rustc_ast::ast; |
5 | use rustc_ast::mut_visit::*; | |
6 | use rustc_ast::ptr::P; | |
dfeec247 | 7 | use rustc_span::source_map::{dummy_spanned, DUMMY_SP}; |
9fa01778 XL |
8 | |
9 | use smallvec::{smallvec, SmallVec}; | |
9e0c209e | 10 | |
b7449926 | 11 | use rustc_data_structures::fx::FxHashMap; |
9e0c209e | 12 | |
dfeec247 XL |
13 | pub fn placeholder( |
14 | kind: AstFragmentKind, | |
15 | id: ast::NodeId, | |
16 | vis: Option<ast::Visibility>, | |
17 | ) -> AstFragment { | |
ba9703b0 XL |
18 | fn mac_placeholder() -> ast::MacCall { |
19 | ast::MacCall { | |
32a655c1 | 20 | path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, |
60c5eb7d | 21 | args: P(ast::MacArgs::Empty), |
416331ca | 22 | prior_type_ascription: None, |
e1599b0c | 23 | } |
9e0c209e SL |
24 | } |
25 | ||
dc9dc135 | 26 | let ident = ast::Ident::invalid(); |
9e0c209e | 27 | let attrs = Vec::new(); |
e74abb32 | 28 | let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited)); |
9e0c209e | 29 | let span = DUMMY_SP; |
dfeec247 XL |
30 | let expr_placeholder = || { |
31 | P(ast::Expr { | |
32 | id, | |
33 | span, | |
34 | attrs: ast::AttrVec::new(), | |
ba9703b0 | 35 | kind: ast::ExprKind::MacCall(mac_placeholder()), |
dfeec247 XL |
36 | }) |
37 | }; | |
ba9703b0 XL |
38 | let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span }); |
39 | let pat = || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span }); | |
9e0c209e SL |
40 | |
41 | match kind { | |
8faf50e0 XL |
42 | AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), |
43 | AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), | |
b7449926 | 44 | AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { |
dfeec247 XL |
45 | id, |
46 | span, | |
47 | ident, | |
48 | vis, | |
49 | attrs, | |
ba9703b0 | 50 | kind: ast::ItemKind::MacCall(mac_placeholder()), |
3b2f2976 | 51 | tokens: None, |
b7449926 | 52 | })]), |
74b04a01 | 53 | AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem { |
dfeec247 XL |
54 | id, |
55 | span, | |
56 | ident, | |
57 | vis, | |
58 | attrs, | |
ba9703b0 | 59 | kind: ast::AssocItemKind::MacCall(mac_placeholder()), |
3b2f2976 | 60 | tokens: None, |
74b04a01 XL |
61 | })]), |
62 | AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem { | |
dfeec247 XL |
63 | id, |
64 | span, | |
65 | ident, | |
66 | vis, | |
67 | attrs, | |
ba9703b0 | 68 | kind: ast::AssocItemKind::MacCall(mac_placeholder()), |
3b2f2976 | 69 | tokens: None, |
74b04a01 XL |
70 | })]), |
71 | AstFragmentKind::ForeignItems => { | |
72 | AstFragment::ForeignItems(smallvec![P(ast::ForeignItem { | |
73 | id, | |
74 | span, | |
75 | ident, | |
76 | vis, | |
77 | attrs, | |
ba9703b0 | 78 | kind: ast::ForeignItemKind::MacCall(mac_placeholder()), |
74b04a01 XL |
79 | tokens: None, |
80 | })]) | |
81 | } | |
ba9703b0 XL |
82 | AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat { |
83 | id, | |
84 | span, | |
85 | kind: ast::PatKind::MacCall(mac_placeholder()), | |
86 | })), | |
dfeec247 | 87 | AstFragmentKind::Ty => { |
ba9703b0 | 88 | AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) })) |
dfeec247 | 89 | } |
b7449926 | 90 | AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{ |
dfeec247 | 91 | let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new())); |
ba9703b0 | 92 | ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) } |
b7449926 | 93 | }]), |
dfeec247 XL |
94 | AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm { |
95 | attrs: Default::default(), | |
96 | body: expr_placeholder(), | |
97 | guard: None, | |
98 | id, | |
99 | pat: pat(), | |
100 | span, | |
101 | is_placeholder: true, | |
102 | }]), | |
103 | AstFragmentKind::Fields => AstFragment::Fields(smallvec![ast::Field { | |
104 | attrs: Default::default(), | |
105 | expr: expr_placeholder(), | |
106 | id, | |
107 | ident, | |
108 | is_shorthand: false, | |
109 | span, | |
110 | is_placeholder: true, | |
111 | }]), | |
112 | AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![ast::FieldPat { | |
113 | attrs: Default::default(), | |
114 | id, | |
115 | ident, | |
116 | is_shorthand: false, | |
117 | pat: pat(), | |
118 | span, | |
119 | is_placeholder: true, | |
120 | }]), | |
e1599b0c XL |
121 | AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{ |
122 | ast::GenericParam { | |
123 | attrs: Default::default(), | |
124 | bounds: Default::default(), | |
125 | id, | |
126 | ident, | |
127 | is_placeholder: true, | |
128 | kind: ast::GenericParamKind::Lifetime, | |
129 | } | |
130 | }]), | |
dfeec247 XL |
131 | AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param { |
132 | attrs: Default::default(), | |
133 | id, | |
134 | pat: pat(), | |
135 | span, | |
136 | ty: ty(), | |
137 | is_placeholder: true, | |
138 | }]), | |
139 | AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ast::StructField { | |
140 | attrs: Default::default(), | |
141 | id, | |
142 | ident: None, | |
143 | span, | |
144 | ty: ty(), | |
145 | vis, | |
146 | is_placeholder: true, | |
147 | }]), | |
148 | AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant { | |
149 | attrs: Default::default(), | |
150 | data: ast::VariantData::Struct(Default::default(), false), | |
151 | disr_expr: None, | |
152 | id, | |
153 | ident, | |
154 | span, | |
155 | vis, | |
156 | is_placeholder: true, | |
157 | }]), | |
9e0c209e SL |
158 | } |
159 | } | |
160 | ||
dc9dc135 | 161 | pub struct PlaceholderExpander<'a, 'b> { |
b7449926 | 162 | expanded_fragments: FxHashMap<ast::NodeId, AstFragment>, |
9e0c209e SL |
163 | cx: &'a mut ExtCtxt<'b>, |
164 | monotonic: bool, | |
165 | } | |
166 | ||
167 | impl<'a, 'b> PlaceholderExpander<'a, 'b> { | |
168 | pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { | |
dfeec247 | 169 | PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic } |
9e0c209e SL |
170 | } |
171 | ||
e74abb32 | 172 | pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { |
9fa01778 | 173 | fragment.mut_visit_with(self); |
8faf50e0 | 174 | self.expanded_fragments.insert(id, fragment); |
9e0c209e SL |
175 | } |
176 | ||
8faf50e0 XL |
177 | fn remove(&mut self, id: ast::NodeId) -> AstFragment { |
178 | self.expanded_fragments.remove(&id).unwrap() | |
9e0c209e SL |
179 | } |
180 | } | |
181 | ||
9fa01778 | 182 | impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> { |
e1599b0c XL |
183 | fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { |
184 | if arm.is_placeholder { | |
185 | self.remove(arm.id).make_arms() | |
186 | } else { | |
187 | noop_flat_map_arm(arm, self) | |
188 | } | |
189 | } | |
190 | ||
191 | fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> { | |
192 | if field.is_placeholder { | |
193 | self.remove(field.id).make_fields() | |
194 | } else { | |
195 | noop_flat_map_field(field, self) | |
196 | } | |
197 | } | |
198 | ||
199 | fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> { | |
200 | if fp.is_placeholder { | |
201 | self.remove(fp.id).make_field_patterns() | |
202 | } else { | |
203 | noop_flat_map_field_pattern(fp, self) | |
204 | } | |
205 | } | |
206 | ||
207 | fn flat_map_generic_param( | |
208 | &mut self, | |
dfeec247 XL |
209 | param: ast::GenericParam, |
210 | ) -> SmallVec<[ast::GenericParam; 1]> { | |
e1599b0c XL |
211 | if param.is_placeholder { |
212 | self.remove(param.id).make_generic_params() | |
213 | } else { | |
214 | noop_flat_map_generic_param(param, self) | |
215 | } | |
216 | } | |
217 | ||
218 | fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> { | |
219 | if p.is_placeholder { | |
220 | self.remove(p.id).make_params() | |
221 | } else { | |
222 | noop_flat_map_param(p, self) | |
223 | } | |
224 | } | |
225 | ||
226 | fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> { | |
227 | if sf.is_placeholder { | |
228 | self.remove(sf.id).make_struct_fields() | |
229 | } else { | |
230 | noop_flat_map_struct_field(sf, self) | |
231 | } | |
232 | } | |
233 | ||
234 | fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { | |
235 | if variant.is_placeholder { | |
236 | self.remove(variant.id).make_variants() | |
237 | } else { | |
238 | noop_flat_map_variant(variant, self) | |
239 | } | |
240 | } | |
241 | ||
9fa01778 | 242 | fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> { |
e74abb32 | 243 | match item.kind { |
ba9703b0 | 244 | ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(), |
b7449926 | 245 | ast::ItemKind::MacroDef(_) => return smallvec![item], |
32a655c1 | 246 | _ => {} |
9e0c209e | 247 | } |
32a655c1 | 248 | |
9fa01778 | 249 | noop_flat_map_item(item, self) |
9e0c209e SL |
250 | } |
251 | ||
74b04a01 | 252 | fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> { |
e74abb32 | 253 | match item.kind { |
ba9703b0 | 254 | ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(), |
dfeec247 | 255 | _ => noop_flat_map_assoc_item(item, self), |
9e0c209e SL |
256 | } |
257 | } | |
258 | ||
74b04a01 | 259 | fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> { |
e74abb32 | 260 | match item.kind { |
ba9703b0 | 261 | ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(), |
dfeec247 | 262 | _ => noop_flat_map_assoc_item(item, self), |
9e0c209e SL |
263 | } |
264 | } | |
265 | ||
74b04a01 XL |
266 | fn flat_map_foreign_item( |
267 | &mut self, | |
268 | item: P<ast::ForeignItem>, | |
269 | ) -> SmallVec<[P<ast::ForeignItem>; 1]> { | |
e74abb32 | 270 | match item.kind { |
ba9703b0 | 271 | ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(), |
9fa01778 | 272 | _ => noop_flat_map_foreign_item(item, self), |
83c7162d XL |
273 | } |
274 | } | |
275 | ||
9fa01778 | 276 | fn visit_expr(&mut self, expr: &mut P<ast::Expr>) { |
e74abb32 | 277 | match expr.kind { |
ba9703b0 | 278 | ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(), |
9fa01778 | 279 | _ => noop_visit_expr(expr, self), |
9e0c209e SL |
280 | } |
281 | } | |
282 | ||
9fa01778 | 283 | fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> { |
e74abb32 | 284 | match expr.kind { |
ba9703b0 | 285 | ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(), |
9fa01778 | 286 | _ => noop_filter_map_expr(expr, self), |
9e0c209e SL |
287 | } |
288 | } | |
289 | ||
9fa01778 | 290 | fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { |
e74abb32 | 291 | let (style, mut stmts) = match stmt.kind { |
ba9703b0 | 292 | ast::StmtKind::MacCall(mac) => (mac.1, self.remove(stmt.id).make_stmts()), |
9fa01778 | 293 | _ => return noop_flat_map_stmt(stmt, self), |
9e0c209e SL |
294 | }; |
295 | ||
296 | if style == ast::MacStmtStyle::Semicolon { | |
8faf50e0 XL |
297 | if let Some(stmt) = stmts.pop() { |
298 | stmts.push(stmt.add_trailing_semicolon()); | |
9e0c209e SL |
299 | } |
300 | } | |
301 | ||
8faf50e0 | 302 | stmts |
9e0c209e SL |
303 | } |
304 | ||
9fa01778 | 305 | fn visit_pat(&mut self, pat: &mut P<ast::Pat>) { |
e74abb32 | 306 | match pat.kind { |
ba9703b0 | 307 | ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(), |
9fa01778 | 308 | _ => noop_visit_pat(pat, self), |
9e0c209e SL |
309 | } |
310 | } | |
311 | ||
9fa01778 | 312 | fn visit_ty(&mut self, ty: &mut P<ast::Ty>) { |
e74abb32 | 313 | match ty.kind { |
ba9703b0 | 314 | ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(), |
9fa01778 | 315 | _ => noop_visit_ty(ty, self), |
9e0c209e SL |
316 | } |
317 | } | |
318 | ||
9fa01778 XL |
319 | fn visit_block(&mut self, block: &mut P<ast::Block>) { |
320 | noop_visit_block(block, self); | |
9e0c209e | 321 | |
9fa01778 | 322 | for stmt in block.stmts.iter_mut() { |
dc9dc135 XL |
323 | if self.monotonic { |
324 | assert_eq!(stmt.id, ast::DUMMY_NODE_ID); | |
325 | stmt.id = self.cx.resolver.next_node_id(); | |
9fa01778 XL |
326 | } |
327 | } | |
9e0c209e SL |
328 | } |
329 | ||
9fa01778 XL |
330 | fn visit_mod(&mut self, module: &mut ast::Mod) { |
331 | noop_visit_mod(module, self); | |
e74abb32 | 332 | module.items.retain(|item| match item.kind { |
ba9703b0 | 333 | ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions |
9fa01778 | 334 | _ => true, |
9e0c209e | 335 | }); |
9e0c209e | 336 | } |
9e0c209e | 337 | |
ba9703b0 | 338 | fn visit_mac(&mut self, _mac: &mut ast::MacCall) { |
9fa01778 | 339 | // Do nothing. |
32a655c1 | 340 | } |
9e0c209e | 341 | } |