Merge branch 'syntax' of https://github.com/aochagavia/rust into mulit-decor
Conflicts: src/librustc/plugin/registry.rs src/libsyntax/ext/base.rs src/libsyntax/ext/cfg_attr.rs src/libsyntax/ext/deriving/mod.rs src/libsyntax/ext/expand.rs src/libsyntax/print/pprust.rs src/test/auxiliary/macro_crate_test.rs
This commit is contained in:
@@ -14,8 +14,13 @@ use lint::{LintPassObject, LintId, Lint};
|
||||
use session::Session;
|
||||
|
||||
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
||||
<<<<<<< HEAD
|
||||
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
|
||||
use syntax::ext::base::MacroExpanderFn;
|
||||
=======
|
||||
use syntax::ext::base::{IdentTT, Decorator, MultiDecorator, Modifier, MultiModifier, MacroRulesTT};
|
||||
use syntax::ext::base::{MacroExpanderFn};
|
||||
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
|
||||
use syntax::codemap::Span;
|
||||
use syntax::parse::token;
|
||||
use syntax::ptr::P;
|
||||
@@ -84,6 +89,7 @@ impl<'a> Registry<'a> {
|
||||
/// Register a syntax extension of any kind.
|
||||
///
|
||||
/// This is the most general hook into `libsyntax`'s expansion behavior.
|
||||
#[allow(deprecated)]
|
||||
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
|
||||
self.syntax_exts.push((name, match extension {
|
||||
NormalTT(ext, _, allow_internal_unstable) => {
|
||||
@@ -93,6 +99,7 @@ impl<'a> Registry<'a> {
|
||||
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
|
||||
}
|
||||
Decorator(ext) => Decorator(ext),
|
||||
MultiDecorator(ext) => MultiDecorator(ext),
|
||||
Modifier(ext) => Modifier(ext),
|
||||
MultiModifier(ext) => MultiModifier(ext),
|
||||
MacroRulesTT => {
|
||||
|
||||
@@ -30,6 +30,8 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::default::Default;
|
||||
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
|
||||
pub trait ItemDecorator {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
@@ -39,6 +41,9 @@ pub trait ItemDecorator {
|
||||
push: &mut FnMut(P<ast::Item>));
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemDecorator")]
|
||||
impl<F> ItemDecorator for F
|
||||
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, &mut FnMut(P<ast::Item>))
|
||||
{
|
||||
@@ -52,6 +57,8 @@ impl<F> ItemDecorator for F
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
|
||||
pub trait ItemModifier {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
@@ -61,9 +68,13 @@ pub trait ItemModifier {
|
||||
-> P<ast::Item>;
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiItemModifier")]
|
||||
impl<F> ItemModifier for F
|
||||
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item>
|
||||
{
|
||||
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
@@ -127,6 +138,29 @@ impl Annotatable {
|
||||
}
|
||||
}
|
||||
|
||||
// A more flexible ItemDecorator.
|
||||
pub trait MultiItemDecorator {
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: &Annotatable,
|
||||
push: Box<FnMut(Annotatable)>);
|
||||
}
|
||||
|
||||
impl<F> MultiItemDecorator for F
|
||||
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, Box<FnMut(Annotatable)>)
|
||||
{
|
||||
fn expand(&self,
|
||||
ecx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
meta_item: &ast::MetaItem,
|
||||
item: &Annotatable,
|
||||
push: Box<FnMut(Annotatable)>) {
|
||||
(*self)(ecx, sp, meta_item, item, push)
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
@@ -397,12 +431,20 @@ impl MacResult for DummyResult {
|
||||
pub enum SyntaxExtension {
|
||||
/// A syntax extension that is attached to an item and creates new items
|
||||
/// based upon it.
|
||||
///
|
||||
/// `#[derive(...)]` is an `ItemDecorator`.
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")]
|
||||
Decorator(Box<ItemDecorator + 'static>),
|
||||
|
||||
/// A syntax extension that is attached to an item and creates new items
|
||||
/// based upon it.
|
||||
///
|
||||
/// `#[derive(...)]` is a `MultiItemDecorator`.
|
||||
MultiDecorator(Box<MultiItemDecorator + 'static>),
|
||||
|
||||
/// A syntax extension that is attached to an item and modifies it
|
||||
/// in-place.
|
||||
#[unstable(feature = "rustc_private")]
|
||||
#[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")]
|
||||
Modifier(Box<ItemModifier + 'static>),
|
||||
|
||||
/// A syntax extension that is attached to an item and modifies it
|
||||
@@ -473,6 +515,13 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
|
||||
syntax_expanders.insert(intern("log_syntax"),
|
||||
builtin_normal_expander(
|
||||
ext::log_syntax::expand_syntax_ext));
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
syntax_expanders.insert(intern("derive"),
|
||||
MultiDecorator(box ext::deriving::expand_meta_derive));
|
||||
syntax_expanders.insert(intern("deriving"),
|
||||
MultiDecorator(box ext::deriving::expand_deprecated_deriving));
|
||||
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
|
||||
|
||||
ext::deriving::register_all(&mut syntax_expanders);
|
||||
|
||||
@@ -537,6 +586,11 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
|
||||
syntax_expanders.insert(intern("cfg"),
|
||||
builtin_normal_expander(
|
||||
ext::cfg::expand_cfg));
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
syntax_expanders.insert(intern("cfg_attr"),
|
||||
MultiModifier(box ext::cfg_attr::expand));
|
||||
>>>>>>> 143f2db3174103e459218958f567985b1f47944b
|
||||
syntax_expanders.insert(intern("trace_macros"),
|
||||
builtin_normal_expander(
|
||||
ext::trace_macros::expand_trace_macros));
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is
|
||||
//! the standard library, and "std" is the core library.
|
||||
|
||||
use ast::{Item, MetaItem, MetaWord};
|
||||
use ast::{Item, MetaItem, MetaWord, MetaList, MetaNameValue};
|
||||
use attr::AttrMetaMethods;
|
||||
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier};
|
||||
use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier, Annotatable};
|
||||
use ext::build::AstBuilder;
|
||||
use feature_gate;
|
||||
use codemap::Span;
|
||||
@@ -78,9 +78,19 @@ pub mod ord;
|
||||
pub mod generic;
|
||||
|
||||
fn expand_derive(cx: &mut ExtCtxt,
|
||||
_: Span,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: P<Item>) -> P<Item> {
|
||||
annotatable: &Annotatable)
|
||||
-> P<Annotatable> {
|
||||
// Derive can only be applied to items
|
||||
let item = match annotatable {
|
||||
&Annotatable::Item(ref it) => it.clone(),
|
||||
_ => {
|
||||
cx.span_err(span, "`derive` can only be applied to items");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
item.map(|mut item| {
|
||||
if mitem.value_str().is_some() {
|
||||
cx.span_err(mitem.span, "unexpected value in `derive`");
|
||||
@@ -113,7 +123,7 @@ fn expand_derive(cx: &mut ExtCtxt,
|
||||
intern_and_get_ident(&format!("derive_{}", tname)))));
|
||||
}
|
||||
|
||||
item
|
||||
Annotatable::Item(item)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -477,6 +477,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
|
||||
.into_iter().map(|i| i.expect_item()).collect()
|
||||
}
|
||||
|
||||
#[allow(deprecated)] // This is needed because the `ItemModifier` trait is used
|
||||
fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
|
||||
-> P<ast::Item> {
|
||||
// partition the attributes into ItemModifiers and others
|
||||
@@ -1082,6 +1083,7 @@ impl<'a> Folder for PatIdentRenamer<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)] // This is needed because the `Decorator` variant is used
|
||||
fn expand_annotatable(a: Annotatable,
|
||||
fld: &mut MacroExpander)
|
||||
-> SmallVector<Annotatable> {
|
||||
@@ -1120,9 +1122,31 @@ fn expand_annotatable(a: Annotatable,
|
||||
let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
|
||||
dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
|
||||
&mut |item| items.push(item));
|
||||
decorator_items.extend(
|
||||
items.into_iter()
|
||||
.flat_map(|item| expand_item(item, fld).into_iter()));
|
||||
decorator_items.extend(items.into_iter()
|
||||
.flat_map(|item| expand_item(item, fld).into_iter()
|
||||
.map(|i| Annotatable::Item(i))));
|
||||
|
||||
fld.cx.bt_pop();
|
||||
}
|
||||
MultiDecorator(ref dec) => {
|
||||
attr::mark_used(attr);
|
||||
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
callee: NameAndSpan {
|
||||
name: mname.get().to_string(),
|
||||
format: MacroAttribute,
|
||||
span: None
|
||||
}
|
||||
});
|
||||
|
||||
// we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
|
||||
// but that double-mut-borrows fld
|
||||
let mut anns: SmallVector<Annotatable> = SmallVector::zero();
|
||||
dec.expand(fld.cx, attr.span, &*attr.node.value, &a,
|
||||
&mut |ann| anns.push(ann));
|
||||
decorator_items.extend(anns.into_iter()
|
||||
.flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
|
||||
|
||||
fld.cx.bt_pop();
|
||||
}
|
||||
@@ -1184,7 +1208,7 @@ fn expand_annotatable(a: Annotatable,
|
||||
}
|
||||
};
|
||||
|
||||
new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
|
||||
new_items.push_all(decorator_items);
|
||||
new_items
|
||||
}
|
||||
|
||||
|
||||
@@ -814,7 +814,6 @@ impl<'a> State<'a> {
|
||||
word(&mut self.s, ";")
|
||||
}
|
||||
|
||||
|
||||
/// Pretty-print an item
|
||||
pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
|
||||
try!(self.hardbreak_if_not_bol());
|
||||
|
||||
@@ -19,8 +19,7 @@ extern crate rustc;
|
||||
use syntax::ast::{self, TokenTree, Item, MetaItem};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ext::base::*;
|
||||
use syntax::parse::token;
|
||||
use syntax::parse;
|
||||
use syntax::parse::{self, token};
|
||||
use syntax::ptr::P;
|
||||
use rustc::plugin::Registry;
|
||||
|
||||
@@ -42,6 +41,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
token::intern("into_multi_foo"),
|
||||
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
|
||||
MultiModifier(Box::new(expand_into_foo_multi)));
|
||||
reg.register_syntax_extension(
|
||||
token::intern("duplicate"),
|
||||
MultiDecorator(box expand_duplicate));
|
||||
}
|
||||
|
||||
fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
|
||||
@@ -104,6 +106,83 @@ fn expand_into_foo_multi(cx: &mut ExtCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
// Create a duplicate of the annotatable, based on the MetaItem
|
||||
fn expand_duplicate(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
mi: &MetaItem,
|
||||
it: &Annotatable,
|
||||
mut push: Box<FnMut(Annotatable)>)
|
||||
{
|
||||
let copy_name = match mi.node {
|
||||
ast::MetaItem_::MetaList(_, ref xs) => {
|
||||
if let ast::MetaItem_::MetaWord(ref w) = xs[0].node {
|
||||
token::str_to_ident(w.get())
|
||||
} else {
|
||||
cx.span_err(mi.span, "Expected word");
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(mi.span, "Expected list");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Duplicate the item but replace its ident by the MetaItem
|
||||
match it.clone() {
|
||||
Annotatable::Item(it) => {
|
||||
let mut new_it = (*it).clone();
|
||||
new_it.attrs.clear();
|
||||
new_it.ident = copy_name;
|
||||
push(Annotatable::Item(P(new_it)));
|
||||
}
|
||||
Annotatable::ImplItem(it) => {
|
||||
match it {
|
||||
ImplItem::MethodImplItem(m) => {
|
||||
let mut new_m = (*m).clone();
|
||||
new_m.attrs.clear();
|
||||
replace_method_name(&mut new_m.node, copy_name);
|
||||
push(Annotatable::ImplItem(ImplItem::MethodImplItem(P(new_m))));
|
||||
}
|
||||
ImplItem::TypeImplItem(t) => {
|
||||
let mut new_t = (*t).clone();
|
||||
new_t.attrs.clear();
|
||||
new_t.ident = copy_name;
|
||||
push(Annotatable::ImplItem(ImplItem::TypeImplItem(P(new_t))));
|
||||
}
|
||||
}
|
||||
}
|
||||
Annotatable::TraitItem(it) => {
|
||||
match it {
|
||||
TraitItem::RequiredMethod(rm) => {
|
||||
let mut new_rm = rm.clone();
|
||||
new_rm.attrs.clear();
|
||||
new_rm.ident = copy_name;
|
||||
push(Annotatable::TraitItem(TraitItem::RequiredMethod(new_rm)));
|
||||
}
|
||||
TraitItem::ProvidedMethod(pm) => {
|
||||
let mut new_pm = (*pm).clone();
|
||||
new_pm.attrs.clear();
|
||||
replace_method_name(&mut new_pm.node, copy_name);
|
||||
push(Annotatable::TraitItem(TraitItem::ProvidedMethod(P(new_pm))));
|
||||
}
|
||||
TraitItem::TypeTraitItem(t) => {
|
||||
let mut new_t = (*t).clone();
|
||||
new_t.attrs.clear();
|
||||
new_t.ty_param.ident = copy_name;
|
||||
push(Annotatable::TraitItem(TraitItem::TypeTraitItem(P(new_t))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_method_name(m: &mut ast::Method_, i: ast::Ident) {
|
||||
if let &mut ast::Method_::MethDecl(ref mut ident, _, _, _, _, _, _, _) = m {
|
||||
*ident = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult+'static> {
|
||||
use syntax::ext::quote::rt::*;
|
||||
|
||||
|
||||
52
src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs
Normal file
52
src/test/run-pass-fulldeps/macro-crate-multi-decorator.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
|
||||
#![feature(plugin)]
|
||||
|
||||
#[plugin] #[no_link]
|
||||
extern crate macro_crate_test;
|
||||
|
||||
// The duplicate macro will create a copy of the item with the given identifier
|
||||
#[duplicate(MyCopy)]
|
||||
struct MyStruct {
|
||||
number: i32
|
||||
}
|
||||
|
||||
trait TestTrait {
|
||||
#[duplicate(TestType2)]
|
||||
type TestType;
|
||||
|
||||
#[duplicate(required_fn2)]
|
||||
fn required_fn(&self);
|
||||
|
||||
#[duplicate(provided_fn2)]
|
||||
fn provided_fn(&self) { }
|
||||
}
|
||||
|
||||
impl TestTrait for MyStruct {
|
||||
#[duplicate(TestType2)]
|
||||
type TestType = f64;
|
||||
|
||||
#[duplicate(required_fn2)]
|
||||
fn required_fn(&self) { }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = MyStruct { number: 42 };
|
||||
s.required_fn();
|
||||
s.required_fn2();
|
||||
s.provided_fn();
|
||||
s.provided_fn2();
|
||||
|
||||
let s = MyCopy { number: 42 };
|
||||
}
|
||||
Reference in New Issue
Block a user