Flatten ForeignItem into an enum

There is some duplication here but it is worth it for having foreign items
individually parsable and printable with Synom and ToTokens impls. This is also
more flexible as we add new types of foreign item, for example macros that can
expand to foreign items. A macro foreign item would not have a visibility and
some of the other fields previously held in the ForeignItem struct.
diff --git a/src/gen/fold.rs b/src/gen/fold.rs
index b38f04c..7bfbbc1 100644
--- a/src/gen/fold.rs
+++ b/src/gen/fold.rs
@@ -198,8 +198,6 @@
 # [ cfg ( feature = "full" ) ]
 fn fold_foreign_item_fn(&mut self, i: ForeignItemFn) -> ForeignItemFn { fold_foreign_item_fn(self, i) }
 # [ cfg ( feature = "full" ) ]
-fn fold_foreign_item_kind(&mut self, i: ForeignItemKind) -> ForeignItemKind { fold_foreign_item_kind(self, i) }
-# [ cfg ( feature = "full" ) ]
 fn fold_foreign_item_static(&mut self, i: ForeignItemStatic) -> ForeignItemStatic { fold_foreign_item_static(self, i) }
 
 fn fold_function_ret_ty(&mut self, i: FunctionRetTy) -> FunctionRetTy { fold_function_ret_ty(self, i) }
