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
,
154 AstFragmentKind
::Params
=> AstFragment
::Params(smallvec
![ast
::Param
{
155 attrs
: Default
::default(),
160 is_placeholder
: true,
162 AstFragmentKind
::FieldDefs
=> AstFragment
::FieldDefs(smallvec
![ast
::FieldDef
{
163 attrs
: Default
::default(),
169 is_placeholder
: true,
171 AstFragmentKind
::Variants
=> AstFragment
::Variants(smallvec
![ast
::Variant
{
172 attrs
: Default
::default(),
173 data
: ast
::VariantData
::Struct(Default
::default(), false),
179 is_placeholder
: true,
185 pub struct PlaceholderExpander
{
186 expanded_fragments
: FxHashMap
<ast
::NodeId
, AstFragment
>,
189 impl PlaceholderExpander
{
190 pub fn add(&mut self, id
: ast
::NodeId
, mut fragment
: AstFragment
) {
191 fragment
.mut_visit_with(self);
192 self.expanded_fragments
.insert(id
, fragment
);
195 fn remove(&mut self, id
: ast
::NodeId
) -> AstFragment
{
196 self.expanded_fragments
.remove(&id
).unwrap()
200 impl MutVisitor
for PlaceholderExpander
{
201 fn flat_map_arm(&mut self, arm
: ast
::Arm
) -> SmallVec
<[ast
::Arm
; 1]> {
202 if arm
.is_placeholder
{
203 self.remove(arm
.id
).make_arms()
205 noop_flat_map_arm(arm
, self)
209 fn flat_map_expr_field(&mut self, field
: ast
::ExprField
) -> SmallVec
<[ast
::ExprField
; 1]> {
210 if field
.is_placeholder
{
211 self.remove(field
.id
).make_expr_fields()
213 noop_flat_map_expr_field(field
, self)
217 fn flat_map_pat_field(&mut self, fp
: ast
::PatField
) -> SmallVec
<[ast
::PatField
; 1]> {
218 if fp
.is_placeholder
{
219 self.remove(fp
.id
).make_pat_fields()
221 noop_flat_map_pat_field(fp
, self)
225 fn flat_map_generic_param(
227 param
: ast
::GenericParam
,
228 ) -> SmallVec
<[ast
::GenericParam
; 1]> {
229 if param
.is_placeholder
{
230 self.remove(param
.id
).make_generic_params()
232 noop_flat_map_generic_param(param
, self)
236 fn flat_map_param(&mut self, p
: ast
::Param
) -> SmallVec
<[ast
::Param
; 1]> {
237 if p
.is_placeholder
{
238 self.remove(p
.id
).make_params()
240 noop_flat_map_param(p
, self)
244 fn flat_map_field_def(&mut self, sf
: ast
::FieldDef
) -> SmallVec
<[ast
::FieldDef
; 1]> {
245 if sf
.is_placeholder
{
246 self.remove(sf
.id
).make_field_defs()
248 noop_flat_map_field_def(sf
, self)
252 fn flat_map_variant(&mut self, variant
: ast
::Variant
) -> SmallVec
<[ast
::Variant
; 1]> {
253 if variant
.is_placeholder
{
254 self.remove(variant
.id
).make_variants()
256 noop_flat_map_variant(variant
, self)
260 fn flat_map_item(&mut self, item
: P
<ast
::Item
>) -> SmallVec
<[P
<ast
::Item
>; 1]> {
262 ast
::ItemKind
::MacCall(_
) => self.remove(item
.id
).make_items(),
263 _
=> noop_flat_map_item(item
, self),
267 fn flat_map_trait_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
269 ast
::AssocItemKind
::MacCall(_
) => self.remove(item
.id
).make_trait_items(),
270 _
=> noop_flat_map_assoc_item(item
, self),
274 fn flat_map_impl_item(&mut self, item
: P
<ast
::AssocItem
>) -> SmallVec
<[P
<ast
::AssocItem
>; 1]> {
276 ast
::AssocItemKind
::MacCall(_
) => self.remove(item
.id
).make_impl_items(),
277 _
=> noop_flat_map_assoc_item(item
, self),
281 fn flat_map_foreign_item(
283 item
: P
<ast
::ForeignItem
>,
284 ) -> SmallVec
<[P
<ast
::ForeignItem
>; 1]> {
286 ast
::ForeignItemKind
::MacCall(_
) => self.remove(item
.id
).make_foreign_items(),
287 _
=> noop_flat_map_foreign_item(item
, self),
291 fn visit_expr(&mut self, expr
: &mut P
<ast
::Expr
>) {
293 ast
::ExprKind
::MacCall(_
) => *expr
= self.remove(expr
.id
).make_expr(),
294 _
=> noop_visit_expr(expr
, self),
298 fn filter_map_expr(&mut self, expr
: P
<ast
::Expr
>) -> Option
<P
<ast
::Expr
>> {
300 ast
::ExprKind
::MacCall(_
) => self.remove(expr
.id
).make_opt_expr(),
301 _
=> noop_filter_map_expr(expr
, self),
305 fn flat_map_stmt(&mut self, stmt
: ast
::Stmt
) -> SmallVec
<[ast
::Stmt
; 1]> {
306 let (style
, mut stmts
) = match stmt
.kind
{
307 ast
::StmtKind
::MacCall(mac
) => (mac
.style
, self.remove(stmt
.id
).make_stmts()),
308 _
=> return noop_flat_map_stmt(stmt
, self),
311 if style
== ast
::MacStmtStyle
::Semicolon
{
312 // Implement the proposal described in
313 // https://github.com/rust-lang/rust/issues/61733#issuecomment-509626449
315 // The macro invocation expands to the list of statements. If the
316 // list of statements is empty, then 'parse' the trailing semicolon
317 // on the original invocation as an empty statement. That is:
319 // `empty();` is parsed as a single `StmtKind::Empty`
321 // If the list of statements is non-empty, see if the final
322 // statement already has a trailing semicolon.
324 // If it doesn't have a semicolon, then 'parse' the trailing
325 // semicolon from the invocation as part of the final statement,
326 // using `stmt.add_trailing_semicolon()`
328 // If it does have a semicolon, then 'parse' the trailing semicolon
329 // from the invocation as a new StmtKind::Empty
331 // FIXME: We will need to preserve the original semicolon token and
332 // span as part of #15701
334 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Empty, span: DUMMY_SP }
;
336 if let Some(stmt
) = stmts
.pop() {
337 if stmt
.has_trailing_semicolon() {
339 stmts
.push(empty_stmt
);
341 stmts
.push(stmt
.add_trailing_semicolon());
344 stmts
.push(empty_stmt
);
351 fn visit_pat(&mut self, pat
: &mut P
<ast
::Pat
>) {
353 ast
::PatKind
::MacCall(_
) => *pat
= self.remove(pat
.id
).make_pat(),
354 _
=> noop_visit_pat(pat
, self),
358 fn visit_ty(&mut self, ty
: &mut P
<ast
::Ty
>) {
360 ast
::TyKind
::MacCall(_
) => *ty
= self.remove(ty
.id
).make_ty(),
361 _
=> noop_visit_ty(ty
, self),
365 fn visit_crate(&mut self, krate
: &mut ast
::Crate
) {
366 if krate
.is_placeholder
{
367 *krate
= self.remove(krate
.id
).make_crate();
369 noop_visit_crate(krate
, self)