]> git.lizzy.rs Git - rust.git/commitdiff
WIP refactor expansion of decorators and move derive to MultiDecorator
authorNick Cameron <ncameron@mozilla.com>
Tue, 28 Apr 2015 05:34:39 +0000 (17:34 +1200)
committerNick Cameron <ncameron@mozilla.com>
Thu, 30 Apr 2015 08:29:45 +0000 (20:29 +1200)
16 files changed:
src/libsyntax/ext/base.rs
src/libsyntax/ext/deriving/bounds.rs
src/libsyntax/ext/deriving/clone.rs
src/libsyntax/ext/deriving/cmp/eq.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/libsyntax/ext/deriving/cmp/partial_eq.rs
src/libsyntax/ext/deriving/cmp/partial_ord.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/default.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/hash.rs
src/libsyntax/ext/deriving/mod.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/deriving/show.rs
src/libsyntax/ext/expand.rs

index 3e54e43c0296144641bb42dc2111d6d70a4897bd..2ecefef51045e85885f27f8f1a5dd9a1c276c269 100644 (file)
@@ -123,6 +123,16 @@ pub fn expect_item(self) -> P<ast::Item> {
         }
     }
 
+    pub fn map_item_or<F, G>(self, mut f: F, mut or: G) -> Annotatable
+        where F: FnMut(P<ast::Item>) -> P<ast::Item>,
+              G: FnMut(Annotatable) -> Annotatable
+    {
+        match self {
+            Annotatable::Item(i) => Annotatable::Item(f(i)),
+            _ => or(self)
+        }
+    }
+
     pub fn expect_trait_item(self) -> P<ast::TraitItem> {
         match self {
             Annotatable::TraitItem(i) => i,
@@ -144,18 +154,18 @@ fn expand(&self,
               ecx: &mut ExtCtxt,
               sp: Span,
               meta_item: &ast::MetaItem,
-              item: &Annotatable,
-              push:  &mut FnMut(Annotatable));
+              item: Annotatable,
+              push: &mut FnMut(Annotatable));
 }
 
 impl<F> MultiItemDecorator for F
-    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &Annotatable, &mut FnMut(Annotatable))
+    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, Annotatable, &mut FnMut(Annotatable))
 {
     fn expand(&self,
               ecx: &mut ExtCtxt,
               sp: Span,
               meta_item: &ast::MetaItem,
-              item: &Annotatable,
+              item: Annotatable,
               push: &mut FnMut(Annotatable)) {
         (*self)(ecx, sp, meta_item, item, push)
     }
@@ -433,6 +443,7 @@ pub enum SyntaxExtension {
     /// based upon it.
     #[unstable(feature = "rustc_private")]
     #[deprecated(since = "1.0.0", reason = "replaced by MultiDecorator")]
+    #[allow(deprecated)]
     Decorator(Box<ItemDecorator + 'static>),
 
     /// A syntax extension that is attached to an item and creates new items
@@ -445,6 +456,7 @@ pub enum SyntaxExtension {
     /// in-place.
     #[unstable(feature = "rustc_private")]
     #[deprecated(since = "1.0.0", reason = "replaced by MultiModifier")]
+    #[allow(deprecated)]
     Modifier(Box<ItemModifier + 'static>),
 
     /// A syntax extension that is attached to an item and modifies it
index eb3debeac99012945f3a4b2b32d8081116af132e..1300eb7ff3f459009269707934d2a6e4c3f1e3db 100644 (file)
@@ -8,18 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item};
+use ast::MetaItem;
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
-use ptr::P;
 
 pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
                                     span: Span,
                                     _: &MetaItem,
-                                    _: &Item,
-                                    _: &mut FnMut(P<Item>))
+                                    _: Annotatable,
+                                    _: &mut FnMut(Annotatable))
 {
     cx.span_err(span, "this unsafe trait should be implemented explicitly");
 }
@@ -27,8 +26,8 @@ pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
 pub fn expand_deriving_copy(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
-                            item: &Item,
-                            push: &mut FnMut(P<Item>))
+                            item: Annotatable,
+                            push: &mut FnMut(Annotatable))
 {
     let path = Path::new(vec![
         if cx.use_std { "std" } else { "core" },
index 97fc3f0bf56004308498f08c92dcd48435d97047..935f0ae8a5ef43b7030fe3d55768929727f3b99f 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr};
+use ast::{MetaItem, Expr};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -20,8 +20,8 @@
 pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                              span: Span,
                              mitem: &MetaItem,
-                             item: &Item,
-                             push: &mut FnMut(P<Item>))
+                             item: Annotatable,
+                             push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
index ce8f0a7b32b904e6f68361c1f948808219212d3c..d7142d657d408ba5b003b762091ec8f5af389fe8 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr};
+use ast::{MetaItem, Expr};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -20,8 +20,8 @@
 pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                           span: Span,
                           mitem: &MetaItem,
-                          item: &Item,
-                          push: &mut FnMut(P<Item>))
+                          item: Annotatable,
+                          push: &mut FnMut(Annotatable))
 {
     fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
         cs_same_method(
index 94cc0d9c493f21dc0abfe6e09b1082138fb26f27..6e52da2f332a619d165f2b8bc43b71b276821270 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 use ast;
-use ast::{MetaItem, Item, Expr};
+use ast::{MetaItem, Expr};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -21,8 +21,8 @@
 pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
-                           item: &Item,
-                           push: &mut FnMut(P<Item>))
+                           item: Annotatable,
+                           push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
index 61eb81c6755e2663e37baf05b61c1804dd5f6902..c31c91760e0c5d4fc85266e7c2e898f78804f41d 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr, self};
+use ast::{MetaItem, Expr, self};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -20,8 +20,8 @@
 pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
                                   span: Span,
                                   mitem: &MetaItem,