@@ -1384,23 +1382,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn fold_foreign_item<V: Folder + ?Sized>(_visitor: &mut V, _i: ForeignItem) -> ForeignItem {
-    ForeignItem {
-        ident: _i . ident,
-        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
-        node: _visitor.fold_foreign_item_kind(_i . node),
-        vis: _visitor.fold_visibility(_i . vis),
-        semi_token: _i . semi_token,
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_foreign_item_fn<V: Folder + ?Sized>(_visitor: &mut V, _i: ForeignItemFn) -> ForeignItemFn {
-    ForeignItemFn {
-        decl: Box::new(_visitor.fold_fn_decl(* _i . decl)),
-    }
-}
-# [ cfg ( feature = "full" ) ]
-pub fn fold_foreign_item_kind<V: Folder + ?Sized>(_visitor: &mut V, _i: ForeignItemKind) -> ForeignItemKind {
-    use ::ForeignItemKind::*;
+    use ::ForeignItem::*;
     match _i {
         Fn(_binding_0, ) => {
             Fn (
@@ -1415,12 +1397,26 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn fold_foreign_item_fn<V: Folder + ?Sized>(_visitor: &mut V, _i: ForeignItemFn) -> ForeignItemFn {
+    ForeignItemFn {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        vis: _visitor.fold_visibility(_i . vis),
+        ident: _i . ident,
+        decl: Box::new(_visitor.fold_fn_decl(* _i . decl)),
+        semi_token: _i . semi_token,
+    }
+}
+# [ cfg ( feature = "full" ) ]
 pub fn fold_foreign_item_static<V: Folder + ?Sized>(_visitor: &mut V, _i: ForeignItemStatic) -> ForeignItemStatic {
     ForeignItemStatic {
+        attrs: FoldHelper::lift(_i . attrs, |it| { _visitor.fold_attribute(it) }),
+        vis: _visitor.fold_visibility(_i . vis),
         static_token: _i . static_token,
-        ty: Box::new(_visitor.fold_ty(* _i . ty)),
-        colon_token: _i . colon_token,
         mutbl: _visitor.fold_mutability(_i . mutbl),
+        ident: _i . ident,
+        colon_token: _i . colon_token,
+        ty: Box::new(_visitor.fold_ty(* _i . ty)),
+        semi_token: _i . semi_token,
     }
 }
 
diff --git a/src/gen/visit.rs b/src/gen/visit.rs
index d241aa0..6f7e5d7 100644
--- a/src/gen/visit.rs
+++ b/src/gen/visit.rs
@@ -171,8 +171,6 @@
 # [ cfg ( feature = "full" ) ]
 fn visit_foreign_item_fn(&mut self, i: &ForeignItemFn) { visit_foreign_item_fn(self, i) }
 # [ cfg ( feature = "full" ) ]
-fn visit_foreign_item_kind(&mut self, i: &ForeignItemKind) { visit_foreign_item_kind(self, i) }
-# [ cfg ( feature = "full" ) ]
 fn visit_foreign_item_static(&mut self, i: &ForeignItemStatic) { visit_foreign_item_static(self, i) }
 
 fn visit_function_ret_ty(&mut self, i: &FunctionRetTy) { visit_function_ret_ty(self, i) }
@@ -1079,19 +1077,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_foreign_item<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ForeignItem) {
-    // Skipped field _i . ident;
-    for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) };
-    _visitor.visit_foreign_item_kind(&_i . node);
-    _visitor.visit_visibility(&_i . vis);
-    // Skipped field _i . semi_token;
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_foreign_item_fn<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ForeignItemFn) {
-    _visitor.visit_fn_decl(&_i . decl);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_foreign_item_kind<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ForeignItemKind) {
-    use ::ForeignItemKind::*;
+    use ::ForeignItem::*;
     match *_i {
         Fn(ref _binding_0, ) => {
             _visitor.visit_foreign_item_fn(&* _binding_0);
@@ -1102,11 +1088,23 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn visit_foreign_item_fn<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ForeignItemFn) {
+    for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) };
+    _visitor.visit_visibility(&_i . vis);
+    // Skipped field _i . ident;
+    _visitor.visit_fn_decl(&_i . decl);
+    // Skipped field _i . semi_token;
+}
+# [ cfg ( feature = "full" ) ]
 pub fn visit_foreign_item_static<V: Visitor + ?Sized>(_visitor: &mut V, _i: &ForeignItemStatic) {
+    for it in (_i . attrs).iter() { _visitor.visit_attribute(&it) };
+    _visitor.visit_visibility(&_i . vis);
     // Skipped field _i . static_token;
-    _visitor.visit_ty(&_i . ty);
-    // Skipped field _i . colon_token;
     _visitor.visit_mutability(&_i . mutbl);
+    // Skipped field _i . ident;
+    // Skipped field _i . colon_token;
+    _visitor.visit_ty(&_i . ty);
+    // Skipped field _i . semi_token;
 }
 
 pub fn visit_function_ret_ty<V: Visitor + ?Sized>(_visitor: &mut V, _i: &FunctionRetTy) {
diff --git a/src/gen/visit_mut.rs b/src/gen/visit_mut.rs
index a8ea12a..874d29f 100644
--- a/src/gen/visit_mut.rs
+++ b/src/gen/visit_mut.rs
@@ -171,8 +171,6 @@
 # [ cfg ( feature = "full" ) ]
 fn visit_foreign_item_fn_mut(&mut self, i: &mut ForeignItemFn) { visit_foreign_item_fn_mut(self, i) }
 # [ cfg ( feature = "full" ) ]
-fn visit_foreign_item_kind_mut(&mut self, i: &mut ForeignItemKind) { visit_foreign_item_kind_mut(self, i) }
-# [ cfg ( feature = "full" ) ]
 fn visit_foreign_item_static_mut(&mut self, i: &mut ForeignItemStatic) { visit_foreign_item_static_mut(self, i) }
 
 fn visit_function_ret_ty_mut(&mut self, i: &mut FunctionRetTy) { visit_function_ret_ty_mut(self, i) }
@@ -1079,19 +1077,7 @@
 }
 # [ cfg ( feature = "full" ) ]
 pub fn visit_foreign_item_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItem) {
-    // Skipped field _i . ident;
-    for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute_mut(&mut it) };
-    _visitor.visit_foreign_item_kind_mut(&mut _i . node);
-    _visitor.visit_visibility_mut(&mut _i . vis);
-    // Skipped field _i . semi_token;
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_foreign_item_fn_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItemFn) {
-    _visitor.visit_fn_decl_mut(&mut _i . decl);
-}
-# [ cfg ( feature = "full" ) ]
-pub fn visit_foreign_item_kind_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItemKind) {
-    use ::ForeignItemKind::*;
+    use ::ForeignItem::*;
     match *_i {
         Fn(ref mut _binding_0, ) => {
             _visitor.visit_foreign_item_fn_mut(&mut * _binding_0);
@@ -1102,11 +1088,23 @@
     }
 }
 # [ cfg ( feature = "full" ) ]
+pub fn visit_foreign_item_fn_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItemFn) {
+    for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute_mut(&mut it) };
+    _visitor.visit_visibility_mut(&mut _i . vis);
+    // Skipped field _i . ident;
+    _visitor.visit_fn_decl_mut(&mut _i . decl);
+    // Skipped field _i . semi_token;
+}
+# [ cfg ( feature = "full" ) ]
 pub fn visit_foreign_item_static_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut ForeignItemStatic) {
+    for mut it in (_i . attrs).iter_mut() { _visitor.visit_attribute_mut(&mut it) };
+    _visitor.visit_visibility_mut(&mut _i . vis);
     // Skipped field _i . static_token;
-    _visitor.visit_ty_mut(&mut _i . ty);
-    // Skipped field _i . colon_token;
     _visitor.visit_mutability_mut(&mut _i . mutbl);
+    // Skipped field _i . ident;
+    // Skipped field _i . colon_token;
+    _visitor.visit_ty_mut(&mut _i . ty);
+    // Skipped field _i . semi_token;
 }
 
 pub fn visit_function_ret_ty_mut<V: VisitorMut + ?Sized>(_visitor: &mut V, _i: &mut FunctionRetTy) {
diff --git a/src/item.rs b/src/item.rs
index 00a3a4f..0416b95 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -275,33 +275,29 @@
     }
 }
 
