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:
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user