1use rustc_ast::mut_visit::*;
2use rustc_ast::ptr::P;
3use rustc_ast::token::Delimiter;
4use rustc_ast::visit::AssocCtxt;
5use rustc_ast::{self as ast, Safety};
6use rustc_data_structures::fx::FxHashMap;
7use rustc_span::{DUMMY_SP, Ident};
8use smallvec::{SmallVec, smallvec};
9use thin_vec::ThinVec;
10
11use crate::expand::{AstFragment, AstFragmentKind};
12
13pub(crate) fn placeholder(
14 kind: AstFragmentKind,
15 id: ast::NodeId,
16 vis: Option<ast::Visibility>,
17) -> AstFragment {
18 fn mac_placeholder() -> P<ast::MacCall> {
19 P(ast::MacCall {
20 path: ast::Path { span: DUMMY_SP, segments: ThinVec::new(), tokens: None },
21 args: P(ast::DelimArgs {
22 dspan: ast::tokenstream::DelimSpan::dummy(),
23 delim: Delimiter::Parenthesis,
24 tokens: ast::tokenstream::TokenStream::new(Vec::new()),
25 }),
26 })
27 }
28
29 let ident = Ident::empty();
30 let attrs = ast::AttrVec::new();
31 let vis = vis.unwrap_or(ast::Visibility {
32 span: DUMMY_SP,
33 kind: ast::VisibilityKind::Inherited,
34 tokens: None,
35 });
36 let span = DUMMY_SP;
37 let expr_placeholder = || {
38 P(ast::Expr {
39 id,
40 span,
41 attrs: ast::AttrVec::new(),
42 kind: ast::ExprKind::MacCall(mac_placeholder()),
43 tokens: None,
44 })
45 };
46 let ty =
47 || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None });
48 let pat =
49 || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
50
51 match kind {
52 AstFragmentKind::Crate => AstFragment::Crate(ast::Crate {
53 attrs: Default::default(),
54 items: Default::default(),
55 spans: ast::ModSpans { inner_span: span, ..Default::default() },
56 id,
57 is_placeholder: true,
58 }),
59 AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
60 AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
61 AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()),
62 AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
63 id,
64 span,
65 ident,
66 vis,
67 attrs,
68 kind: ast::ItemKind::MacCall(mac_placeholder()),
69 tokens: None,
70 })]),
71 AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
72 id,
73 span,
74 ident,
75 vis,
76 attrs,
77 kind: ast::AssocItemKind::MacCall(mac_placeholder()),
78 tokens: None,
79 })]),
80 AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
81 id,
82 span,
83 ident,
84 vis,
85 attrs,
86 kind: ast::AssocItemKind::MacCall(mac_placeholder()),
87 tokens: None,
88 })]),
89 AstFragmentKind::TraitImplItems => {
90 AstFragment::TraitImplItems(smallvec![P(ast::AssocItem {
91 id,
92 span,
93 ident,
94 vis,
95 attrs,
96 kind: ast::AssocItemKind::MacCall(mac_placeholder()),
97 tokens: None,
98 })])
99 }
100 AstFragmentKind::ForeignItems => {
101 AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
102 id,
103 span,
104 ident,
105 vis,
106 attrs,
107 kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
108 tokens: None,
109 })])
110 }
111 AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
112 id,
113 span,
114 kind: ast::PatKind::MacCall(mac_placeholder()),
115 tokens: None,
116 })),
117 AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
118 id,
119 span,
120 kind: ast::TyKind::MacCall(mac_placeholder()),
121 tokens: None,
122 })),
123 AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
124 let mac = P(ast::MacCallStmt {
125 mac: mac_placeholder(),
126 style: ast::MacStmtStyle::Braces,
127 attrs: ast::AttrVec::new(),
128 tokens: None,
129 });
130 ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
131 }]),
132 AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
133 attrs: Default::default(),
134 body: Some(expr_placeholder()),
135 guard: None,
136 id,
137 pat: pat(),
138 span,
139 is_placeholder: true,
140 }]),
141 AstFragmentKind::ExprFields => AstFragment::ExprFields(smallvec![ast::ExprField {
142 attrs: Default::default(),
143 expr: expr_placeholder(),
144 id,
145 ident,
146 is_shorthand: false,
147 span,
148 is_placeholder: true,
149 }]),
150 AstFragmentKind::PatFields => AstFragment::PatFields(smallvec![ast::PatField {
151 attrs: Default::default(),
152 id,
153 ident,
154 is_shorthand: false,
155 pat: pat(),
156 span,
157 is_placeholder: true,
158 }]),
159 AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
160 ast::GenericParam {
161 attrs: Default::default(),
162 bounds: Default::default(),
163 id,
164 ident,
165 is_placeholder: true,
166 kind: ast::GenericParamKind::Lifetime,
167 colon_span: None,
168 }
169 }]),
170 AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param {
171 attrs: Default::default(),
172 id,
173 pat: pat(),
174 span,
175 ty: ty(),
176 is_placeholder: true,
177 }]),
178 AstFragmentKind::FieldDefs => AstFragment::FieldDefs(smallvec![ast::FieldDef {
179 attrs: Default::default(),
180 id,
181 ident: None,
182 span,
183 ty: ty(),
184 vis,
185 is_placeholder: true,
186 safety: Safety::Default,
187 default: None,
188 }]),
189 AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
190 attrs: Default::default(),
191 data: ast::VariantData::Struct {
192 fields: Default::default(),
193 recovered: ast::Recovered::No
194 },
195 disr_expr: None,
196 id,
197 ident,
198 span,
199 vis,
200 is_placeholder: true,
201 }]),
202 AstFragmentKind::WherePredicates => {
203 AstFragment::WherePredicates(smallvec![ast::WherePredicate {
204 attrs: Default::default(),
205 id,
206 span,
207 kind: ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
208 bound_generic_params: Default::default(),
209 bounded_ty: ty(),
210 bounds: Default::default(),
211 }),
212 is_placeholder: true,
213 }])
214 }
215 }
216}
217
218#[derive(Default)]
219pub(crate) struct PlaceholderExpander {
220 expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
221}
222
223impl PlaceholderExpander {
224 pub(crate) fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
225 fragment.mut_visit_with(self);
226 self.expanded_fragments.insert(id, fragment);
227 }
228
229 fn remove(&mut self, id: ast::NodeId) -> AstFragment {
230 self.expanded_fragments.remove(&id).unwrap()
231 }
232}
233
234impl MutVisitor for PlaceholderExpander {
235 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
236 if arm.is_placeholder {
237 self.remove(arm.id).make_arms()
238 } else {
239 walk_flat_map_arm(self, arm)
240 }
241 }
242
243 fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
244 if field.is_placeholder {
245 self.remove(field.id).make_expr_fields()
246 } else {
247 walk_flat_map_expr_field(self, field)
248 }
249 }
250
251 fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
252 if fp.is_placeholder {
253 self.remove(fp.id).make_pat_fields()
254 } else {
255 walk_flat_map_pat_field(self, fp)
256 }
257 }
258
259 fn flat_map_generic_param(
260 &mut self,
261 param: ast::GenericParam,
262 ) -> SmallVec<[ast::GenericParam; 1]> {
263 if param.is_placeholder {
264 self.remove(param.id).make_generic_params()
265 } else {
266 walk_flat_map_generic_param(self, param)
267 }
268 }
269
270 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
271 if p.is_placeholder {
272 self.remove(p.id).make_params()
273 } else {
274 walk_flat_map_param(self, p)
275 }
276 }
277
278 fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
279 if sf.is_placeholder {
280 self.remove(sf.id).make_field_defs()
281 } else {
282 walk_flat_map_field_def(self, sf)
283 }
284 }
285
286 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
287 if variant.is_placeholder {
288 self.remove(variant.id).make_variants()
289 } else {
290 walk_flat_map_variant(self, variant)
291 }
292 }
293
294 fn flat_map_where_predicate(
295 &mut self,
296 predicate: ast::WherePredicate,
297 ) -> SmallVec<[ast::WherePredicate; 1]> {
298 if predicate.is_placeholder {
299 self.remove(predicate.id).make_where_predicates()
300 } else {
301 walk_flat_map_where_predicate(self, predicate)
302 }
303 }
304
305 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
306 match item.kind {
307 ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
308 _ => walk_flat_map_item(self, item),
309 }
310 }
311
312 fn flat_map_assoc_item(
313 &mut self,
314 item: P<ast::AssocItem>,
315 ctxt: AssocCtxt,
316 ) -> SmallVec<[P<ast::AssocItem>; 1]> {
317 match item.kind {
318 ast::AssocItemKind::MacCall(_) => {
319 let it = self.remove(item.id);
320 match ctxt {
321 AssocCtxt::Trait => it.make_trait_items(),
322 AssocCtxt::Impl { of_trait: false } => it.make_impl_items(),
323 AssocCtxt::Impl { of_trait: true } => it.make_trait_impl_items(),
324 }
325 }
326 _ => walk_flat_map_assoc_item(self, item, ctxt),
327 }
328 }
329
330 fn flat_map_foreign_item(
331 &mut self,
332 item: P<ast::ForeignItem>,
333 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
334 match item.kind {
335 ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
336 _ => walk_flat_map_foreign_item(self, item),
337 }
338 }
339
340 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
341 match expr.kind {
342 ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
343 _ => walk_expr(self, expr),
344 }
345 }
346
347 fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
348 match expr.kind {
349 ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(),
350 _ => walk_expr(self, expr),
351 }
352 }
353
354 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
355 match expr.kind {
356 ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
357 _ => noop_filter_map_expr(self, expr),
358 }
359 }
360
361 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
362 let (style, mut stmts) = match stmt.kind {
363 ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()),
364 _ => return walk_flat_map_stmt(self, stmt),
365 };
366
367 if style == ast::MacStmtStyle::Semicolon {
368 let empty_stmt =
390 ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Empty, span: DUMMY_SP };
391
392 if let Some(stmt) = stmts.pop() {
393 if stmt.has_trailing_semicolon() {
394 stmts.push(stmt);
395 stmts.push(empty_stmt);
396 } else {
397 stmts.push(stmt.add_trailing_semicolon());
398 }
399 } else {
400 stmts.push(empty_stmt);
401 }
402 }
403
404 stmts
405 }
406
407 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
408 match pat.kind {
409 ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
410 _ => walk_pat(self, pat),
411 }
412 }
413
414 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
415 match ty.kind {
416 ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
417 _ => walk_ty(self, ty),
418 }
419 }
420
421 fn visit_crate(&mut self, krate: &mut ast::Crate) {
422 if krate.is_placeholder {
423 *krate = self.remove(krate.id).make_crate();
424 } else {
425 walk_crate(self, krate)
426 }
427 }
428}