-ast_struct! {
-    pub struct ForeignItem {
-        pub ident: Ident,
-        pub attrs: Vec<Attribute>,
-        pub node: ForeignItemKind,
-        pub vis: Visibility,
-        pub semi_token: tokens::Semi,
-    }
-}
-
 ast_enum_of_structs! {
     /// An item within an `extern` block
-    pub enum ForeignItemKind {
+    pub enum ForeignItem {
         /// A foreign function
         pub Fn(ForeignItemFn {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
+            pub ident: Ident,
             pub decl: Box<FnDecl>,
+            pub semi_token: tokens::Semi,
         }),
         /// A foreign static item (`static ext: u8`)
         pub Static(ForeignItemStatic {
+            pub attrs: Vec<Attribute>,
+            pub vis: Visibility,
             pub static_token: tokens::Static,
-            pub ty: Box<Ty>,
-            pub colon_token: tokens::Colon,
             pub mutbl: Mutability,
+            pub ident: Ident,
+            pub colon_token: tokens::Colon,
+            pub ty: Box<Ty>,
+            pub semi_token: tokens::Semi,
         }),
     }
-
-    do_not_generate_to_tokens
 }
 
 ast_enum_of_structs! {
@@ -821,15 +817,13 @@
         })
     ));
 
-    impl Synom for ForeignItem {
-        named!(parse -> Self, alt!(
-            foreign_fn
-            |
-            foreign_static
-        ));
-    }
+    impl_synom!(ForeignItem "foreign item" alt!(
+        syn!(ForeignItemFn) => { ForeignItem::Fn }
+        |
+        syn!(ForeignItemStatic) => { ForeignItem::Static }
+    ));
 
