Skip to content

Syntax extensions on trait and impl items. #21052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/plugin/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use lint::{LintPassObject, LintId, Lint};
use session::Session;

use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
use syntax::ext::base::{MacroExpanderFn};
use syntax::codemap::Span;
use syntax::parse::token;
Expand Down Expand Up @@ -82,7 +82,7 @@ impl<'a> Registry<'a> {
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
Decorator(ext) => Decorator(ext),
Modifier(ext) => Modifier(ext),

MultiModifier(ext) => MultiModifier(ext),
MacroRulesTT => {
self.sess.err("plugin tried to register a new MacroRulesTT");
return;
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ pub type Mac = Spanned<Mac_>;
pub enum Mac_ {
// NB: the additional ident for a macro_rules-style macro is actually
// stored in the enclosing item. Oog.
MacInvocTT(Path, Vec<TokenTree> , SyntaxContext), // new macro-invocation
MacInvocTT(Path, Vec<TokenTree>, SyntaxContext), // new macro-invocation
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
Expand Down
106 changes: 106 additions & 0 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,108 @@ impl<F> ItemModifier for F
}
}

#[derive(Show,Clone)]
pub enum Annotatable {
Item(P<ast::Item>),
TraitItem(ast::TraitItem),
ImplItem(ast::ImplItem),
}

impl Annotatable {
pub fn attrs(&self) -> &[ast::Attribute] {
match *self {
Annotatable::Item(ref i) => &i.attrs[],
Annotatable::TraitItem(ref i) => match *i {
ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs[],
ast::TraitItem::ProvidedMethod(ref m) => &m.attrs[],
ast::TraitItem::TypeTraitItem(ref at) => &at.attrs[],
},
Annotatable::ImplItem(ref i) => match *i {
ast::ImplItem::MethodImplItem(ref m) => &m.attrs[],
ast::ImplItem::TypeImplItem(ref t) => &t.attrs[],
}
}
}

pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
match self {
Annotatable::Item(i) => Annotatable::Item(P(ast::Item {
attrs: attrs,
..(*i).clone()
})),
Annotatable::TraitItem(i) => match i {
ast::TraitItem::RequiredMethod(tm) => Annotatable::TraitItem(
ast::TraitItem::RequiredMethod(
ast::TypeMethod { attrs: attrs, ..tm })),
ast::TraitItem::ProvidedMethod(m) => Annotatable::TraitItem(
ast::TraitItem::ProvidedMethod(P(
ast::Method { attrs: attrs, ..(*m).clone() }))),
ast::TraitItem::TypeTraitItem(at) => Annotatable::TraitItem(
ast::TraitItem::TypeTraitItem(P(
ast::AssociatedType { attrs: attrs, ..(*at).clone() }))),
},
Annotatable::ImplItem(i) => match i {
ast::ImplItem::MethodImplItem(m) => Annotatable::ImplItem(
ast::ImplItem::MethodImplItem(P(
ast::Method { attrs: attrs, ..(*m).clone() }))),
ast::ImplItem::TypeImplItem(t) => Annotatable::ImplItem(
ast::ImplItem::TypeImplItem(P(
ast::Typedef { attrs: attrs, ..(*t).clone() }))),
}
}
}

pub fn expect_item(self) -> P<ast::Item> {
match self {
Annotatable::Item(i) => i,
_ => panic!("expected Item")
}
}

pub fn expect_trait_item(self) -> ast::TraitItem {
match self {
Annotatable::TraitItem(i) => i,
_ => panic!("expected Item")
}
}

pub fn expect_impl_item(self) -> ast::ImplItem {
match self {
Annotatable::ImplItem(i) => i,
_ => panic!("expected Item")
}
}
}

// A more flexible ItemModifier (ItemModifier 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.
// FIXME Decorators should follow the same pattern too.
pub trait MultiItemModifier {
fn expand(&self,
ecx: &mut ExtCtxt,
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable)
-> Annotatable;
}

impl<F> MultiItemModifier for F
where F: Fn(&mut ExtCtxt,
Span,
&ast::MetaItem,
Annotatable) -> Annotatable
{
fn expand(&self,
ecx: &mut ExtCtxt,
span: Span,
meta_item: &ast::MetaItem,
item: Annotatable)
-> Annotatable {
(*self)(ecx, span, meta_item, item)
}
}

/// Represents a thing that maps token trees to Macro Results
pub trait TTMacroExpander {
fn expand<'cx>(&self,
Expand Down Expand Up @@ -299,6 +401,10 @@ pub enum SyntaxExtension {
/// in-place.
Modifier(Box<ItemModifier + 'static>),

/// A syntax extension that is attached to an item and modifies it
/// in-place. More flexible version than Modifier.
MultiModifier(Box<MultiItemModifier + 'static>),

/// A normal, function-like syntax extension.
///
/// `bytes!` is a `NormalTT`.
Expand Down
Loading