-                                  item: &Item,
-                                  push: &mut FnMut(P<Item>))
+                                  item: Annotatable,
+                                  push: &mut FnMut(Annotatable))
 {
     // structures are equal if all fields are equal, and non equal, if
     // any fields are not equal or if the enum variants are different
index dbb779decace27715f6eab03ff5ac36299a91a58..9097e984dd6af190340b7c3ce5be0b33d9f80489 100644 (file)
@@ -11,9 +11,9 @@
 pub use self::OrderingOp::*;
 
 use ast;
-use ast::{MetaItem, Item, Expr};
+use ast::{MetaItem, Expr};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -23,8 +23,8 @@
 pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
                                    span: Span,
                                    mitem: &MetaItem,
-                                   item: &Item,
-                                   push: &mut FnMut(P<Item>))
+                                   item: Annotatable,
+                                   push: &mut FnMut(Annotatable))
 {
     macro_rules! md {
         ($name:expr, $op:expr, $equal:expr) => { {
index 0b31f06f87d0676c19615d079c461f87ef4fe30f..1ab51865652a71e7740b65d22b1c8d396e8510ea 100644 (file)
@@ -11,9 +11,9 @@
 //! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more.
 
 use ast;
-use ast::{MetaItem, Item, Expr, MutMutable};
+use ast::{MetaItem, Expr, MutMutable};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -24,8 +24,8 @@
 pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
                                        span: Span,
                                        mitem: &MetaItem,
-                                       item: &Item,
-                                       push: &mut FnMut(P<Item>))
+                                       item: Annotatable,
+                                       push: &mut FnMut(Annotatable))
 {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize")
 }
@@ -33,8 +33,8 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
 pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: &Item,
-                                 push: &mut FnMut(P<Item>))
+                                 item: Annotatable,
+                                 push: &mut FnMut(Annotatable))
 {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
 }
@@ -42,8 +42,8 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
 fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: &Item,
