• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::expand::{AstFragment, AstFragmentKind};
2 use rustc_ast as ast;
3 use rustc_ast::mut_visit::*;
4 use rustc_ast::ptr::P;
5 use rustc_data_structures::fx::FxHashMap;
6 use rustc_span::source_map::DUMMY_SP;
7 use rustc_span::symbol::Ident;
8 use smallvec::{smallvec, SmallVec};
9 use thin_vec::ThinVec;
10 
placeholder( kind: AstFragmentKind, id: ast::NodeId, vis: Option<ast::Visibility>, ) -> AstFragment11 pub fn placeholder(
12     kind: AstFragmentKind,
13     id: ast::NodeId,
14     vis: Option<ast::Visibility>,
15 ) -> AstFragment {
16     fn mac_placeholder() -> P<ast::MacCall> {
17         P(ast::MacCall {
18             path: ast::Path { span: DUMMY_SP, segments: ThinVec::new(), tokens: None },
19             args: P(ast::DelimArgs {
20                 dspan: ast::tokenstream::DelimSpan::dummy(),
21                 delim: ast::MacDelimiter::Parenthesis,
22                 tokens: ast::tokenstream::TokenStream::new(Vec::new()),
23             }),
24         })
25     }
26 
27     let ident = Ident::empty();
28     let attrs = ast::AttrVec::new();
29     let vis = vis.unwrap_or(ast::Visibility {
30         span: DUMMY_SP,
31         kind: ast::VisibilityKind::Inherited,
32         tokens: None,
33     });
34     let span = DUMMY_SP;
35     let expr_placeholder = || {
36         P(ast::Expr {
37             id,
38             span,
39             attrs: ast::AttrVec::new(),
40             kind: ast::ExprKind::MacCall(mac_placeholder()),
41             tokens: None,
42         })
43     };
44     let ty =
45         || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None });
46     let pat =
47         || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
48 
49     match kind {
50         AstFragmentKind::Crate => AstFragment::Crate(ast::Crate {
51             attrs: Default::default(),
52             items: Default::default(),
53             spans: ast::ModSpans { inner_span: span, ..Default::default() },
54             id,
55             is_placeholder: true,
56         }),
57         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
58         AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
59         AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()),
60         AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
61             id,
62             span,
63             ident,
64             vis,
65             attrs,
66             kind: ast::ItemKind::MacCall(mac_placeholder()),
67             tokens: None,
68         })]),
69         AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
70             id,
71             span,
72             ident,
73             vis,
74             attrs,
75             kind: ast::AssocItemKind::MacCall(mac_placeholder()),
76             tokens: None,
77         })]),
78         AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
79             id,
80             span,
81             ident,
82             vis,
83             attrs,
84             kind: ast::AssocItemKind::MacCall(mac_placeholder()),
85             tokens: None,
86         })]),
87         AstFragmentKind::ForeignItems => {
88             AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
89                 id,
90                 span,
91                 ident,
92                 vis,
93                 attrs,
94                 kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
95                 tokens: None,
96             })])
97         }
98         AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
99             id,
100             span,
101             kind: ast::PatKind::MacCall(mac_placeholder()),
102             tokens: None,
103         })),
104         AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
105             id,
106             span,
107             kind: ast::TyKind::MacCall(mac_placeholder()),
108             tokens: None,
109         })),
110         AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
111             let mac = P(ast::MacCallStmt {
112                 mac: mac_placeholder(),
113                 style: ast::MacStmtStyle::Braces,
114                 attrs: ast::AttrVec::new(),
115                 tokens: None,
116             });
117             ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
118         }]),
119         AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
120             attrs: Default::default(),
121             body: expr_placeholder(),
122             guard: None,
123             id,
124             pat: pat(),
125             span,
126             is_placeholder: true,
127         }]),
128         AstFragmentKind::ExprFields => AstFragment::ExprFields(smallvec![ast::ExprField {
129             attrs: Default::default(),
130             expr: expr_placeholder(),
131             id,
132             ident,
133             is_shorthand: false,
134             span,
135             is_placeholder: true,
136         }]),
137         AstFragmentKind::PatFields => AstFragment::PatFields(smallvec![ast::PatField {
138             attrs: Default::default(),
139             id,
140             ident,
141             is_shorthand: false,
142             pat: pat(),
143             span,
144             is_placeholder: true,
145         }]),
146         AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
147             ast::GenericParam {
148                 attrs: Default::default(),
149                 bounds: Default::default(),
150                 id,
151                 ident,
152                 is_placeholder: true,
153                 kind: ast::GenericParamKind::Lifetime,
154                 colon_span: None,
155             }
156         }]),
157         AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param {
158             attrs: Default::default(),
159             id,
160             pat: pat(),
161             span,
162             ty: ty(),
163             is_placeholder: true,
164         }]),
165         AstFragmentKind::FieldDefs => AstFragment::FieldDefs(smallvec![ast::FieldDef {
166             attrs: Default::default(),
167             id,
168             ident: None,
169             span,
170             ty: ty(),
171             vis,
172             is_placeholder: true,
173         }]),
174         AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
175             attrs: Default::default(),
176             data: ast::VariantData::Struct(Default::default(), false),
177             disr_expr: None,
178             id,
179             ident,
180             span,
181             vis,
182             is_placeholder: true,
183         }]),
184     }
185 }
186 
187 #[derive(Default)]
188 pub struct PlaceholderExpander {
189     expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
190 }
191 
192 impl PlaceholderExpander {
add(&mut self, id: ast::NodeId, mut fragment: AstFragment)193     pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
194         fragment.mut_visit_with(self);
195         self.expanded_fragments.insert(id, fragment);
196     }
197 
remove(&mut self, id: ast::NodeId) -> AstFragment198     fn remove(&mut self, id: ast::NodeId) -> AstFragment {
199         self.expanded_fragments.remove(&id).unwrap()
200     }
201 }
202 
203 impl MutVisitor for PlaceholderExpander {
flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]>204     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
205         if arm.is_placeholder {
206             self.remove(arm.id).make_arms()
207         } else {
208             noop_flat_map_arm(arm, self)
209         }
210     }
211 
flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]>212     fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
213         if field.is_placeholder {
214             self.remove(field.id).make_expr_fields()
215         } else {
216             noop_flat_map_expr_field(field, self)
217         }
218     }
219 
flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]>220     fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
221         if fp.is_placeholder {
222             self.remove(fp.id).make_pat_fields()
223         } else {
224             noop_flat_map_pat_field(fp, self)
225         }
226     }
227 
flat_map_generic_param( &mut self, param: ast::GenericParam, ) -> SmallVec<[ast::GenericParam; 1]>228     fn flat_map_generic_param(
229         &mut self,
230         param: ast::GenericParam,
231     ) -> SmallVec<[ast::GenericParam; 1]> {
232         if param.is_placeholder {
233             self.remove(param.id).make_generic_params()
234         } else {
235             noop_flat_map_generic_param(param, self)
236         }
237     }
238 
flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]>239     fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
240         if p.is_placeholder {
241             self.remove(p.id).make_params()
242         } else {
243             noop_flat_map_param(p, self)
244         }
245     }
246 
flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]>247     fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
248         if sf.is_placeholder {
249             self.remove(sf.id).make_field_defs()
250         } else {
251             noop_flat_map_field_def(sf, self)
252         }
253     }
254 
flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]>255     fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
256         if variant.is_placeholder {
257             self.remove(variant.id).make_variants()
258         } else {
259             noop_flat_map_variant(variant, self)
260         }
261     }
262 
flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]>263     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
264         match item.kind {
265             ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
266             _ => noop_flat_map_item(item, self),
267         }
268     }
269 
flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]>270     fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
271         match item.kind {
272             ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
273             _ => noop_flat_map_assoc_item(item, self),
274         }
275     }
276 
flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]>277     fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
278         match item.kind {
279             ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
280             _ => noop_flat_map_assoc_item(item, self),
281         }
282     }
283 
flat_map_foreign_item( &mut self, item: P<ast::ForeignItem>, ) -> SmallVec<[P<ast::ForeignItem>; 1]>284     fn flat_map_foreign_item(
285         &mut self,
286         item: P<ast::ForeignItem>,
287     ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
288         match item.kind {
289             ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
290             _ => noop_flat_map_foreign_item(item, self),
291         }
292     }
293 
visit_expr(&mut self, expr: &mut P<ast::Expr>)294     fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
295         match expr.kind {
296             ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
297             _ => noop_visit_expr(expr, self),
298         }
299     }
300 
visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>)301     fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
302         match expr.kind {
303             ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(),
304             _ => noop_visit_expr(expr, self),
305         }
306     }
307 
filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>>308     fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
309         match expr.kind {
310             ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
311             _ => noop_filter_map_expr(expr, self),
312         }
313     }
314 
flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]>315     fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
316         let (style, mut stmts) = match stmt.kind {
317             ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()),
318             _ => return noop_flat_map_stmt(stmt, self),
319         };
320 
321         if style == ast::MacStmtStyle::Semicolon {
322             // Implement the proposal described in
323             // https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449
324             //
325             // The macro invocation expands to the list of statements. If the
326             // list of statements is empty, then 'parse' the trailing semicolon
327             // on the original invocation as an empty statement. That is:
328             //
329             // `empty();` is parsed as a single `StmtKind::Empty`
330             //
331             // If the list of statements is non-empty, see if the final
332             // statement already has a trailing semicolon.
333             //
334             // If it doesn't have a semicolon, then 'parse' the trailing
335             // semicolon from the invocation as part of the final statement,
336             // using `stmt.add_trailing_semicolon()`
337             //
338             // If it does have a semicolon, then 'parse' the trailing semicolon
339             // from the invocation as a new StmtKind::Empty
340 
341             // FIXME: We will need to preserve the original semicolon token and
342             // span as part of #15701
343             let empty_stmt =
344                 ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Empty, span: DUMMY_SP };
345 
346             if let Some(stmt) = stmts.pop() {
347                 if stmt.has_trailing_semicolon() {
348                     stmts.push(stmt);
349                     stmts.push(empty_stmt);
350                 } else {
351                     stmts.push(stmt.add_trailing_semicolon());
352                 }
353             } else {
354                 stmts.push(empty_stmt);
355             }
356         }
357 
358         stmts
359     }
360 
visit_pat(&mut self, pat: &mut P<ast::Pat>)361     fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
362         match pat.kind {
363             ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
364             _ => noop_visit_pat(pat, self),
365         }
366     }
367 
visit_ty(&mut self, ty: &mut P<ast::Ty>)368     fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
369         match ty.kind {
370             ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
371             _ => noop_visit_ty(ty, self),
372         }
373     }
374 
visit_crate(&mut self, krate: &mut ast::Crate)375     fn visit_crate(&mut self, krate: &mut ast::Crate) {
376         if krate.is_placeholder {
377             *krate = self.remove(krate.id).make_crate();
378         } else {
379             noop_visit_crate(krate, self)
380         }
381     }
382 }
383