use proc_macro::TokenStream;
use quote::quote;
use syn::{parse::Parser, Attribute, Data, DeriveInput, Error, Field, Fields};
pub(crate) fn merge_opt(input: TokenStream) -> Result<TokenStream, Error> {
let mut input: DeriveInput = syn::parse(input)?;
let attributes = quote!(#[derive(::std::fmt::Debug, ::structopt::StructOpt)]);
let attributes = Attribute::parse_outer.parse2(attributes)?;
input.attrs.extend(attributes);
match &mut input.data {
Data::Struct(struct_) => {
if let Fields::Named(fields) = &mut struct_.fields {
for field in fields.named.iter_mut() {
let attributes = quote!(#[structopt(flatten)]);
let attributes = Attribute::parse_outer.parse2(attributes)?;
field.attrs.extend(attributes)
}
fields.named.push(Field::parse_named.parse2(quote!(
#[structopt(flatten)]
_dummy: __Dummy
))?);
} else {
return Err(Error::new_spanned(
&struct_.fields,
"merge_opt can only apply to named fields",
));
}
}
Data::Enum(enum_) => {
return Err(Error::new_spanned(
enum_.enum_token,
"merge_opt can only apply to struct",
));
}
Data::Union(union_) => {
return Err(Error::new_spanned(
union_.union_token,
"merge_opt can only apply to struct",
));
}
}
let attributes = &input.attrs;
Ok(quote! {
#input
#(#attributes)*
#[doc(hidden)]
struct __Dummy {}
}
.into())
}