-                                 push: &mut FnMut(P<Item>),
+                                 item: Annotatable,
+                                 push: &mut FnMut(Annotatable),
                                  krate: &'static str)
 {
     if !cx.use_std {
index f04eaa08dead14824df2f09531f65bc1feb61b75..b7b741290af1b03273a3cb389e577b2b9406a36c 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr};
+use ast::{MetaItem, Expr};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -20,8 +20,8 @@
 pub fn expand_deriving_default(cx: &mut ExtCtxt,
                                span: Span,
                                mitem: &MetaItem,
-                               item: &Item,
-                               push: &mut FnMut(P<Item>))
+                               item: Annotatable,
+                               push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
index 92944d649332f04617e1dea75f8cd75d10687090..47acedbcb8a665c6aaa41f44ad0727bd7bfc3e05 100644 (file)
@@ -88,9 +88,9 @@
 //! }
 //! ```
 
-use ast::{MetaItem, Item, Expr, ExprRet, MutMutable};
+use ast::{MetaItem, Expr, ExprRet, MutMutable};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt,Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
 pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
                                        span: Span,
                                        mitem: &MetaItem,
-                                       item: &Item,
-                                       push: &mut FnMut(P<Item>))
+                                       item: Annotatable,
+                                       push: &mut FnMut(Annotatable))
 {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize")
 }
@@ -109,8 +109,8 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
 pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: &Item,
-                                 push: &mut FnMut(P<Item>))
+                                 item: Annotatable,
+                                 push: &mut FnMut(Annotatable))
 {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
 }
@@ -118,8 +118,8 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
 fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
