Refactor ensure_complete_parse
.
This commit is contained in:
parent
4a8467b62d
commit
b90ceddcee
3 changed files with 31 additions and 45 deletions
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use ast::{Block, Crate, Ident, Mac_, PatKind};
|
||||
use ast::{MacStmtStyle, StmtKind, ItemKind};
|
||||
use ast::{Name, MacStmtStyle, StmtKind, ItemKind};
|
||||
use ast;
|
||||
use ext::hygiene::Mark;
|
||||
use ext::placeholders::{placeholder, PlaceholderExpander};
|
||||
|
@ -299,10 +299,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
};
|
||||
|
||||
attr::mark_used(&attr);
|
||||
let name = intern(&attr.name());
|
||||
self.cx.bt_push(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
callee: NameAndSpan {
|
||||
format: MacroAttribute(intern(&attr.name())),
|
||||
format: MacroAttribute(name),
|
||||
span: Some(attr.span),
|
||||
allow_internal_unstable: false,
|
||||
}
|
||||
|
@ -325,7 +326,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
let item_toks = TokenStream::from_tts(tts_for_item(&item, &self.cx.parse_sess));
|
||||
|
||||
let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
|
||||
self.parse_expansion(tok_result, kind, attr.span)
|
||||
self.parse_expansion(tok_result, kind, name, attr.span)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -424,7 +425,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
|
||||
let toks = TokenStream::from_tts(marked_tts);
|
||||
let tok_result = expandfun.expand(self.cx, span, toks);
|
||||
Some(self.parse_expansion(tok_result, kind, span))
|
||||
Some(self.parse_expansion(tok_result, kind, extname, span))
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -443,7 +444,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, span: Span) -> Expansion {
|
||||
fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, name: Name, span: Span)
|
||||
-> Expansion {
|
||||
let mut parser = self.cx.new_parser_from_tts(&toks.to_tts());
|
||||
let expansion = match parser.parse_expansion(kind, false) {
|
||||
Ok(expansion) => expansion,
|
||||
|
@ -452,13 +454,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
return kind.dummy(span);
|
||||
}
|
||||
};
|
||||
parser.ensure_complete_parse(kind == ExpansionKind::Expr, |parser| {
|
||||
let msg = format!("macro expansion ignores token `{}` and any following",
|
||||
parser.this_token_to_string());
|
||||
parser.diagnostic().struct_span_err(parser.span, &msg)
|
||||
.span_note(span, "caused by the macro expansion here")
|
||||
.emit();
|
||||
});
|
||||
parser.ensure_complete_parse(name, kind.name(), span);
|
||||
// FIXME better span info
|
||||
expansion.fold_with(&mut ChangeSpan { span: span })
|
||||
}
|
||||
|
|
|
@ -39,32 +39,19 @@ pub struct ParserAnyMacro<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ParserAnyMacro<'a> {
|
||||
/// Make sure we don't have any tokens left to parse, so we don't
|
||||
/// silently drop anything. `allow_semi` is so that "optional"
|
||||
/// semicolons at the end of normal expressions aren't complained
|
||||
/// about e.g. the semicolon in `macro_rules! kapow { () => {
|
||||
/// panic!(); } }` doesn't get picked up by .parse_expr(), but it's
|
||||
/// allowed to be there.
|
||||
fn ensure_complete_parse(&mut self, allow_semi: bool, context: &str) {
|
||||
let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self;
|
||||
parser.ensure_complete_parse(allow_semi, |parser| {
|
||||
let token_str = parser.this_token_to_string();
|
||||
let msg = format!("macro expansion ignores token `{}` and any \
|
||||
following",
|
||||
token_str);
|
||||
let span = parser.span;
|
||||
let mut err = parser.diagnostic().struct_span_err(span, &msg);
|
||||
let msg = format!("caused by the macro expansion here; the usage \
|
||||
of `{}!` is likely invalid in {} context",
|
||||
macro_ident, context);
|
||||
err.span_note(site_span, &msg)
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: ExpansionKind) -> Expansion {
|
||||
let expansion = panictry!(self.parser.parse_expansion(kind, true));
|
||||
self.ensure_complete_parse(kind == ExpansionKind::Expr, kind.name());
|
||||
let ParserAnyMacro { site_span, macro_ident, ref mut parser } = *self;
|
||||
let expansion = panictry!(parser.parse_expansion(kind, true));
|
||||
|
||||
// We allow semicolons at the end of expressions -- e.g. the semicolon in
|
||||
// `macro_rules! m { () => { panic!(); } }` isn't parsed by `.parse_expr()`,
|
||||
// but `m!()` is allowed in expression positions (c.f. issue #34706).
|
||||
if kind == ExpansionKind::Expr && parser.token == token::Semi {
|
||||
parser.bump();
|
||||
}
|
||||
|
||||
// Make sure we don't have any tokens left to parse so we don't silently drop anything.
|
||||
parser.ensure_complete_parse(macro_ident.name, kind.name(), site_span);
|
||||
expansion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6172,14 +6172,17 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ensure_complete_parse<F>(&mut self, allow_semi: bool, on_err: F)
|
||||
where F: FnOnce(&Parser)
|
||||
{
|
||||
if allow_semi && self.token == token::Semi {
|
||||
self.bump();
|
||||
}
|
||||
if self.token != token::Eof {
|
||||
on_err(self);
|
||||
pub fn ensure_complete_parse(&mut self, macro_name: ast::Name, kind_name: &str, span: Span) {
|
||||
if self.token == token::Eof {
|
||||
return
|
||||
}
|
||||
|
||||
let msg = format!("macro expansion ignores token `{}` and any following",
|
||||
self.this_token_to_string());
|
||||
let mut err = self.diagnostic().struct_span_err(self.span, &msg);
|
||||
let msg = format!("caused by the macro expansion here; the usage \
|
||||
of `{}!` is likely invalid in {} context",
|
||||
macro_name, kind_name);
|
||||
err.span_note(span, &msg).emit();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue