Skip to content

Commit

Permalink
Fix merge_fn for fields with cfg attrs
Browse files Browse the repository at this point in the history
  • Loading branch information
roignpar committed Dec 6, 2024
1 parent fdf6860 commit 40ebe4a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
25 changes: 20 additions & 5 deletions src/merge.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use proc_macro2::{Span, TokenStream};
use quote::quote;
use quote::{quote, ToTokens};
use syn::{Fields, Ident, Index, ItemStruct};

use crate::args::{Args, MergeFnName};
use crate::fields;

const DEFAULT_FN_NAME: &str = "merge_opt";
const CFG: &str = "cfg";

pub fn generate(item: &ItemStruct, opt_item: &ItemStruct, args: &Args) -> TokenStream {
if let Some(merge_fn) = &args.merge {
Expand Down Expand Up @@ -40,6 +41,14 @@ fn field_bindings(fields: &Fields, args: &Args) -> TokenStream {
let mut tokens = TokenStream::new();

for (i, field) in fields.iter().enumerate() {
let mut cfg_attrs = TokenStream::new();

for attr in field.attrs.iter() {
if attr.path().is_ident(CFG) {
attr.to_tokens(&mut cfg_attrs);
}
}

let field_name = match &field.ident {
// means that original item is a tuple struct
None => {
Expand All @@ -52,14 +61,20 @@ fn field_bindings(fields: &Fields, args: &Args) -> TokenStream {

let field_tokens = if fields::is_option(field) && !args.rewrap {
quote! {
if opt.#field_name.is_some() {
self.#field_name = opt.#field_name;
#cfg_attrs
{
if opt.#field_name.is_some() {
self.#field_name = opt.#field_name;
}
}
}
} else {
quote! {
if let Some(value) = opt.#field_name {
self.#field_name = value
#cfg_attrs
{
if let Some(value) = opt.#field_name {
self.#field_name = value
}
}
}
};
Expand Down
39 changes: 39 additions & 0 deletions tests/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,42 @@ fn merge_tuple_struct() {
assert_eq!(original_clone.0, opt4.0.unwrap());
assert_eq!(original_clone.1, opt4.1.unwrap());
}

#[test]
fn merge_cfg_field() {
#![allow(unexpected_cfgs)]

#[optfield(Opt, attrs, merge_fn)]
#[optfield(OptFieldAttrs, field_attrs, attrs, merge_fn = merge_opt_attrs)]
#[derive(Clone, Debug)]
struct Original {
#[cfg(some_feature)]
feature_field: String,
field: i32,
}

let mut original = Original { field: 2 };
let mut opt = Opt {
field: None,
feature_field: None,
};

original.merge_opt(opt.clone());
assert_eq!(original.field, 2);

opt.field = Some(3);
opt.feature_field = Some("test".to_string());

original.merge_opt(opt);
assert_eq!(original.field, 3);

let mut opt_attrs = OptFieldAttrs { field: None };

original.merge_opt_attrs(opt_attrs.clone());
assert_eq!(original.field, 3);

opt_attrs.field = Some(4);

original.merge_opt_attrs(opt_attrs);
assert_eq!(original.field, 4);
}

0 comments on commit 40ebe4a

Please sign in to comment.