-                                 item: &Item,
-                                 push: &mut FnMut(P<Item>),
+                                 item: Annotatable,
+                                 push: &mut FnMut(Annotatable),
                                  krate: &'static str)
 {
     if !cx.use_std {
index 4c05cd973ff6f3252751ee7c2a96e644010b9840..222bbe2df6d21bfdf4ea8209de95dccb8d367c42 100644 (file)
 use ast_util;
 use attr;
 use attr::AttrMetaMethods;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use codemap::{self, DUMMY_SP};
 use codemap::Span;
@@ -378,41 +378,48 @@ impl<'a> TraitDef<'a> {
     pub fn expand(&self,
                   cx: &mut ExtCtxt,
                   mitem: &ast::MetaItem,
-                  item: &ast::Item,
-                  push: &mut FnMut(P<ast::Item>))
+                  item: Annotatable,
+                  push: &mut FnMut(Annotatable))
     {
-        let newitem = match item.node {
-            ast::ItemStruct(ref struct_def, ref generics) => {
-                self.expand_struct_def(cx,
-                                       &**struct_def,
-                                       item.ident,
-                                       generics)
-            }
-            ast::ItemEnum(ref enum_def, ref generics) => {
-                self.expand_enum_def(cx,
-                                     enum_def,
-                                     &item.attrs[..],
-                                     item.ident,
-                                     generics)
+        match item {
+            Annotatable::Item(item) => {
+                let newitem = match item.node {
+                    ast::ItemStruct(ref struct_def, ref generics) => {
+                        self.expand_struct_def(cx,
+                                               &**struct_def,
+                                               item.ident,
+                                               generics)
+                    }
+                    ast::ItemEnum(ref enum_def, ref generics) => {
+                        self.expand_enum_def(cx,
+                                             enum_def,
+                                             &item.attrs[..],
+                                             item.ident,
+                                             generics)
+                    }
+                    _ => {
+                        cx.span_err(mitem.span, "`derive` may only be applied to structs and enums");
+                        return;
+                    }
+                };
+                // Keep the lint attributes of the previous item to control how the
+                // generated implementations are linted
+                let mut attrs = newitem.attrs.clone();
+                attrs.extend(item.attrs.iter().filter(|a| {
+                    match &a.name()[..] {
+                        "allow" | "warn" | "deny" | "forbid" => true,
+                        _ => false,
+                    }
+                }).cloned());
+                push(Annotatable::Item(P(ast::Item {
+                    attrs: attrs,
+                    ..(*newitem).clone()
+                })))
             }
             _ => {
-                cx.span_err(mitem.span, "`derive` may only be applied to structs and enums");
-                return;
-            }
-        };
-        // Keep the lint attributes of the previous item to control how the
-        // generated implementations are linted
-        let mut attrs = newitem.attrs.clone();
-        attrs.extend(item.attrs.iter().filter(|a| {
-            match &a.name()[..] {
-                "allow" | "warn" | "deny" | "forbid" => true,
-                _ => false,
+                cx.span_err(mitem.span, "`derive` may only be applied to structs and enums");                
             }
-        }).cloned());
-        push(P(ast::Item {
-            attrs: attrs,
-            ..(*newitem).clone()
-        }))
+        }
     }
 
     /// Given that we are deriving a trait `DerivedTrait` for a type like:
index b9835eda791f7f004589c170bc7b600d76eb1fab..b1ec3f564f5747d2ca726041624cde1d84cb4a42 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr, MutMutable};
+use ast::{MetaItem, Expr, MutMutable};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -19,8 +19,8 @@
 pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
-                            item: &Item,
-                            push: &mut FnMut(P<Item>))
+                            item: Annotatable,
+                            push: &mut FnMut(Annotatable))
 {
 
     let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
index bc4a7f90911dc37fc130b5f7c4bfbe7808ae59ca..61848cca059ce3c0c02f7093933ad91872f71d45 100644 (file)
 //! 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, MetaList, MetaNameValue};
+use ast::{MetaItem, MetaWord};
 use attr::AttrMetaMethods;
-use ext::base::{ExtCtxt, SyntaxEnv, Decorator, ItemDecorator, Modifier, Annotatable};
+use ext::base::{ExtCtxt, SyntaxEnv, MultiDecorator, MultiItemDecorator, MultiModifier, Annotatable};
 use ext::build::AstBuilder;
 use feature_gate;
 use codemap::Span;
 use parse::token::{intern, intern_and_get_ident};
-use ptr::P;
 
 macro_rules! pathvec {
     ($($x:ident)::+) => (
@@ -80,41 +79,46 @@ macro_rules! path_std {
 fn expand_derive(cx: &mut ExtCtxt,
                  span: Span,
                  mitem: &MetaItem,
-                 item: P<Item>)
-                 -> P<Item> {
-    item.map(|mut item| {
-        if mitem.value_str().is_some() {
-            cx.span_err(mitem.span, "unexpected value in `derive`");
-        }
+                 annotatable: Annotatable)
+                 -> Annotatable {
+    annotatable.map_item_or(|item| {
+        item.map(|mut item| {
+            if mitem.value_str().is_some() {
+                cx.span_err(mitem.span, "unexpected value in `derive`");
+            }
 
-        let traits = mitem.meta_item_list().unwrap_or(&[]);
-        if traits.is_empty() {
-            cx.span_warn(mitem.span, "empty trait list in `derive`");
-        }
+            let traits = mitem.meta_item_list().unwrap_or(&[]);
+            if traits.is_empty() {
+                cx.span_warn(mitem.span, "empty trait list in `derive`");
+            }
 
-        for titem in traits.iter().rev() {
-            let tname = match titem.node {
-                MetaWord(ref tname) => tname,
-                _ => {
-                    cx.span_err(titem.span, "malformed `derive` entry");
+            for titem in traits.iter().rev() {
+                let tname = match titem.node {
+                    MetaWord(ref tname) => tname,
+                    _ => {
+                        cx.span_err(titem.span, "malformed `derive` entry");
+                        continue;
+                    }
+                };
+
+                if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) {
+                    feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
+                                                   "custom_derive",
+                                                   titem.span,
+                                                   feature_gate::EXPLAIN_CUSTOM_DERIVE);
                     continue;
                 }
-            };
-
-            if !(is_builtin_trait(tname) || cx.ecfg.enable_custom_derive()) {
-                feature_gate::emit_feature_err(&cx.parse_sess.span_diagnostic,
-                                               "custom_derive",
-                                               titem.span,
-                                               feature_gate::EXPLAIN_CUSTOM_DERIVE);
-                continue;
-            }
 
-            // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
-            item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span,
-                intern_and_get_ident(&format!("derive_{}", tname)))));
-        }
+                // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
+                item.attrs.push(cx.attribute(titem.span, cx.meta_word(titem.span,
+                    intern_and_get_ident(&format!("derive_{}", tname)))));
+            }
 
-        item
+            item
+        })
+    }, |a| {
+        cx.span_err(span, "`derive` can only be applied to items");
+        a
     })
 }
 
@@ -125,24 +129,24 @@ pub fn register_all(env: &mut SyntaxEnv) {
             $({
                 struct DeriveExtension;
 
-                impl ItemDecorator for DeriveExtension {
+                impl MultiItemDecorator for DeriveExtension {
                     fn expand(&self,
                               ecx: &mut ExtCtxt,
                               sp: Span,
                               mitem: &MetaItem,
-                              item: &Item,
-                              push: &mut FnMut(P<Item>)) {
+                              annotatable: Annotatable,
+                              push: &mut FnMut(Annotatable)) {
                         warn_if_deprecated(ecx, sp, $name);
-                        $func(ecx, sp, mitem, item, push);
+                        $func(ecx, sp, mitem, annotatable, push);
                     }
                 }
 
                 env.insert(intern(concat!("derive_", $name)),
-                           Decorator(Box::new(DeriveExtension)));
+                           MultiDecorator(Box::new(DeriveExtension)));
             })+
 
             env.insert(intern("derive"),
-                       Modifier(Box::new(expand_derive)));
+                       MultiModifier(Box::new(expand_derive)));
         }
 
         fn is_builtin_trait(name: &str) -> bool {
index a972cfe135511d99f6961edc9bc6fc37ad5a4dd7..d218b8df153113ff93bcd619ff9127589c78eac4 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{MetaItem, Item, Expr};
+use ast::{MetaItem, Expr};
 use ast;
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -21,8 +21,8 @@
 pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                       span: Span,
                                       mitem: &MetaItem,
-                                      item: &Item,
-                                      push: &mut FnMut(P<Item>))
+                                      item: Annotatable,
+                                      push: &mut FnMut(Annotatable))
 {
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let attrs = vec!(cx.attribute(span, inline));
index 3ce1f6f12ceab58ac7cbf5a01cc3d4bd2a3764ef..5ace1b45b065b4b51877e526ea4dca8d8c45ac18 100644 (file)
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 use ast;
-use ast::{MetaItem, Item, Expr,};
+use ast::{MetaItem, Expr,};
 use codemap::Span;
-use ext::base::ExtCtxt;
+use ext::base::{ExtCtxt, Annotatable};
 use ext::build::AstBuilder;
 use ext::deriving::generic::*;
 use ext::deriving::generic::ty::*;
@@ -21,8 +21,8 @@
 pub fn expand_deriving_show(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
-                            item: &Item,
-                            push: &mut FnMut(P<Item>))
+                            item: Annotatable,
+                            push: &mut FnMut(Annotatable))
 {
     // &mut ::std::fmt::Formatter
     let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))),
