Merge pull request #618 from serde-rs/up
Ask proc_macro_derive to ignore serde attributes
This commit is contained in:
commit
5bd0386b8e
@ -22,7 +22,6 @@ with-syn = []
|
||||
|
||||
[dependencies]
|
||||
clippy = { version = "^0.*", optional = true }
|
||||
post-expansion = "0.2"
|
||||
quote = "0.3"
|
||||
serde_codegen_internals = { version = "=0.10.0", default-features = false, path = "../serde_codegen_internals" }
|
||||
syn = { version = "0.10", features = ["aster", "visit"] }
|
||||
|
@ -27,9 +27,6 @@ extern crate syn;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
#[cfg(feature = "with-syn")]
|
||||
extern crate post_expansion;
|
||||
|
||||
#[cfg(feature = "with-syntex")]
|
||||
use std::path::Path;
|
||||
|
||||
@ -73,8 +70,8 @@ fn syntex_registry() -> syntex::Registry {
|
||||
reg.add_attr("feature(custom_derive)");
|
||||
reg.add_attr("feature(custom_attribute)");
|
||||
|
||||
reg.add_decorator("derive_Serialize", expand_derive_serialize);
|
||||
reg.add_decorator("derive_Deserialize", expand_derive_deserialize);
|
||||
reg.add_decorator("derive_Serialize", shim::expand_derive_serialize);
|
||||
reg.add_decorator("derive_Deserialize", shim::expand_derive_deserialize);
|
||||
|
||||
reg.add_post_expansion_pass(strip_attributes);
|
||||
|
||||
@ -112,19 +109,19 @@ pub fn register(reg: &mut rustc_plugin::Registry) {
|
||||
reg.register_syntax_extension(
|
||||
syntax::parse::token::intern("derive_Serialize"),
|
||||
syntax::ext::base::MultiDecorator(
|
||||
Box::new(expand_derive_serialize)));
|
||||
Box::new(shim::expand_derive_serialize)));
|
||||
|
||||
reg.register_syntax_extension(
|
||||
syntax::parse::token::intern("derive_Deserialize"),
|
||||
syntax::ext::base::MultiDecorator(
|
||||
Box::new(expand_derive_deserialize)));
|
||||
Box::new(shim::expand_derive_deserialize)));
|
||||
|
||||
reg.register_attribute("serde".to_owned(), AttributeType::Normal);
|
||||
}
|
||||
|
||||
macro_rules! shim {
|
||||
($name:ident $pkg:ident :: $func:ident) => {
|
||||
fn $func(
|
||||
pub fn $func(
|
||||
cx: &mut ::syntax::ext::base::ExtCtxt,
|
||||
span: ::syntax::codemap::Span,
|
||||
meta_item: &::syntax::ast::MetaItem,
|
||||
@ -160,6 +157,7 @@ macro_rules! shim {
|
||||
use syntax::print::pprust;
|
||||
let s = pprust::item_to_string(item);
|
||||
|
||||
use {syn, $pkg};
|
||||
let syn_item = syn::parse_macro_input(&s).unwrap();
|
||||
let expanded = match $pkg::$func(&syn_item) {
|
||||
Ok(expanded) => expanded.to_string(),
|
||||
@ -178,72 +176,23 @@ macro_rules! shim {
|
||||
};
|
||||
}
|
||||
|
||||
shim!(Serialize ser::expand_derive_serialize);
|
||||
shim!(Deserialize de::expand_derive_deserialize);
|
||||
mod shim {
|
||||
shim!(Serialize ser::expand_derive_serialize);
|
||||
shim!(Deserialize de::expand_derive_deserialize);
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-syn")]
|
||||
pub fn expand_single_item(item: &str) -> Result<String, String> {
|
||||
#[doc(hidden)]
|
||||
/// Not public API. Use the serde_derive crate.
|
||||
pub fn expand_derive_serialize(item: &str) -> Result<String, String> {
|
||||
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(try!(ser::expand_derive_serialize(&syn_item)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let expanded_de = if de {
|
||||
Some(try!(de::expand_derive_deserialize(&syn_item)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let syn_item = post_expansion::strip_attrs_later(syn_item, &["serde"], "serde");
|
||||
return Ok(quote!(#expanded_ser #expanded_de #syn_item).to_string());
|
||||
|
||||
fn strip_serde_derives(item: syn::MacroInput) -> (bool, bool, syn::MacroInput) {
|
||||
let mut ser = false;
|
||||
let mut de = false;
|
||||
let item = syn::MacroInput {
|
||||
attrs: item.attrs.into_iter().flat_map(|attr| {
|
||||
if attr.is_sugared_doc || attr.style != syn::AttrStyle::Outer {
|
||||
return Some(attr);
|
||||
}
|
||||
let (name, nested) = match attr.value {
|
||||
syn::MetaItem::List(name, nested) => (name, nested),
|
||||
_ => return Some(attr)
|
||||
};
|
||||
if name != "derive" {
|
||||
return Some(syn::Attribute {
|
||||
style: syn::AttrStyle::Outer,
|
||||
value: syn::MetaItem::List(name, nested),
|
||||
is_sugared_doc: false,
|
||||
});
|
||||
}
|
||||
let rest: Vec<_> = nested.into_iter().filter(|nested| {
|
||||
use syn::MetaItem::Word;
|
||||
use syn::NestedMetaItem::MetaItem;
|
||||
match *nested {
|
||||
MetaItem(Word(ref word)) if word == "Serialize" => {
|
||||
ser = true;
|
||||
false
|
||||
}
|
||||
MetaItem(Word(ref word)) if word == "Deserialize" => {
|
||||
de = true;
|
||||
false
|
||||
}
|
||||
_ => true,
|
||||
}
|
||||
}).collect();
|
||||
if rest.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(syn::Attribute {
|
||||
style: syn::AttrStyle::Outer,
|
||||
value: syn::MetaItem::List(name, rest),
|
||||
is_sugared_doc: false,
|
||||
})
|
||||
}
|
||||
}).collect(),
|
||||
..item
|
||||
};
|
||||
(ser, de, item)
|
||||
}
|
||||
ser::expand_derive_serialize(&syn_item).map(|derive| derive.to_string())
|
||||
}
|
||||
|
||||
#[cfg(feature = "with-syn")]
|
||||
#[doc(hidden)]
|
||||
/// Not public API. Use the serde_derive crate.
|
||||
pub fn expand_derive_deserialize(item: &str) -> Result<String, String> {
|
||||
let syn_item = syn::parse_macro_input(item).unwrap();
|
||||
de::expand_derive_deserialize(&syn_item).map(|derive| derive.to_string())
|
||||
}
|
||||
|
@ -14,9 +14,6 @@ include = ["Cargo.toml", "src/**/*.rs"]
|
||||
name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
post-expansion = "0.2.0"
|
||||
|
||||
[dependencies.serde_codegen]
|
||||
version = "=0.8.17"
|
||||
path = "../serde_codegen"
|
||||
|
@ -4,27 +4,20 @@
|
||||
extern crate proc_macro;
|
||||
extern crate serde_codegen;
|
||||
|
||||
#[macro_use]
|
||||
extern crate post_expansion;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_derive(Serialize)]
|
||||
#[proc_macro_derive(Serialize, attributes(serde))]
|
||||
pub fn derive_serialize(input: TokenStream) -> TokenStream {
|
||||
let item = format!("#[derive(Serialize)]\n{}", input);
|
||||
match serde_codegen::expand_single_item(&item) {
|
||||
match serde_codegen::expand_derive_serialize(&input.to_string()) {
|
||||
Ok(expanded) => expanded.parse().unwrap(),
|
||||
Err(msg) => panic!(msg),
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Deserialize)]
|
||||
#[proc_macro_derive(Deserialize, attributes(serde))]
|
||||
pub fn derive_deserialize(input: TokenStream) -> TokenStream {
|
||||
let item = format!("#[derive(Deserialize)]\n{}", input);
|
||||
match serde_codegen::expand_single_item(&item) {
|
||||
match serde_codegen::expand_derive_deserialize(&input.to_string()) {
|
||||
Ok(expanded) => expanded.parse().unwrap(),
|
||||
Err(msg) => panic!(msg),
|
||||
}
|
||||
}
|
||||
|
||||
register_post_expansion!(PostExpansion_serde);
|
||||
|
Loading…
Reference in New Issue
Block a user