Refactor MultiModifier expansion
This commit is contained in:
@@ -13,6 +13,7 @@ use ast::{Local, Ident, Mac_, Name, SpannedIdent};
|
|||||||
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
|
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
|
||||||
use ast::TokenTree;
|
use ast::TokenTree;
|
||||||
use ast;
|
use ast;
|
||||||
|
use attr::HasAttrs;
|
||||||
use ext::mtwt;
|
use ext::mtwt;
|
||||||
use ext::build::AstBuilder;
|
use ext::build::AstBuilder;
|
||||||
use attr;
|
use attr;
|
||||||
@@ -712,11 +713,7 @@ impl<'a> Folder for PatIdentRenamer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_annotatable(a: Annotatable,
|
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
|
||||||
fld: &mut MacroExpander)
|
|
||||||
-> SmallVector<Annotatable> {
|
|
||||||
let a = expand_item_multi_modifier(a, fld);
|
|
||||||
|
|
||||||
let new_items: SmallVector<Annotatable> = match a {
|
let new_items: SmallVector<Annotatable> = match a {
|
||||||
Annotatable::Item(it) => match it.node {
|
Annotatable::Item(it) => match it.node {
|
||||||
ast::ItemKind::Mac(..) => {
|
ast::ItemKind::Mac(..) => {
|
||||||
@@ -795,29 +792,6 @@ fn decorate(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable>
|
|||||||
new_items
|
new_items
|
||||||
}
|
}
|
||||||
|
|
||||||
// Partition a set of attributes into one kind of attribute, and other kinds.
|
|
||||||
macro_rules! partition {
|
|
||||||
($fn_name: ident, $variant: ident) => {
|
|
||||||
#[allow(deprecated)] // The `allow` is needed because the `Modifier` variant might be used.
|
|
||||||
fn $fn_name(attrs: &[ast::Attribute],
|
|
||||||
fld: &MacroExpander)
|
|
||||||
-> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
|
|
||||||
attrs.iter().cloned().partition(|attr| {
|
|
||||||
match fld.cx.syntax_env.find(intern(&attr.name())) {
|
|
||||||
Some(rc) => match *rc {
|
|
||||||
$variant(..) => true,
|
|
||||||
_ => false
|
|
||||||
},
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
partition!(multi_modifiers, MultiModifier);
|
|
||||||
|
|
||||||
|
|
||||||
fn expand_decorators(a: Annotatable,
|
fn expand_decorators(a: Annotatable,
|
||||||
fld: &mut MacroExpander,
|
fld: &mut MacroExpander,
|
||||||
decorator_items: &mut SmallVector<Annotatable>,
|
decorator_items: &mut SmallVector<Annotatable>,
|
||||||
@@ -861,46 +835,41 @@ fn expand_decorators(a: Annotatable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_item_multi_modifier(mut it: Annotatable,
|
fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
|
||||||
fld: &mut MacroExpander)
|
let mut multi_modifier = None;
|
||||||
-> Annotatable {
|
item = item.map_attrs(|mut attrs| {
|
||||||
let (modifiers, other_attrs) = multi_modifiers(it.attrs(), fld);
|
for i in 0..attrs.len() {
|
||||||
|
if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) {
|
||||||
// Update the attrs, leave everything else alone. Is this mutation really a good idea?
|
if let MultiModifier(..) = *extension {
|
||||||
it = it.fold_attrs(other_attrs);
|
multi_modifier = Some((attrs.remove(i), extension));
|
||||||
|
break;
|
||||||
if modifiers.is_empty() {
|
|
||||||
return it
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attrs
|
||||||
|
});
|
||||||
|
|
||||||
for attr in &modifiers {
|
match multi_modifier {
|
||||||
let mname = intern(&attr.name());
|
None => expand_multi_modified(item, fld),
|
||||||
|
Some((attr, extension)) => match *extension {
|
||||||
match fld.cx.syntax_env.find(mname) {
|
|
||||||
Some(rc) => match *rc {
|
|
||||||
MultiModifier(ref mac) => {
|
MultiModifier(ref mac) => {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(&attr);
|
||||||
fld.cx.bt_push(ExpnInfo {
|
fld.cx.bt_push(ExpnInfo {
|
||||||
call_site: attr.span,
|
call_site: attr.span,
|
||||||
callee: NameAndSpan {
|
callee: NameAndSpan {
|
||||||
format: MacroAttribute(mname),
|
format: MacroAttribute(intern(&attr.name())),
|
||||||
span: Some(attr.span),
|
span: Some(attr.span),
|
||||||
// attributes can do whatever they like,
|
// attributes can do whatever they like, for now
|
||||||
// for now
|
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
it = mac.expand(fld.cx, attr.span, &attr.node.value, it);
|
let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item);
|
||||||
fld.cx.bt_pop();
|
fld.cx.bt_pop();
|
||||||
|
expand_annotatable(modified, fld)
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => unreachable!(),
|
||||||
},
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expansion may have added new ItemKind::Modifiers.
|
|
||||||
expand_item_multi_modifier(it, fld)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
|
fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
|
||||||
|
|||||||
Reference in New Issue
Block a user