Auto merge of #34253 - jseyfried:improve_multi_modifiers, r=nrc

Allow `MultiItemModifier`s to expand into zero or many items

Fixes #34223.
r? @nrc
This commit is contained in:
bors
2016-06-23 01:04:47 -07:00
committed by GitHub
4 changed files with 77 additions and 100 deletions

View File

@@ -12,6 +12,7 @@ pub use self::SyntaxExtension::*;
use ast;
use ast::{Name, PatKind};
use attr::HasAttrs;
use codemap;
use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
use errors::DiagnosticBuilder;
@@ -40,29 +41,31 @@ pub enum Annotatable {
ImplItem(P<ast::ImplItem>),
}
impl Annotatable {
pub fn attrs(&self) -> &[ast::Attribute] {
impl HasAttrs for Annotatable {
fn attrs(&self) -> &[ast::Attribute] {
match *self {
Annotatable::Item(ref i) => &i.attrs,
Annotatable::TraitItem(ref ti) => &ti.attrs,
Annotatable::ImplItem(ref ii) => &ii.attrs,
Annotatable::Item(ref item) => &item.attrs,
Annotatable::TraitItem(ref trait_item) => &trait_item.attrs,
Annotatable::ImplItem(ref impl_item) => &impl_item.attrs,
}
}
pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self {
match self {
Annotatable::Item(i) => Annotatable::Item(i.map(|i| ast::Item {
attrs: attrs,
..i
})),
Annotatable::TraitItem(i) => Annotatable::TraitItem(i.map(|ti| {
ast::TraitItem { attrs: attrs, ..ti }
})),
Annotatable::ImplItem(i) => Annotatable::ImplItem(i.map(|ii| {
ast::ImplItem { attrs: attrs, ..ii }
})),
Annotatable::Item(item) => Annotatable::Item(item.map_attrs(f)),
Annotatable::TraitItem(trait_item) => Annotatable::TraitItem(trait_item.map_attrs(f)),
Annotatable::ImplItem(impl_item) => Annotatable::ImplItem(impl_item.map_attrs(f)),
}
}
}
impl Annotatable {
pub fn attrs(&self) -> &[ast::Attribute] {
HasAttrs::attrs(self)
}
pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
self.map_attrs(|_| attrs)
}
pub fn expect_item(self) -> P<ast::Item> {
match self {
@@ -129,9 +132,7 @@ impl<F> MultiItemDecorator for F
}
}
// A more flexible ItemKind::Modifier (ItemKind::Modifier should go away, eventually, FIXME).
// meta_item is the annotation, item is the item being modified, parent_item
// is the impl or trait item is declared in if item is part of such a thing.
// `meta_item` is the annotation, and `item` is the item being modified.
// FIXME Decorators should follow the same pattern too.
pub trait MultiItemModifier {
fn expand(&self,
@@ -139,22 +140,26 @@ pub trait MultiItemModifier {
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable)
-> Annotatable;
-> Vec<Annotatable>;
}
impl<F> MultiItemModifier for F
where F: Fn(&mut ExtCtxt,
Span,
&ast::MetaItem,
Annotatable) -> Annotatable
impl<F, T> MultiItemModifier for F
where F: Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable) -> T,
T: Into<Vec<Annotatable>>,
{
fn expand(&self,
ecx: &mut ExtCtxt,
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable)
-> Annotatable {
(*self)(ecx, span, meta_item, item)
-> Vec<Annotatable> {
(*self)(ecx, span, meta_item, item).into()
}
}
impl Into<Vec<Annotatable>> for Annotatable {
fn into(self) -> Vec<Annotatable> {
vec![self]
}
}