index 106d862042a9047e0c39764837127349ef9c2e76..5033f406da0477408248810695bc0ddaaa3d6db3 100644 (file)
@@ -477,59 +477,6 @@ 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
-    let (modifiers, other_attrs) = modifiers(&it.attrs, fld);
-
-    // update the attrs, leave everything else alone. Is this mutation really a good idea?
-    it = P(ast::Item {
-        attrs: other_attrs,
-        ..(*it).clone()
-    });
-
-    if modifiers.is_empty() {
-        let it = expand_item_multi_modifier(Annotatable::Item(it), fld);
-        return it.expect_item();
-    }
-
-    for attr in &modifiers {
-        let mname = attr.name();
-
-        match fld.cx.syntax_env.find(&intern(&mname)) {
-            Some(rc) => match *rc {
-                Modifier(ref mac) => {
-                    attr::mark_used(attr);
-                    fld.cx.bt_push(ExpnInfo {
-                        call_site: attr.span,
-                        callee: NameAndSpan {
-                            name: mname.to_string(),
-                            format: MacroAttribute,
-                            span: None,
-                            // attributes can do whatever they like,
-                            // for now
-                            allow_internal_unstable: true,
-                        }
-                    });
-                    it = mac.expand(fld.cx, attr.span, &*attr.node.value, it);
-                    fld.cx.bt_pop();
-                }
-                _ => unreachable!()
-            },
-            _ => unreachable!()
-        }
-    }
-
-    // Expansion may have added new ItemModifiers.
-    // It is possible, that an item modifier could expand to a multi-modifier or
-    // vice versa. In this case we will expand all modifiers before multi-modifiers,
-    // which might give an odd ordering. However, I think it is unlikely that the
-    // two kinds will be mixed, and I old-style multi-modifiers should be deprecated
-    // anyway.
-    expand_item_modifiers(it, fld)
-}
-
 /// Expand item_underscore
 fn expand_item_underscore(item: ast::Item_, fld: &mut MacroExpander) -> ast::Item_ {
     match item {
@@ -1083,7 +1030,6 @@ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
     }
 }
 
