Attach `TokenStream` to `ast::Block`
A `Block` does not have outer attributes, so we only capture tokens when parsing a `macro_rules!` matcher
This commit is contained in:
parent
ad3a6f70ac
commit
de4bd9f0f8
|
@ -540,6 +540,7 @@ pub struct Block {
|
||||||
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
|
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
|
||||||
pub rules: BlockCheckMode,
|
pub rules: BlockCheckMode,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
pub tokens: Option<TokenStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A match pattern.
|
/// A match pattern.
|
||||||
|
|
|
@ -871,7 +871,7 @@ pub fn noop_visit_mt<T: MutVisitor>(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mu
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
|
pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
|
||||||
let Block { id, stmts, rules: _, span } = block.deref_mut();
|
let Block { id, stmts, rules: _, span, tokens: _ } = block.deref_mut();
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
|
stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
|
|
|
@ -75,6 +75,7 @@ fn call_intrinsic(
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
|
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
|
||||||
span,
|
span,
|
||||||
|
tokens: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,13 @@ impl<'a> ExtCtxt<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
|
pub fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
|
||||||
P(ast::Block { stmts, id: ast::DUMMY_NODE_ID, rules: BlockCheckMode::Default, span })
|
P(ast::Block {
|
||||||
|
stmts,
|
||||||
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
rules: BlockCheckMode::Default,
|
||||||
|
span,
|
||||||
|
tokens: None,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
|
pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
|
||||||
|
|
|
@ -693,6 +693,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> {
|
||||||
rules,
|
rules,
|
||||||
id: resolver.next_node_id(),
|
id: resolver.next_node_id(),
|
||||||
span: rustc_span::DUMMY_SP,
|
span: rustc_span::DUMMY_SP,
|
||||||
|
tokens: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
|
||||||
Nonterminal::NtItem(ref item) => {
|
Nonterminal::NtItem(ref item) => {
|
||||||
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
|
||||||
}
|
}
|
||||||
|
Nonterminal::NtBlock(ref block) => block.tokens.clone(),
|
||||||
Nonterminal::NtPat(ref pat) => pat.tokens.clone(),
|
Nonterminal::NtPat(ref pat) => pat.tokens.clone(),
|
||||||
Nonterminal::NtIdent(ident, is_raw) => {
|
Nonterminal::NtIdent(ident, is_raw) => {
|
||||||
Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
|
Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
|
||||||
|
|
|
@ -111,7 +111,14 @@ impl<'a> Parser<'a> {
|
||||||
return Err(self.struct_span_err(self.token.span, "expected an item keyword"));
|
return Err(self.struct_span_err(self.token.span, "expected an item keyword"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NonterminalKind::Block => token::NtBlock(self.parse_block()?),
|
NonterminalKind::Block => {
|
||||||
|
let (mut block, tokens) = self.collect_tokens(|this| this.parse_block())?;
|
||||||
|
// We have have eaten an NtBlock, which could already have tokens
|
||||||
|
if block.tokens.is_none() {
|
||||||
|
block.tokens = Some(tokens);
|
||||||
|
}
|
||||||
|
token::NtBlock(block)
|
||||||
|
}
|
||||||
NonterminalKind::Stmt => match self.parse_stmt()? {
|
NonterminalKind::Stmt => match self.parse_stmt()? {
|
||||||
Some(s) => token::NtStmt(s),
|
Some(s) => token::NtStmt(s),
|
||||||
None => return Err(self.struct_span_err(self.token.span, "expected a statement")),
|
None => return Err(self.struct_span_err(self.token.span, "expected a statement")),
|
||||||
|
|
|
@ -411,7 +411,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> {
|
pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> {
|
||||||
P(Block { stmts, id: DUMMY_NODE_ID, rules, span })
|
P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
|
pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
|
||||||
|
|
Loading…
Reference in New Issue