1 use crate::expand
::{AstFragment, AstFragmentKind}
;
4 use rustc_ast
::mut_visit
::*;
6 use rustc_span
::source_map
::DUMMY_SP
;
7 use rustc_span
::symbol
::Ident
;
9 use smallvec
::{smallvec, SmallVec}
;
11 use rustc_data_structures
::fx
::FxHashMap
;
14 kind
: AstFragmentKind
,
16 vis
: Option
<ast
::Visibility
>,
18 fn mac_placeholder() -> ast
::MacCall
{
20 path
: ast
::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None }
,
21 args
: P(ast
::MacArgs
::Empty
),
22 prior_type_ascription
: None
,
26 let ident
= Ident
::empty();
27 let attrs
= Vec
::new();
28 let vis
= vis
.unwrap_or(ast
::Visibility
{
30 kind
: ast
::VisibilityKind
::Inherited
,
34 let expr_placeholder
= || {
38 attrs
: ast
::AttrVec
::new(),
39 kind
: ast
::ExprKind
::MacCall(mac_placeholder()),
44 || P(ast
::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None }
);
46 || P(ast
::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None }
);
49 AstFragmentKind
::Crate
=> AstFragment
::Crate(ast
::Crate
{
50 attrs
: Default
::default(),
51 items
: Default
::default(),
52 spans
: ast
::ModSpans { inner_span: span, ..Default::default() }
,
56 AstFragmentKind
::Expr
=> AstFragment
::Expr(expr_placeholder()),
57 AstFragmentKind
::OptExpr
=> AstFragment
::OptExpr(Some(expr_placeholder())),
58 AstFragmentKind
::Items
=> AstFragment
::Items(smallvec
![P(ast
::Item
{
64 kind
: ast
::ItemKind
::MacCall(mac_placeholder()),
67 AstFragmentKind
::TraitItems
=> AstFragment
::TraitItems(smallvec
![P(ast
::AssocItem
{
73 kind
: ast
::AssocItemKind
::MacCall(mac_placeholder()),
76 AstFragmentKind
::ImplItems
=> AstFragment
::ImplItems(smallvec
![P(ast
::AssocItem
{
82 kind
: ast
::AssocItemKind
::MacCall(mac_placeholder()),
85 AstFragmentKind
::ForeignItems
=> {
86 AstFragment
::ForeignItems(smallvec
![P(ast
::ForeignItem
{
92 kind
: ast
::ForeignItemKind
::MacCall(mac_placeholder()),
96 AstFragmentKind
::Pat
=> AstFragment
::Pat(P(ast
::Pat
{
99 kind
: ast
::PatKind
::MacCall(mac_placeholder()),
102 AstFragmentKind
::Ty
=> AstFragment
::Ty(P(ast
::Ty
{
105 kind
: ast
::TyKind
::MacCall(mac_placeholder()),
108 AstFragmentKind
::Stmts
=> AstFragment
::Stmts(smallvec
![{
109 let mac
= P(ast
::MacCallStmt
{
110 mac
: mac_placeholder(),
111 style
: ast
::MacStmtStyle
::Braces
,
112 attrs
: ast
::AttrVec
::new(),
115 ast
::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
117 AstFragmentKind
::Arms
=> AstFragment
::Arms(smallvec
![ast
::Arm
{
118 attrs
: Default
::default(),
119 body
: expr_placeholder(),
124 is_placeholder
: true,
126 AstFragmentKind
::ExprFields
=> AstFragment
::ExprFields(smallvec
![ast
::ExprField
{
127 attrs
: Default
::default(),
128 expr
: expr_placeholder(),
133 is_placeholder
: true,
135 AstFragmentKind
::PatFields
=> AstFragment
::PatFields(smallvec
![ast
::PatField
{
136 attrs
: Default
::default(),
142 is_placeholder
: true,
144 AstFragmentKind
::GenericParams
=> AstFragment
::GenericParams(smallvec
![{
146 attrs
: Default
::default(),
147 bounds
: Default
::default(),
150 is_placeholder
: true,
151 kind
: ast
::GenericParamKind
::Lifetime
,
155 AstFragmentKind
::Params
=> AstFragment
::Params(smallvec
![ast
::Param
{
156 attrs
: Default
::default(),
161 is_placeholder
: true,
163 AstFragmentKind
::FieldDefs
=> AstFragment
::FieldDefs(smallvec
![ast
::FieldDef
{
164 attrs
: Default
::default(),
170 is_placeholder
: true,
172 AstFragmentKind
::Variants
=> AstFragment
::Variants(smallvec
![ast
::Variant
{
173 attrs
: Default
::default(),
174 data
: ast
::VariantData
::Struct(Default
::default(), false),
180 is_placeholder
: true,
186 pub struct PlaceholderExpander
{
187 expanded_fragments
: FxHashMap
<ast
::NodeId
, AstFragment
>,
190 impl PlaceholderExpander
{
191 pub fn add(&mut self, id
: ast
::NodeId
, mut fragment
: AstFragment
) {
192 fragment
.mut_visit_with(self);
193 self.expanded_fragments
.insert(id
, fragment
);
196 fn remove(&mut self, id
: ast
::NodeId
) -> AstFragment
{
197 self.expanded_fragments
.remove(&id
).unwrap()
201 impl MutVisitor
for PlaceholderExpander
{
202 fn flat_map_arm(&mut self, arm
: ast
::Arm
) -> SmallVec
<[ast
::Arm
; 1]> {
203 if arm
.is_placeholder
{
204 self.remove(arm
.id
).make_arms()
206 noop_flat_map_arm(arm
, self)
210 fn flat_map_expr_field(&mut self, field
: ast
::ExprField
) -> SmallVec
<[ast
::ExprField
; 1]> {
211 if field
.is_placeholder
{
212 self.remove(field
.id
).make_expr_fields()
214 noop_flat_map_expr_field(field
, self)
218 fn flat_map_pat_field(&mut self, fp
: ast
::PatField
) -> SmallVec
<[ast
::PatField
; 1]> {
219 if fp
.is_placeholder
{
220 self.remove(fp
.id
).make_pat_fields()
222 noop_flat_map_pat_field(fp
, self)
226 fn flat_map_generic_param(
228 param
: ast
::GenericParam
,
229 ) -> SmallVec
<[ast
::GenericParam
; 1]> {
230 if param
.is_placeholder
{
231 self.remove(param
.id
).make_generic_params()
233 noop_flat_map_generic_param(param
, self)
237 fn flat_map_param(&mut self, p
: ast
::Param
) -> SmallVec
<[ast
::Param
; 1]> {
238 if p
.is_placeholder
{
239 self.remove(p
.id
).make_params()
241 noop_flat_map_param(p
, self)
245 fn flat_map_field_def(&mut self, sf
: ast
::FieldDef
) -> SmallVec
<[ast
::FieldDef
; 1]> {
246 if sf
.is_placeholder
{
247 self.remove(sf
.id
).make_field_defs()
249 noop_flat_map_field_def(sf
, self)
253 fn flat_map_variant(&mut self, variant
: ast
::Variant
) -> SmallVec
<[ast
::Variant
; 1]> {
254 if variant
.is_placeholder
{
255 self.remove(variant
.id
).make_variants()
257 noop_flat_map_variant(variant
, self)
261 fn flat_map_item(&mut self, item
: P
<ast
::Item
>) -> SmallVec
<[P
<ast
::Item
>; 1]> {
263 ast
::ItemKind
::MacCall(_
) => self.remove(item
.id
).make_items(),
264 _
=> noop_flat_map_item(item
, self),
268 fn flat_map_trait_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
270 ast
::AssocItemKind
::MacCall(_
) => self.remove(item
.id
).make_trait_items(),
271 _
=> noop_flat_map_assoc_item(item
, self),
275 fn flat_map_impl_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
277 ast
::AssocItemKind
::MacCall(_
) => self.remove(item
.id
).make_impl_items(),
278 _
=> noop_flat_map_assoc_item(item
, self),
282 fn flat_map_foreign_item(
284 item
: P
<ast
::ForeignItem
>,
285 ) -> SmallVec
<[P
<ast
::ForeignItem
>; 1]> {
287 ast
::ForeignItemKind
::MacCall(_
) => self.remove(item
.id
).make_foreign_items(),
288 _
=> noop_flat_map_foreign_item(item
, self),
292 fn visit_expr(&mut self, expr
: &mut P
<ast
::Expr
>) {
294 ast
::ExprKind
::MacCall(_
) => *expr
= self.remove(expr
.id
).make_expr(),
295 _
=> noop_visit_expr(expr
, self),
299 fn filter_map_expr(&mut self, expr
: P
<ast
::Expr
>) -> Option
<P
<ast
::Expr
>> {
301 ast
::ExprKind
::MacCall(_
) => self.remove(expr
.id
).make_opt_expr(),
302 _
=> noop_filter_map_expr(expr
, self),
306 fn flat_map_stmt(&mut self, stmt
: ast
::Stmt
) -> SmallVec
<[ast
::Stmt
; 1]> {
307 let (style
, mut stmts
) = match stmt
.kind
{
308 ast
::StmtKind
::MacCall(mac
) => (mac
.style
, self.remove(stmt
.id
).make_stmts()),
309 _
=> return noop_flat_map_stmt(stmt
, self),
312 if style
== ast
::MacStmtStyle
::Semicolon
{
313 // Implement the proposal described in
314 // https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449
316 // The macro invocation expands to the list of statements. If the
317 // list of statements is empty, then 'parse' the trailing semicolon
318 // on the original invocation as an empty statement. That is:
320 // `empty();` is parsed as a single `StmtKind::Empty`
322 // If the list of statements is non-empty, see if the final
323 // statement already has a trailing semicolon.
325 // If it doesn't have a semicolon, then 'parse' the trailing
326 // semicolon from the invocation as part of the final statement,
327 // using `stmt.add_trailing_semicolon()`
329 // If it does have a semicolon, then 'parse' the trailing semicolon
330 // from the invocation as a new StmtKind::Empty
332 // FIXME: We will need to preserve the original semicolon token and
333 // span as part of #15701
335 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Empty, span: DUMMY_SP }
;
337 if let Some(stmt
) = stmts
.pop() {
338 if stmt
.has_trailing_semicolon() {
340 stmts
.push(empty_stmt
);
342 stmts
.push(stmt
.add_trailing_semicolon());
345 stmts
.push(empty_stmt
);
352 fn visit_pat(&mut self, pat
: &mut P
<ast
::Pat
>) {
354 ast
::PatKind
::MacCall(_
) => *pat
= self.remove(pat
.id
).make_pat(),
355 _
=> noop_visit_pat(pat
, self),
359 fn visit_ty(&mut self, ty
: &mut P
<ast
::Ty
>) {
361 ast
::TyKind
::MacCall(_
) => *ty
= self.remove(ty
.id
).make_ty(),
362 _
=> noop_visit_ty(ty
, self),
366 fn visit_crate(&mut self, krate
: &mut ast
::Crate
) {
367 if krate
.is_placeholder
{
368 *krate
= self.remove(krate
.id
).make_crate();
370 noop_visit_crate(krate
, self)