-    named!(foreign_fn -> ForeignItem, do_parse!(
+    impl_synom!(ForeignItemFn "foreign function" do_parse!(
         attrs: many0!(call!(Attribute::parse_outer)) >>
         vis: syn!(Visibility) >>
         fn_: syn!(Fn_) >>
@@ -847,30 +841,28 @@
         ({
             let ((inputs, variadic), parens) = inputs;
             let variadic = variadic.and_then(|v| v);
-            ForeignItem {
+            ForeignItemFn {
                 ident: ident,
                 attrs: attrs,
                 semi_token: semi,
-                node: ForeignItemFn {
-                    decl: Box::new(FnDecl {
-                        fn_token: fn_,
-                        paren_token: parens,
-                        inputs: inputs,
-                        variadic: variadic.is_some(),
-                        dot_tokens: variadic,
-                        output: ret,
-                        generics: Generics {
-                            where_clause: where_clause,
-                            .. generics
-                        },
-                    }),
-                }.into(),
+                decl: Box::new(FnDecl {
+                    fn_token: fn_,
+                    paren_token: parens,
+                    inputs: inputs,
+                    variadic: variadic.is_some(),
+                    dot_tokens: variadic,
+                    output: ret,
+                    generics: Generics {
+                        where_clause: where_clause,
+                        .. generics
+                    },
+                }),
                 vis: vis,
             }
         })
     ));
 
-    named!(foreign_static -> ForeignItem, do_parse!(
+    impl_synom!(ForeignItemStatic "foreign static" do_parse!(
         attrs: many0!(call!(Attribute::parse_outer)) >>
         vis: syn!(Visibility) >>
         static_: syn!(Static) >>
@@ -879,16 +871,14 @@
         colon: syn!(Colon) >>
         ty: syn!(Ty) >>
         semi: syn!(Semi) >>
-        (ForeignItem {
+        (ForeignItemStatic {
             ident: ident,
             attrs: attrs,
             semi_token: semi,
-            node: ForeignItemStatic {
-                ty: Box::new(ty),
-                mutbl: mutability,
-                static_token: static_,
-                colon_token: colon,
-            }.into(),
+            ty: Box::new(ty),
+            mutbl: mutability,
+            static_token: static_,
+            colon_token: colon,
             vis: vis,
         })
     ));
@@ -1638,22 +1628,24 @@
         }
     }
 
-    impl ToTokens for ForeignItem {
+    impl ToTokens for ForeignItemFn {
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(self.attrs.outer());
             self.vis.to_tokens(tokens);
-            match self.node {
-                ForeignItemKind::Fn(ref item) => {
-                    NamedDecl(&item.decl, self.ident).to_tokens(tokens)
-                }
-                ForeignItemKind::Static(ref item) => {
-                    item.static_token.to_tokens(tokens);
-                    item.mutbl.to_tokens(tokens);
-                    self.ident.to_tokens(tokens);
-                    item.colon_token.to_tokens(tokens);
-                    item.ty.to_tokens(tokens);
-                }
-            }
+            NamedDecl(&self.decl, self.ident).to_tokens(tokens);
+            self.semi_token.to_tokens(tokens);
+        }
+    }
+
+    impl ToTokens for ForeignItemStatic {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
+            self.vis.to_tokens(tokens);
+            self.static_token.to_tokens(tokens);
+            self.mutbl.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
+            self.colon_token.to_tokens(tokens);
+            self.ty.to_tokens(tokens);
             self.semi_token.to_tokens(tokens);
         }
     }
diff --git a/src/lib.rs b/src/lib.rs
index ed855c7..5fc447e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -52,7 +52,7 @@
 #[cfg(feature = "full")]
 mod item;
 #[cfg(feature = "full")]
-pub use item::{Constness, Defaultness, FnArg, FnDecl, ForeignItemKind, ForeignItem, ItemForeignMod,
+pub use item::{Constness, Defaultness, FnArg, FnDecl, ForeignItem, ItemForeignMod,
                ImplItem, ImplItemKind, ImplPolarity, Item, MethodSig, PathListItem,
                TraitItem, ViewPath, ItemExternCrate, ItemUse,
                ItemStatic, ItemConst, ItemFn, ItemMacro, ItemMod, ItemTy, ItemEnum,