diff --git a/serde_codegen/Cargo.toml b/serde_codegen/Cargo.toml index 9b469f1c..132547be 100644 --- a/serde_codegen/Cargo.toml +++ b/serde_codegen/Cargo.toml @@ -25,6 +25,6 @@ with-syn = [] clippy = { version = "^0.*", optional = true } quote = "0.1" serde_codegen_internals = { version = "=0.8.9", default-features = false, path = "../serde_codegen_internals" } -syn = { version = "0.5", features = ["aster", "visit"] } +syn = { version = "0.7", features = ["aster", "visit"] } syntex = { version = "^0.44.0", optional = true } syntex_syntax = { version = "^0.44.0", optional = true } diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index dae4ca65..d8a147d0 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -5,7 +5,7 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_deserialize(item: &syn::Item) -> Tokens { +pub fn expand_derive_deserialize(item: &syn::MacroInput) -> Tokens { let item = { let ctxt = internals::Ctxt::new(); let item = Item::from_ast(&ctxt, item); diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index 8dbfdf31..fed63700 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -143,7 +143,7 @@ macro_rules! shim { use syntax::print::pprust; let s = pprust::item_to_string(item); - let syn_item = syn::parse_item(&s).unwrap(); + let syn_item = syn::parse_macro_input(&s).unwrap(); let expanded = $pkg::$func(&syn_item).to_string(); use syntax::parse; @@ -163,7 +163,7 @@ shim!(Deserialize de::expand_derive_deserialize); #[cfg(feature = "with-syn")] pub fn expand_single_item(item: &str) -> String { - let syn_item = syn::parse_item(item).unwrap(); + let syn_item = syn::parse_macro_input(item).unwrap(); let (ser, de, syn_item) = strip_serde_derives(syn_item); let expanded_ser = if ser { Some(ser::expand_derive_serialize(&syn_item)) @@ -178,10 +178,10 @@ pub fn expand_single_item(item: &str) -> String { let syn_item = strip_serde_attrs(syn_item); return quote!(#expanded_ser #expanded_de #syn_item).to_string(); - fn strip_serde_derives(item: syn::Item) -> (bool, bool, syn::Item) { + fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) { let mut ser = false; let mut de = false; - let item = syn::Item { + let item = syn::MacroInput { attrs: item.attrs.into_iter().flat_map(|attr| { if attr.is_sugared_doc { return Some(attr); @@ -223,8 +223,8 @@ pub fn expand_single_item(item: &str) -> String { (ser, de, item) } - fn strip_serde_attrs(item: syn::Item) -> syn::Item { - syn::Item { + fn strip_serde_attrs(item: syn::MacroInput) -> syn::MacroInput { + syn::MacroInput { attrs: strip_serde_from_attrs(item.attrs), body: match item.body { syn::Body::Enum(variants) => syn::Body::Enum( @@ -233,6 +233,7 @@ pub fn expand_single_item(item: &str) -> String { ident: variant.ident, attrs: strip_serde_from_attrs(variant.attrs), data: strip_serde_from_variant_data(variant.data), + discriminant: variant.discriminant, } }).collect() ), diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index 448c974c..3500a230 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -5,7 +5,7 @@ use bound; use internals::ast::{Body, Field, Item, Style, Variant}; use internals::{self, attr}; -pub fn expand_derive_serialize(item: &syn::Item) -> Tokens { +pub fn expand_derive_serialize(item: &syn::MacroInput) -> Tokens { let item = Item::from_ast(&internals::Ctxt::new(), item); let impl_generics = build_impl_generics(&item); diff --git a/serde_codegen_internals/Cargo.toml b/serde_codegen_internals/Cargo.toml index a364739b..f501786f 100644 --- a/serde_codegen_internals/Cargo.toml +++ b/serde_codegen_internals/Cargo.toml @@ -15,4 +15,4 @@ unstable-testing = ["clippy"] [dependencies] clippy = { version = "^0.*", optional = true } -syn = "0.5" +syn = "0.7" diff --git a/serde_codegen_internals/src/ast.rs b/serde_codegen_internals/src/ast.rs index d62ad807..2941c164 100644 --- a/serde_codegen_internals/src/ast.rs +++ b/serde_codegen_internals/src/ast.rs @@ -35,7 +35,7 @@ pub enum Style { } impl<'a> Item<'a> { - pub fn from_ast(cx: &Ctxt, item: &'a syn::Item) -> Item<'a> { + pub fn from_ast(cx: &Ctxt, item: &'a syn::MacroInput) -> Item<'a> { let attrs = attr::Item::from_ast(cx, item); let body = match item.body { diff --git a/serde_codegen_internals/src/attr.rs b/serde_codegen_internals/src/attr.rs index 02b72b6c..44da33e3 100644 --- a/serde_codegen_internals/src/attr.rs +++ b/serde_codegen_internals/src/attr.rs @@ -94,7 +94,7 @@ pub struct Item { impl Item { /// Extract out the `#[serde(...)]` attributes from an item. - pub fn from_ast(cx: &Ctxt, item: &syn::Item) -> Self { + pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self { let mut ser_name = Attr::none(cx, "rename"); let mut de_name = Attr::none(cx, "rename"); let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields"); @@ -106,8 +106,10 @@ impl Item { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - ser_name.set(lit.clone()); - de_name.set(lit.clone()); + if let Ok(s) = get_string_from_lit(cx, name, lit) { + ser_name.set(s.clone()); + de_name.set(s); + } } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` @@ -191,8 +193,10 @@ impl Variant { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - ser_name.set(lit.clone()); - de_name.set(lit.clone()); + if let Ok(s) = get_string_from_lit(cx, name, lit) { + ser_name.set(s.clone()); + de_name.set(s); + } } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` @@ -275,8 +279,10 @@ impl Field { match meta_item { // Parse `#[serde(rename="foo")]` syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => { - ser_name.set(lit.clone()); - de_name.set(lit.clone()); + if let Ok(s) = get_string_from_lit(cx, name, lit) { + ser_name.set(s.clone()); + de_name.set(s); + } } // Parse `#[serde(rename(serialize="foo", deserialize="bar"))]` @@ -421,7 +427,7 @@ fn get_ser_and_de( items: &[syn::MetaItem], f: F ) -> Result, ()> - where F: Fn(&Ctxt, &Ident, &str) -> Result, + where F: Fn(&Ctxt, &Ident, &syn::Lit) -> Result, { let mut ser_item = Attr::none(cx, attribute); let mut de_item = Attr::none(cx, attribute); @@ -454,7 +460,7 @@ fn get_renames( cx: &Ctxt, items: &[syn::MetaItem], ) -> Result, ()> { - get_ser_and_de(cx, "rename", items, |_, _, s| Ok(s.to_owned())) + get_ser_and_de(cx, "rename", items, get_string_from_lit) } fn get_where_predicates( @@ -473,17 +479,28 @@ pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option> } } -fn parse_lit_into_path(cx: &Ctxt, name: &Ident, lit: &str) -> Result { - // TODO handle error - Ok(syn::parse_path(lit).unwrap()) +fn get_string_from_lit(_cx: &Ctxt, _name: &Ident, lit: &syn::Lit) -> Result { + if let syn::Lit::Str(ref s, _) = *lit { + Ok(s.clone()) + } else { + // TODO handle error + Err(()) + } } -fn parse_lit_into_where(cx: &Ctxt, name: &Ident, lit: &str) -> Result, ()> { - if lit.is_empty() { +fn parse_lit_into_path(cx: &Ctxt, name: &Ident, lit: &syn::Lit) -> Result { + let string = try!(get_string_from_lit(cx, name, lit)); + // TODO handle error + Ok(syn::parse_path(&string).unwrap()) +} + +fn parse_lit_into_where(cx: &Ctxt, name: &Ident, lit: &syn::Lit) -> Result, ()> { + let string = try!(get_string_from_lit(cx, name, lit)); + if string.is_empty() { return Ok(Vec::new()); } - let where_string = format!("where {}", lit); + let where_string = format!("where {}", string); // TODO handle error Ok(syn::parse_where_clause(&where_string).unwrap().predicates)