Fix the search paths for macro-expanded non-inline modules
This commit is contained in:
parent
cccc0880d9
commit
472fcb5973
@ -552,6 +552,10 @@ pub struct ExtCtxt<'a> {
|
||||
|
||||
pub syntax_env: SyntaxEnv,
|
||||
pub recursion_count: usize,
|
||||
|
||||
pub filename: Option<String>,
|
||||
pub mod_path_stack: Vec<InternedString>,
|
||||
pub in_block: bool,
|
||||
}
|
||||
|
||||
impl<'a> ExtCtxt<'a> {
|
||||
@ -570,6 +574,10 @@ impl<'a> ExtCtxt<'a> {
|
||||
exported_macros: Vec::new(),
|
||||
syntax_env: env,
|
||||
recursion_count: 0,
|
||||
|
||||
filename: None,
|
||||
mod_path_stack: Vec::new(),
|
||||
in_block: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1183,6 +1183,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
|
||||
impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
||||
fn fold_crate(&mut self, c: Crate) -> Crate {
|
||||
self.cx.filename = Some(self.cx.parse_sess.codemap().span_to_filename(c.span));
|
||||
noop_fold_crate(c, self)
|
||||
}
|
||||
|
||||
fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
|
||||
expand_expr(expr, self)
|
||||
}
|
||||
@ -1192,7 +1197,27 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
||||
}
|
||||
|
||||
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
||||
expand_item(item, self)
|
||||
use std::mem::replace;
|
||||
let result;
|
||||
if let ast::ItemKind::Mod(ast::Mod { inner, .. }) = item.node {
|
||||
if item.span.contains(inner) {
|
||||
self.push_mod_path(item.ident, &item.attrs);
|
||||
result = expand_item(item, self);
|
||||
self.pop_mod_path();
|
||||
} else {
|
||||
let filename = if inner != codemap::DUMMY_SP {
|
||||
Some(self.cx.parse_sess.codemap().span_to_filename(inner))
|
||||
} else { None };
|
||||
let orig_filename = replace(&mut self.cx.filename, filename);
|
||||
let orig_mod_path_stack = replace(&mut self.cx.mod_path_stack, Vec::new());
|
||||
result = expand_item(item, self);
|
||||
self.cx.filename = orig_filename;
|
||||
self.cx.mod_path_stack = orig_mod_path_stack;
|
||||
}
|
||||
} else {
|
||||
result = expand_item(item, self);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
|
||||
@ -1204,7 +1229,10 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
||||
}
|
||||
|
||||
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
|
||||
expand_block(block, self)
|
||||
let was_in_block = ::std::mem::replace(&mut self.cx.in_block, true);
|
||||
let result = expand_block(block, self);
|
||||
self.cx.in_block = was_in_block;
|
||||
result
|
||||
}
|
||||
|
||||
fn fold_arm(&mut self, arm: ast::Arm) -> ast::Arm {
|
||||
@ -1230,6 +1258,21 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
fn push_mod_path(&mut self, id: Ident, attrs: &[ast::Attribute]) {
|
||||
let default_path = id.name.as_str();
|
||||
let file_path = match ::attr::first_attr_value_str_by_name(attrs, "path") {
|
||||
Some(d) => d,
|
||||
None => default_path,
|
||||
};
|
||||
self.cx.mod_path_stack.push(file_path)
|
||||
}
|
||||
|
||||
fn pop_mod_path(&mut self) {
|
||||
self.cx.mod_path_stack.pop().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
|
||||
/* this discards information in the case of macro-defining macros */
|
||||
Span {
|
||||
|
@ -16,7 +16,7 @@ use ext::tt::macro_parser::{Success, Error, Failure};
|
||||
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||
use ext::tt::macro_parser::parse;
|
||||
use parse::lexer::new_tt_reader;
|
||||
use parse::parser::Parser;
|
||||
use parse::parser::{Parser, Restrictions};
|
||||
use parse::token::{self, special_idents, gensym_ident, NtTT, Token};
|
||||
use parse::token::Token::*;
|
||||
use print;
|
||||
@ -195,6 +195,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
|
||||
imported_from,
|
||||
rhs);
|
||||
let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr));
|
||||
p.filename = cx.filename.clone();
|
||||
p.mod_path_stack = cx.mod_path_stack.clone();
|
||||
p.restrictions = match cx.in_block {
|
||||
true => Restrictions::NO_NONINLINE_MOD,
|
||||
false => Restrictions::empty(),
|
||||
};
|
||||
p.check_unknown_macro_variable();
|
||||
// Let the context choose how to interpret the result.
|
||||
// Weird, but useful for X-macros.
|
||||
|
Loading…
Reference in New Issue
Block a user