-#[allow(deprecated)] // This is needed because the `Decorator` variant is used
 fn expand_annotatable(a: Annotatable,
                       fld: &mut MacroExpander)
                       -> SmallVector<Annotatable> {
@@ -1091,73 +1037,7 @@ fn expand_annotatable(a: Annotatable,
 
     let mut decorator_items = SmallVector::zero();
     let mut new_attrs = Vec::new();
-    for attr in a.attrs() {
-        let mname = attr.name();
-
-        match fld.cx.syntax_env.find(&intern(&mname)) {
-            Some(rc) => match *rc {
-                Decorator(ref dec) => {
-                    let it = match a {
-                        Annotatable::Item(ref it) => it,
-                        // ItemDecorators are only implemented for Items.
-                        _ => break,
-                    };
-
-                    attr::mark_used(attr);
-
-                    fld.cx.bt_push(ExpnInfo {
-                        call_site: attr.span,
-                        callee: NameAndSpan {
-                            name: mname.to_string(),
-                            format: MacroAttribute,
-                            span: Some(attr.span),
-                            // attributes can do whatever they like,
-                            // for now.
-                            allow_internal_unstable: true,
-                        }
-                    });
-
-                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
-                    // but that double-mut-borrows fld
-                    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()
-                                                               .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.to_string(),
-                            format: MacroAttribute,
-                            span: Some(attr.span),
-                            // attributes can do whatever they like,
-                            // for now.
-                            allow_internal_unstable: true,
-                        }
-                    });
-
-                    // 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();
-                }
-                _ => new_attrs.push((*attr).clone()),
-            },
-            _ => new_attrs.push((*attr).clone()),
-        }
-    }
+    expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs);
 
     let mut new_items: SmallVector<Annotatable> = match a {
         Annotatable::Item(it) => match it.node {
@@ -1215,34 +1095,101 @@ fn expand_annotatable(a: Annotatable,
     new_items
 }
 
-// partition the attributes into ItemModifiers and others
-fn modifiers(attrs: &Vec<ast::Attribute>,
-             fld: &MacroExpander)
-             -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
-    attrs.iter().cloned().partition(|attr| {
-        match fld.cx.syntax_env.find(&intern(&attr.name())) {
-            Some(rc) => match *rc {
-                Modifier(_) => true,
-                _ => false
-            },
-            _ => false
+// Partition a set of attributes into one kind of attribute, and other kinds.
+macro_rules! partition {
+    ($fn_name: ident, $variant: ident) => {
+        #[allow(deprecated)] // The `allow` is needed because the `Modifier` variant might be used.
+        fn $fn_name(attrs: &[ast::Attribute],
+                    fld: &MacroExpander)
+                     -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
+            attrs.iter().cloned().partition(|attr| {
+                match fld.cx.syntax_env.find(&intern(&attr.name())) {
+                    Some(rc) => match *rc {
+                        $variant(..) => true,
+                        _ => false
+                    },
+                    _ => false
+                }
+            })
         }
-    })
+    }
 }
 
-// partition the attributes into MultiModifiers and others
-fn multi_modifiers(attrs: &[ast::Attribute],
-                   fld: &MacroExpander)
-                   -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
-    attrs.iter().cloned().partition(|attr| {
-        match fld.cx.syntax_env.find(&intern(&attr.name())) {
+partition!(modifiers, Modifier);
+partition!(multi_modifiers, MultiModifier);
+
+
+#[allow(deprecated)] // The `allow` is needed because the `Decorator` variant is used.
+fn expand_decorators(a: Annotatable,
+                     fld: &mut MacroExpander,
+                     decorator_items: &mut SmallVector<Annotatable>,
+                     new_attrs: &mut Vec<ast::Attribute>)
+{
+    for attr in a.attrs() {
+        let mname = attr.name();
+        match fld.cx.syntax_env.find(&intern(&mname)) {
             Some(rc) => match *rc {
-                MultiModifier(_) => true,
-                _ => false
+                Decorator(ref dec) => {
+                    attr::mark_used(&attr);
+
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.to_string(),
+                            format: MacroAttribute,
+                            span: Some(attr.span),
+                            // attributes can do whatever they like,
+                            // for now.
+                            allow_internal_unstable: true,
+                        }
+                    });
+
+                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
+                    // but that double-mut-borrows fld
+                    let mut items: SmallVector<Annotatable> = SmallVector::zero();
+                    dec.expand(fld.cx,
+                               attr.span,
+                               &attr.node.value,
+                               &a.clone().expect_item(),
+                               &mut |item| items.push(Annotatable::Item(item)));
+                    decorator_items.extend(items.into_iter()
+                        .flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
+
+                    fld.cx.bt_pop();
+                }
+                MultiDecorator(ref dec) => {
+                    attr::mark_used(&attr);
+
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.to_string(),
+                            format: MacroAttribute,
+                            span: Some(attr.span),
+                            // attributes can do whatever they like,
+                            // for now.
+                            allow_internal_unstable: true,
+                        }
+                    });
+
+                    // we'd ideally decorator_items.push_all(expand_annotatable(ann, fld)),
+                    // but that double-mut-borrows fld
+                    let mut items: SmallVector<Annotatable> = SmallVector::zero();
+                    dec.expand(fld.cx,
+                               attr.span,
+                               &attr.node.value,
+                               a.clone(),
+                               &mut |ann| items.push(ann));
+                    decorator_items.extend(items.into_iter()
+                        .flat_map(|ann| expand_annotatable(ann, fld).into_iter()));
+
+                    fld.cx.bt_pop();
+                }
+                _ => new_attrs.push((*attr).clone()),
             },
-            _ => false
+            _ => new_attrs.push((*attr).clone()),
         }
-    })
+    }
 }
 
 fn expand_item_multi_modifier(mut it: Annotatable,
@@ -1269,7 +1216,7 @@ fn expand_item_multi_modifier(mut it: Annotatable,
                         callee: NameAndSpan {
                             name: mname.to_string(),
                             format: MacroAttribute,
-                            span: None,
+                            span: Some(attr.span),
                             // attributes can do whatever they like,
                             // for now
                             allow_internal_unstable: true,
@@ -1288,6 +1235,59 @@ fn expand_item_multi_modifier(mut it: Annotatable,
     expand_item_multi_modifier(it, fld)
 }
 
+#[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
+    let (modifiers, other_attrs) = modifiers(&it.attrs, fld);
+
+    // update the attrs, leave everything else alone. Is this mutation really a good idea?
+    it = P(ast::Item {
+        attrs: other_attrs,
+        ..(*it).clone()
+    });
+
+    if modifiers.is_empty() {
+        let it = expand_item_multi_modifier(Annotatable::Item(it), fld);
+        return it.expect_item();
+    }
+
+    for attr in &modifiers {
+        let mname = attr.name();
+
+        match fld.cx.syntax_env.find(&intern(&mname)) {
+            Some(rc) => match *rc {
+                Modifier(ref mac) => {
+                    attr::mark_used(attr);
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.to_string(),
+                            format: MacroAttribute,
+                            span: Some(attr.span),
+                            // attributes can do whatever they like,
+                            // for now
+                            allow_internal_unstable: true,
+                        }
+                    });
+                    it = mac.expand(fld.cx, attr.span, &*attr.node.value, it);
+                    fld.cx.bt_pop();
+                }
+                _ => unreachable!()
+            },
+            _ => unreachable!()
+        }
+    }
+
+    // Expansion may have added new ItemModifiers.
+    // It is possible, that an item modifier could expand to a multi-modifier or
+    // vice versa. In this case we will expand all modifiers before multi-modifiers,
+    // which might give an odd ordering. However, I think it is unlikely that the
+    // two kinds will be mixed, and old-style multi-modifiers are deprecated.
+    expand_item_modifiers(it, fld)
+}
+
 fn expand_impl_item(ii: P<ast::ImplItem>, fld: &mut MacroExpander)
                  -> SmallVector<P<ast::ImplItem>> {
     match ii.node {