diff --git a/README.md b/README.md index 0edc9e1..443e247 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,4 @@ fn main() { # Contributors * Dan Hable +* Denis Dengler diff --git a/merge-rs-derive/src/lib.rs b/merge-rs-derive/src/lib.rs index 844d086..7297f67 100644 --- a/merge-rs-derive/src/lib.rs +++ b/merge-rs-derive/src/lib.rs @@ -1,14 +1,13 @@ -use proc_macro::TokenStream; -use proc_macro2::Span; -use quote::quote; -use syn::{parse_macro_input, Ident}; use darling::{ast, util, FromDeriveInput, FromField}; +use proc_macro::TokenStream; +use quote::{quote, quote_spanned}; +use syn::{parse_macro_input, spanned::Spanned, Ident}; #[derive(Debug, FromField)] #[darling(attributes(merge_field))] struct MergeField { ident: Option, - strategy: Option, + strategy: Option, #[darling(default)] skip: bool, } @@ -45,11 +44,7 @@ fn gen_field_lines( res } -fn do_derive( - input: TokenStream, - gen_field: FieldGenFn, - gen_trait: TraitGenFn, -) -> TokenStream { +fn do_derive(input: TokenStream, gen_field: FieldGenFn, gen_trait: TraitGenFn) -> TokenStream { let parsed = parse_macro_input!(input); match MergeTarget::from_derive_input(&parsed) { Err(e) => e.write_errors(), @@ -58,26 +53,22 @@ fn do_derive( let fields = gen_field_lines(target.data.take_struct(), gen_field); gen_trait(target_ident, fields) } - }.into() + } + .into() } #[proc_macro_derive(MergeMut, attributes(merge_field))] pub fn derive_merge_mut(input: TokenStream) -> TokenStream { do_derive( input, - |field, field_token| { - match field.strategy { - _ if field.skip => None, - None => Some(quote! { - self.#field_token.merge_mut(&other.#field_token)?; - }), - Some(strategy) => { - let strategy_fn = Ident::new(&strategy, Span::call_site()); - Some(quote! { - #strategy_fn(&mut self.#field_token, &other.#field_token); // TODO: bug here? - }) - } - } + |field, field_token| match field.strategy { + _ if field.skip => None, + None => Some(quote! { + self.#field_token.merge_mut(&other.#field_token)?; + }), + Some(strategy) => Some( + quote_spanned!(strategy.span() => #strategy(&mut self.#field_token, &other.#field_token)?;), + ), }, |target, fields| { quote! { @@ -88,28 +79,24 @@ pub fn derive_merge_mut(input: TokenStream) -> TokenStream { } } } - }) + }, + ) } #[proc_macro_derive(Merge, attributes(merge_field))] pub fn derive_merge(input: TokenStream) -> TokenStream { do_derive( input, - |field, field_token| { - match field.strategy { - _ if field.skip => Some(quote! { - #field_token: self.#field_token.clone(), - }), - None => Some(quote! { - #field_token: self.#field_token.merge(&other.#field_token)?, - }), - Some(strategy) => { - let strategy_fn = Ident::new(&strategy, Span::call_site()); - Some(quote! { - #field_token: #strategy_fn(&self.#field_token, &other.#field_token)?, - }) - } - } + |field, field_token| match field.strategy { + _ if field.skip => Some(quote! { + #field_token: self.#field_token.clone(), + }), + None => Some(quote! { + #field_token: self.#field_token.merge(&other.#field_token)?, + }), + Some(strategy) => Some(quote! { + #field_token: quote_spanned!(strategy.span() => #strategy(&mut self.#field_token, &other.#field_token)?;) + }), }, |target, fields| { quote! { diff --git a/tests/merge_mut_tests.rs b/tests/merge_mut_tests.rs index 2c37104..a6035c1 100644 --- a/tests/merge_mut_tests.rs +++ b/tests/merge_mut_tests.rs @@ -1,17 +1,23 @@ -use merge_rs::{MergeMut}; +use merge_rs::MergeMut; -fn concat_string(lhs: &mut String, rhs: &str) { +fn concat_string(lhs: &mut String, rhs: &str) -> Result<(), Box> { lhs.push_str(rhs); + Ok(()) } -fn sum(lhs: &mut T, rhs: &T) { +fn sum( + lhs: &mut T, + rhs: &T, +) -> Result<(), Box> { *lhs += *rhs; + Ok(()) } -fn max(lhs: &mut T, rhs: &T) { +fn max(lhs: &mut T, rhs: &T) -> Result<(), Box> { if *lhs < *rhs { *lhs = *rhs; } + Ok(()) } #[derive(Debug, MergeMut)] @@ -83,16 +89,24 @@ struct TupleStruct( #[test] fn test_tuple_struct() { - let mut left = TupleStruct(789, 1700319581526, NestedStruct { - name: "C".to_string(), - name_len: 1, - age: 5, - }); - let right = TupleStruct(987, 1700319612124, NestedStruct { - name: "DD".to_string(), - name_len: 2, - age: 65, - }); + let mut left = TupleStruct( + 789, + 1700319581526, + NestedStruct { + name: "C".to_string(), + name_len: 1, + age: 5, + }, + ); + let right = TupleStruct( + 987, + 1700319612124, + NestedStruct { + name: "DD".to_string(), + name_len: 2, + age: 65, + }, + ); left.merge_mut(&right).expect("merge should be successful"); assert_eq!(left.0, 789); assert_eq!(left.1, 1700319612124);