diff --git a/schemars_derive/Cargo.toml b/schemars_derive/Cargo.toml index 7e67edc..2a8c5fd 100644 --- a/schemars_derive/Cargo.toml +++ b/schemars_derive/Cargo.toml @@ -14,5 +14,9 @@ proc-macro = true [dependencies] proc-macro2 = "0.4" quote = "0.6.13" -syn = "0.15.22" +syn = "0.15.44" serde_derive_internals = "0.24.1" + +[dev-dependencies] +pretty_assertions = "0.6.1" +syn = { version = "0.15.44", features = ["extra-traits"] } diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs index b0d6178..050c506 100644 --- a/schemars_derive/src/lib.rs +++ b/schemars_derive/src/lib.rs @@ -20,7 +20,7 @@ pub fn derive_json_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt preprocess::add_trait_bounds(&mut input.generics); if let Err(e) = preprocess::process_serde_attrs(&mut input) { - return e.into(); + return compile_error(input.span(), e).into(); } let ctxt = Ctxt::new(); diff --git a/schemars_derive/src/preprocess.rs b/schemars_derive/src/preprocess.rs index bd0b32d..009ce29 100644 --- a/schemars_derive/src/preprocess.rs +++ b/schemars_derive/src/preprocess.rs @@ -1,9 +1,7 @@ -use proc_macro2::TokenStream; use quote::ToTokens; use serde_derive_internals::Ctxt; use std::collections::BTreeSet; use syn::parse::Parser; -use syn::spanned::Spanned; use syn::{ Attribute, Data, DeriveInput, Field, GenericParam, Generics, Ident, Meta, NestedMeta, Variant, }; @@ -18,7 +16,7 @@ pub fn add_trait_bounds(generics: &mut Generics) { // If a struct/variant/field has any #[schemars] attributes, then rename them // to #[serde] so that serde_derive_internals will parse them for us. -pub fn process_serde_attrs(input: &mut DeriveInput) -> Result<(), TokenStream> { +pub fn process_serde_attrs(input: &mut DeriveInput) -> Result<(), String> { let ctxt = Ctxt::new(); process_attrs(&ctxt, &mut input.attrs); match input.data { @@ -27,11 +25,7 @@ pub fn process_serde_attrs(input: &mut DeriveInput) -> Result<(), TokenStream> { Data::Union(ref mut u) => process_serde_field_attrs(&ctxt, u.fields.named.iter_mut()), }; - ctxt.check().map_err(|message| { - quote_spanned! {input.span()=> - compile_error!(#message); - } - }) + ctxt.check() } fn process_serde_variant_attrs<'a>(ctxt: &Ctxt, variants: impl Iterator) { @@ -118,3 +112,48 @@ fn get_meta_ident(ctxt: &Ctxt, meta: &NestedMeta) -> Result { } } } + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + use syn::DeriveInput; + + #[test] + fn test_process_serde_attrs() { + let mut input: DeriveInput = parse_quote! { + #[serde(container, container2 = "blah")] + #[serde(container3(foo, bar))] + #[schemars(container2 = "overridden", container4)] + #[misc] + struct MyStruct { + #[serde(field, field2)] + field1: i32, + #[serde(field, field2)] + #[schemars(field = "overridden")] + field2: i32, + #[schemars(field)] + field3: i32, + } + }; + let expected: DeriveInput = parse_quote! { + #[serde(container2 = "overridden", container4)] + #[serde(container, container3(foo, bar))] + struct MyStruct { + #[serde(field, field2)] + field1: i32, + #[serde(field = "overridden")] + #[serde(field2)] + field2: i32, + #[serde(field)] + field3: i32, + } + }; + + if let Err(e) = process_serde_attrs(&mut input) { + panic!("process_serde_attrs returned error: {}", e) + }; + + assert_eq!(input, expected); + } +}