Skip to content

Commit 8903c21

Browse files
committed
auto merge of #21052 : nick29581/rust/methods-ext, r=sfackler
Allows modifiers to be used on methods, associated types, etc. r? @sfackler
2 parents 9ade482 + 98d4711 commit 8903c21

File tree

7 files changed

+419
-121
lines changed

7 files changed

+419
-121
lines changed

src/librustc/plugin/registry.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use lint::{LintPassObject, LintId, Lint};
1414
use session::Session;
1515

1616
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
17-
use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
17+
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
1818
use syntax::ext::base::{MacroExpanderFn};
1919
use syntax::codemap::Span;
2020
use syntax::parse::token;
@@ -82,7 +82,7 @@ impl<'a> Registry<'a> {
8282
IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
8383
Decorator(ext) => Decorator(ext),
8484
Modifier(ext) => Modifier(ext),
85-
85+
MultiModifier(ext) => MultiModifier(ext),
8686
MacroRulesTT => {
8787
self.sess.err("plugin tried to register a new MacroRulesTT");
8888
return;

src/libsyntax/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,7 @@ pub type Mac = Spanned<Mac_>;
957957
pub enum Mac_ {
958958
// NB: the additional ident for a macro_rules-style macro is actually
959959
// stored in the enclosing item. Oog.
960-
MacInvocTT(Path, Vec<TokenTree> , SyntaxContext), // new macro-invocation
960+
MacInvocTT(Path, Vec<TokenTree>, SyntaxContext), // new macro-invocation
961961
}
962962

963963
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]

src/libsyntax/ext/base.rs

+106
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,108 @@ impl<F> ItemModifier for F
7373
}
7474
}
7575

76+
#[derive(Show,Clone)]
77+
pub enum Annotatable {
78+
Item(P<ast::Item>),
79+
TraitItem(ast::TraitItem),
80+
ImplItem(ast::ImplItem),
81+
}
82+
83+
impl Annotatable {
84+
pub fn attrs(&self) -> &[ast::Attribute] {
85+
match *self {
86+
Annotatable::Item(ref i) => &i.attrs[],
87+
Annotatable::TraitItem(ref i) => match *i {
88+
ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs[],
89+
ast::TraitItem::ProvidedMethod(ref m) => &m.attrs[],
90+
ast::TraitItem::TypeTraitItem(ref at) => &at.attrs[],
91+
},
92+
Annotatable::ImplItem(ref i) => match *i {
93+
ast::ImplItem::MethodImplItem(ref m) => &m.attrs[],
94+
ast::ImplItem::TypeImplItem(ref t) => &t.attrs[],
95+
}
96+
}
97+
}
98+
99+
pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
100+
match self {
101+
Annotatable::Item(i) => Annotatable::Item(P(ast::Item {
102+
attrs: attrs,
103+
..(*i).clone()
104+
})),
105+
Annotatable::TraitItem(i) => match i {
106+
ast::TraitItem::RequiredMethod(tm) => Annotatable::TraitItem(
107+
ast::TraitItem::RequiredMethod(
108+
ast::TypeMethod { attrs: attrs, ..tm })),
109+
ast::TraitItem::ProvidedMethod(m) => Annotatable::TraitItem(
110+
ast::TraitItem::ProvidedMethod(P(
111+
ast::Method { attrs: attrs, ..(*m).clone() }))),
112+
ast::TraitItem::TypeTraitItem(at) => Annotatable::TraitItem(
113+
ast::TraitItem::TypeTraitItem(P(
114+
ast::AssociatedType { attrs: attrs, ..(*at).clone() }))),
115+
},
116+
Annotatable::ImplItem(i) => match i {
117+
ast::ImplItem::MethodImplItem(m) => Annotatable::ImplItem(
118+
ast::ImplItem::MethodImplItem(P(
119+
ast::Method { attrs: attrs, ..(*m).clone() }))),
120+
ast::ImplItem::TypeImplItem(t) => Annotatable::ImplItem(
121+
ast::ImplItem::TypeImplItem(P(
122+
ast::Typedef { attrs: attrs, ..(*t).clone() }))),
123+
}
124+
}
125+
}
126+
127+
pub fn expect_item(self) -> P<ast::Item> {
128+
match self {
129+
Annotatable::Item(i) => i,
130+
_ => panic!("expected Item")
131+
}
132+
}
133+
134+
pub fn expect_trait_item(self) -> ast::TraitItem {
135+
match self {
136+
Annotatable::TraitItem(i) => i,
137+
_ => panic!("expected Item")
138+
}
139+
}
140+
141+
pub fn expect_impl_item(self) -> ast::ImplItem {
142+
match self {
143+
Annotatable::ImplItem(i) => i,
144+
_ => panic!("expected Item")
145+
}
146+
}
147+
}
148+
149+
// A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
150+
// meta_item is the annotation, item is the item being modified, parent_item
151+
// is the impl or trait item is declared in if item is part of such a thing.
152+
// FIXME Decorators should follow the same pattern too.
153+
pub trait MultiItemModifier {
154+
fn expand(&self,
155+
ecx: &mut ExtCtxt,
156+
span: Span,
157+
meta_item: &ast::MetaItem,
158+
item: Annotatable)
159+
-> Annotatable;
160+
}
161+
162+
impl<F> MultiItemModifier for F
163+
where F: Fn(&mut ExtCtxt,
164+
Span,
165+
&ast::MetaItem,
166+
Annotatable) -> Annotatable
167+
{
168+
fn expand(&self,
169+
ecx: &mut ExtCtxt,
170+
span: Span,
171+
meta_item: &ast::MetaItem,
172+
item: Annotatable)
173+
-> Annotatable {
174+
(*self)(ecx, span, meta_item, item)
175+
}
176+
}
177+
76178
/// Represents a thing that maps token trees to Macro Results
77179
pub trait TTMacroExpander {
78180
fn expand<'cx>(&self,
@@ -299,6 +401,10 @@ pub enum SyntaxExtension {
299401
/// in-place.
300402
Modifier(Box<ItemModifier + 'static>),
301403

404+
/// A syntax extension that is attached to an item and modifies it
405+
/// in-place. More flexible version than Modifier.
406+
MultiModifier(Box<MultiItemModifier + 'static>),
407+
302408
/// A normal, function-like syntax extension.
303409
///
304410
/// `bytes!` is a `NormalTT`.

0 commit comments

Comments
 (0)