derive-ex 0.1.4

Improved version of the macro to implement the traits defined in the standard library.
Documentation
use crate::{
    bound::{Bound, Bounds, WhereClauseBuilder},
    common::BinaryOp,
    syn_utils::expand_self,
};
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, ToTokens};
use std::collections::HashMap;
use structmeta::{Flag, NameArgs, Parse, StructMeta};
use syn::{
    parse::Parse, parse2, parse_quote, spanned::Spanned, token, Attribute, Error, Expr, Field,
    Fields, Ident, Index, ItemEnum, ItemStruct, Path, Result, Type, Variant,
};

#[derive(StructMeta, Debug)]
#[struct_meta(name_filter = "snake_case")]
struct Args {
    #[struct_meta(unnamed)]
    items: Vec<DeriveItem>,
    bound: Option<NameArgs<Vec<Bound>>>,
    dump: bool,
}

#[derive(Parse, Debug)]
struct DeriveItem {
    trait_ident: Ident,
    args: DeriveItemArgsOption,
}

#[derive(StructMeta, Debug)]
#[struct_meta(name_filter = "snake_case")]
struct DeriveItemArgs {
    bound: Option<NameArgs<Vec<Bound>>>,
    dump: bool,
}

#[derive(Parse, Debug)]
enum DeriveItemArgsOption {
    Some {
        #[parse(peek)]
        #[to_tokens("(")]
        _paren: token::Paren,
        args: DeriveItemArgs,
    },
    None,
}

pub fn build_by_item_struct(attr: TokenStream, item: &mut ItemStruct) -> Result<TokenStream> {
    let mut kinds = HelperAttributeKinds::new(true);
    let result = build_by_item_struct_core(attr, item, &mut kinds);
    remove_attrs(&mut item.attrs, &kinds);
    for field in &mut item.fields {
        remove_attrs(&mut field.attrs, &kinds)
    }
    result
}
fn build_by_item_struct_core(
    attr: TokenStream,
    item: &ItemStruct,
    kinds: &mut HelperAttributeKinds,
) -> Result<TokenStream> {
    let es = DeriveEntry::from_root(attr, &item.attrs)?;
    kinds.extend(&es);
    let hattrs = HelperAttributes::from_attrs(&item.attrs, &kinds.without_derive_ex())?;
    let fields = FieldEntry::from_fields(&item.fields, kinds)?;
    let mut ts_all = TokenStream::new();
    for e in es {
        let result = match e.kind {
            DeriveItemKind::BinaryOp(op) => build_binary_op(item, op, &e, &fields),
            DeriveItemKind::AssignOp(op) => build_assign_op(item, op, &e, &fields),
            DeriveItemKind::UnaryOp(op) => build_unary_op(item, op, &e, &fields),
            DeriveItemKind::Copy => build_copy_for_struct(item, &e, &fields),
            DeriveItemKind::Clone => build_clone_for_struct(item, &e, &fields),
            DeriveItemKind::Debug => build_debug_for_struct(item, &e, &hattrs, &fields),
            DeriveItemKind::Default => build_default_for_struct(item, &e, &hattrs, &fields),
            DeriveItemKind::Deref | DeriveItemKind::DerefMut => {
                build_deref_for_struct(item, &e, &fields)
            }
        };
        ts_all.extend(e.apply_dump(result));
    }
    Ok(ts_all)
}
pub fn build_by_item_enum(attr: TokenStream, item: &mut ItemEnum) -> Result<TokenStream> {
    let mut kinds = HelperAttributeKinds::new(true);
    let result = build_by_item_enum_core(attr, item, &mut kinds);
    remove_attrs(&mut item.attrs, &kinds);
    for variant in &mut item.variants {
        remove_attrs(&mut variant.attrs, &kinds);
        for field in &mut variant.fields {
            remove_attrs(&mut field.attrs, &kinds)
        }
    }
    result
}
fn build_by_item_enum_core(
    attr: TokenStream,
    item: &ItemEnum,
    kinds: &mut HelperAttributeKinds,
) -> Result<TokenStream> {
    let es = DeriveEntry::from_root(attr, &item.attrs)?;
    kinds.extend(&es);
    let hattrs = HelperAttributes::from_attrs(&item.attrs, &kinds.without_derive_ex())?;
    let variants = VariantEntry::from_variants(&item.variants, kinds)?;
    let mut ts_all = TokenStream::new();
    for e in es {
        let result = match e.kind {
            DeriveItemKind::Copy => build_copy_for_enum(item, &e, &variants),
            DeriveItemKind::Clone => build_clone_for_enum(item, &e, &variants),
            DeriveItemKind::Debug => build_debug_for_enum(item, &e, &hattrs, &variants),
            DeriveItemKind::Default => build_default_for_enum(item, &e, &hattrs, &variants),
            _ => bail!(e.span, "derive `{}` for enum is not supported", e.kind),
        };
        ts_all.extend(e.apply_dump(result));
    }
    Ok(ts_all)
}

fn build_binary_op(
    item: &ItemStruct,
    op: BinaryOp,
    e: &DeriveEntry,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::BinaryOp(op);
    let (_, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let generics = expand_self(&item.generics, &this_ty);
    let (impl_g, _, _) = generics.split_for_impl();
    let trait_ = kind.to_path();
    let func_name = format_ident!("{}", op.to_func_name());

    let build = |lhs_is_ref: bool, rhs_is_ref: bool| {
        let self_ty = with_ref(&this_ty, lhs_is_ref);
        let rhs_ty = with_ref(&this_ty, rhs_is_ref);
        let mut wcb = WhereClauseBuilder::new(&generics);
        let use_bounds = e.push_bounds_to(&mut wcb);
        let mut values = Vec::new();
        for field in fields {
            let field_ty = &field.field.ty;
            let lhs = with_ref(&member(quote!(self), field), lhs_is_ref);
            let rhs = with_ref(&member(quote!(rhs), field), rhs_is_ref);
            let lhs_ty = with_ref(field_ty, lhs_is_ref);
            let rhs_ty = with_ref(field_ty, rhs_is_ref);
            values.push(quote!(<#lhs_ty as #trait_<#rhs_ty>>::#func_name(#lhs, #rhs)));
            field.push_bounds_to(use_bounds, kind, &mut wcb);
        }
        let ctor_args = build_ctor_args(&item.fields, &values);
        let wheres = wcb.build(|ty| match (lhs_is_ref, rhs_is_ref) {
            (true, true) => quote!(for<'a> &'a #ty : #trait_<&'a #ty, Output = #ty>),
            (true, false) => quote!(for<'a> &'a #ty : #trait_<#ty, Output = #ty>),
            (false, true) => quote!(for<'a> #ty : #trait_<&'a #ty, Output = #ty>),
            (false, false) => quote!(#ty : #trait_<#ty, Output = #ty>),
        });
        quote! {
            impl #impl_g #trait_<#rhs_ty> for #self_ty #wheres {
                type Output = #this_ty;
                fn #func_name(self, rhs: #rhs_ty) -> Self::Output {
                    #this_ty_ident #ctor_args
                }
            }
        }
    };
    let mut ts = TokenStream::new();
    for lhs_is_ref in [false, true] {
        for rhs_is_ref in [false, true] {
            ts.extend(build(lhs_is_ref, rhs_is_ref));
        }
    }
    Ok(ts)
}
fn build_assign_op(
    item: &ItemStruct,
    op: BinaryOp,
    e: &DeriveEntry,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::AssignOp(op);
    let (_, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let generics = expand_self(&item.generics, &this_ty);
    let (impl_g, _, _) = generics.split_for_impl();
    let trait_ = kind.to_path();
    let func_name = format_ident!("{}_assign", op.to_func_name());

    let build = |rhs_is_ref: bool| {
        let rhs_ty = with_ref(&this_ty, rhs_is_ref);
        let mut wcb = WhereClauseBuilder::new(&generics);
        let use_bounds = e.push_bounds_to(&mut wcb);
        let mut exprs = Vec::new();
        for field in fields {
            let field_ty = &field.field.ty;
            let lhs = member(quote!(self), field);
            let rhs = with_ref(&member(quote!(rhs), field), rhs_is_ref);
            let rhs_ty = with_ref(field_ty, rhs_is_ref);
            exprs.push(quote!(<#field_ty as #trait_<#rhs_ty>>::#func_name(&mut #lhs, #rhs)));
            field.push_bounds_to(use_bounds, kind, &mut wcb);
        }
        let wheres = wcb.build(|ty| match rhs_is_ref {
            true => parse_quote!(for<'a> #ty : #trait_<&'a #ty>),
            false => parse_quote!(#ty : #trait_<#ty>),
        });
        quote! {
            impl #impl_g #trait_<#rhs_ty> for #this_ty #wheres {
                fn #func_name(&mut self, rhs: #rhs_ty) {
                    #(#exprs;)*
                }
            }
        }
    };
    let mut ts = TokenStream::new();
    for rhs_is_ref in [false, true] {
        ts.extend(build(rhs_is_ref));
    }
    Ok(ts)
}
fn build_unary_op(
    item: &ItemStruct,
    op: UnaryOp,
    e: &DeriveEntry,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::UnaryOp(op);
    let (_, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let generics = expand_self(&item.generics, &this_ty);
    let (impl_g, _, _) = generics.split_for_impl();
    let trait_ = kind.to_path();
    let func_name = format_ident!("{}", op.to_func_name());

    let build = |lhs_is_ref: bool| {
        let self_ty = with_ref(&this_ty, lhs_is_ref);
        let mut wcb = WhereClauseBuilder::new(&generics);
        let use_bounds = e.push_bounds_to(&mut wcb);
        let mut values = Vec::new();
        for field in fields {
            let field_ty = &field.field.ty;
            let lhs = with_ref(&member(quote!(self), field), lhs_is_ref);
            let lhs_ty = with_ref(field_ty, lhs_is_ref);
            values.push(quote!(<#lhs_ty as #trait_>::#func_name(#lhs)));
            field.push_bounds_to(use_bounds, kind, &mut wcb);
        }
        let ctor_args = build_ctor_args(&item.fields, &values);
        let wheres = wcb.build(|ty| match lhs_is_ref {
            true => quote!(for<'a> &'a #ty : #trait_<Output = #ty>),
            false => quote!(#ty : #trait_<Output = #ty>),
        });
        quote! {
            impl #impl_g #trait_ for #self_ty #wheres {
                type Output = #this_ty;
                fn #func_name(self) -> Self::Output {
                    #this_ty_ident #ctor_args
                }
            }
        }
    };
    let mut ts = TokenStream::new();
    for lhs_is_ref in [false, true] {
        ts.extend(build(lhs_is_ref));
    }
    Ok(ts)
}
fn build_clone_for_struct(
    item: &ItemStruct,
    e: &DeriveEntry,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Clone;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to(&mut wcb);
    let mut ctor_args = Vec::new();
    let mut clone_from_exprs = Vec::new();
    for field in fields {
        let field_ty = &field.field.ty;
        let lhs = &member(quote!(self), field);
        let rhs = &member(quote!(source), field);
        ctor_args.push(quote!(<#field_ty as #trait_>::clone(&#lhs)));
        clone_from_exprs.push(quote!(<#field_ty as #trait_>::clone_from(&mut #lhs, &#rhs)));
        field.push_bounds_to(use_bounds, kind, &mut wcb);
    }
    let ctor_args = build_ctor_args(&item.fields, &ctor_args);
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            fn clone(&self) -> Self {
                #this_ty_ident #ctor_args
            }
            fn clone_from(&mut self, source: &Self) {
                #(#clone_from_exprs;)*
            }
        }
    })
}
fn build_clone_for_enum(
    item: &ItemEnum,
    e: &DeriveEntry,
    variants: &[VariantEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Clone;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to(&mut wcb);
    let mut arms_clone = Vec::new();
    let mut arms_clone_from = Vec::new();
    for variant in variants {
        let variant_ident = &variant.variant.ident;
        let mut pat_args_l = Vec::new();
        let mut pat_args_r = Vec::new();
        let mut ctor_args = Vec::new();
        let mut clone_from_exprs = Vec::new();
        let use_bounds = variant.hattrs.push_bounds_to(use_bounds, kind, &mut wcb);
        for field in &variant.fields {
            let field_ty = &field.field.ty;
            let lhs = field.make_ident("l");
            let rhs = field.make_ident("r");
            pat_args_l.push(quote!(#lhs));
            pat_args_r.push(quote!(#rhs));
            ctor_args.push(quote!(<#field_ty as #trait_>::clone(#lhs)));
            clone_from_exprs.push(quote!(<#field_ty as #trait_>::clone_from(#lhs, #rhs)));
            field.push_bounds_to(use_bounds, kind, &mut wcb);
        }

        let pat_l = build_ctor_args(&variant.variant.fields, &pat_args_l);
        let pat_r = build_ctor_args(&variant.variant.fields, &pat_args_r);
        let ctor_args = build_ctor_args(&variant.variant.fields, &ctor_args);

        arms_clone.push(quote!(Self::#variant_ident #pat_l => Self::#variant_ident #ctor_args));
        arms_clone_from.push(quote! {
            (Self::#variant_ident #pat_l , Self::#variant_ident #pat_r) => {
                #(#clone_from_exprs;)*
            }
        });
    }
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            fn clone(&self) -> Self {
                match self {
                    #(#arms_clone,)*
                }
            }
            fn clone_from(&mut self, source: &Self) {
                match (self, source) {
                    #(#arms_clone_from,)*
                    (lhs, rhs) => *lhs = <Self as ::core::clone::Clone>::clone(rhs),
                }
            }
        }
    })
}
fn build_copy_for_struct(
    item: &ItemStruct,
    e: &DeriveEntry,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Copy;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to(&mut wcb);
    for field in fields {
        field.push_bounds_to(use_bounds, kind, &mut wcb);
    }
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {}
    })
}
fn build_copy_for_enum(
    item: &ItemEnum,
    e: &DeriveEntry,
    variants: &[VariantEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Copy;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to(&mut wcb);
    for variant in variants {
        for field in &variant.fields {
            field.push_bounds_to(use_bounds, kind, &mut wcb);
        }
    }
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {}
    })
}

fn build_debug_for_struct(
    item: &ItemStruct,
    e: &DeriveEntry,
    hattrs: &HelperAttributes,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Debug;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to_with(hattrs, kind, &mut wcb);
    let to_expr = |field: &FieldEntry| {
        let member = field.member();
        quote!(&self.#member)
    };
    let expr = build_debug_expr(
        this_ty_ident,
        &item.fields,
        fields,
        use_bounds,
        to_expr,
        &mut wcb,
    )?;
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                #expr
            }
        }
    })
}
fn build_debug_for_enum(
    item: &ItemEnum,
    e: &DeriveEntry,
    hattrs: &HelperAttributes,
    variants: &[VariantEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Debug;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to_with(hattrs, kind, &mut wcb);
    let mut arms = Vec::new();
    for variant in variants {
        let variant_ident = &variant.variant.ident;
        let use_bounds = variant.hattrs.push_bounds_to(use_bounds, kind, &mut wcb);
        let to_expr = |field: &FieldEntry| {
            let var = field.make_ident("");
            quote!(#var)
        };
        let mut pat_args = Vec::new();
        for field in &variant.fields {
            let var = field.make_ident("");
            pat_args.push(quote!(#var));
        }
        let expr = build_debug_expr(
            variant_ident,
            &variant.variant.fields,
            &variant.fields,
            use_bounds,
            to_expr,
            &mut wcb,
        )?;
        let pat = build_ctor_args(&variant.variant.fields, &pat_args);
        arms.push(quote!(Self::#variant_ident #pat => #expr));
    }
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
                match self {
                    #(#arms,)*
                }
            }
        }
    })
}
fn build_debug_expr(
    ident: &Ident,
    fields_source: &Fields,
    fields: &[FieldEntry],
    use_bounds: bool,
    to_expr: impl Fn(&FieldEntry) -> TokenStream,
    wcb: &mut WhereClauseBuilder,
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Debug;
    let mut transparent_field = None;
    for field in fields {
        if let Some(a) = &field.hattrs.debug {
            if let Some(span) = a.transparent.span {
                if transparent_field.is_some() {
                    bail!(span, "only one field can be set `#[debug(transparent)]`");
                }
                transparent_field = Some(field);
            }
        }
    }
    let expr = if let Some(field) = transparent_field {
        field.push_bounds_to(use_bounds, kind, wcb);
        let e = to_expr(field);
        quote!(::core::fmt::Debug::fmt(#e, f))
    } else {
        let is_named = match fields_source {
            Fields::Named(_) => true,
            Fields::Unnamed(_) | Fields::Unit => false,
        };
        let mut expr = TokenStream::new();
        let debug_x = match is_named {
            true => quote!(debug_struct),
            false => quote!(debug_tuple),
        };
        expr.extend(quote!(f.#debug_x(::core::stringify!(#ident))));
        for field in fields {
            if !field.hattrs.is_debug_ignore() {
                let e = to_expr(field);
                let member = field.member();
                expr.extend(match is_named {
                    true => quote! (.field(::core::stringify!(#member), #e)),
                    false => quote! (.field(#e)),
                });
                field.push_bounds_to(use_bounds, kind, wcb);
            }
        }
        expr.extend(quote!(.finish()));
        expr
    };
    Ok(expr)
}

fn build_default_for_struct(
    item: &ItemStruct,
    e: &DeriveEntry,
    hattrs: &HelperAttributes,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Default;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let use_bounds = e.push_bounds_to_with(hattrs, kind, &mut wcb);
    let value = if let Some(a) = &hattrs.default {
        a.value.as_ref()
    } else {
        None
    };
    let value = if let Some(value) = value {
        quote!(#value)
    } else {
        let ctor_args = build_default_ctor_args(&item.fields, fields, use_bounds, &mut wcb)?;
        quote!(#this_ty_ident #ctor_args)
    };
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            fn default() -> Self {
                #value
            }
        }
    })
}

fn build_default_for_enum(
    item: &ItemEnum,
    e: &DeriveEntry,
    hattrs: &HelperAttributes,
    variants: &[VariantEntry],
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Default;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    let mut use_bounds = e.push_bounds_to_with(hattrs, kind, &mut wcb);
    let value = if let Some(value) = hattrs.default_value() {
        quote!(#value)
    } else {
        let vs: Vec<_> = variants
            .iter()
            .filter_map(|v| Some((v, v.hattrs.default.as_ref()?)))
            .collect();
        let a_default = HelperAttributeForDefault::default();
        let (v, a) = match vs.len() {
            0 => {
                if variants.len() == 1 {
                    (&variants[0], &a_default)
                } else {
                    bail!(_, "variant with `#[default(...)]` does not exist.")
                }
            }
            1 => vs[0],
            _ => {
                let names: Vec<String> = vs
                    .iter()
                    .map(|variant| variant.0.variant.ident.to_string())
                    .collect();

                bail!(
                    vs[0].0.variant.span(),
                    "there are multiple variants with `#[default(...)]` ({})",
                    names.join(", "),
                )
            }
        };
        use_bounds = v.hattrs.push_bounds_to(use_bounds, kind, &mut wcb);
        if let Some(value) = &a.value {
            bail!(
                value.span(),
                "`#[default(...)]` on a variant cannot specify a default value"
            )
        }
        let ctor_args =
            build_default_ctor_args(&v.variant.fields, &v.fields, use_bounds, &mut wcb)?;
        let variant_ident = &v.variant.ident;
        quote!(#this_ty_ident::#variant_ident #ctor_args)
    };
    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            fn default() -> Self {
                #value
            }
        }
    })
}
fn build_default_ctor_args(
    fields_source: &Fields,
    fields: &[FieldEntry],
    use_bounds: bool,
    wcb: &mut WhereClauseBuilder,
) -> Result<TokenStream> {
    let kind = DeriveItemKind::Default;
    let trait_ = kind.to_path();
    let mut ctor_args = Vec::new();
    for field in fields {
        let value = field.hattrs.default_value();
        if field.hattrs.push_bounds_to(use_bounds, kind, wcb) && value.is_none() {
            wcb.push_bounds_for_field(field.field)
        }
        let value = if let Some(value) = value {
            value.to_token_stream()
        } else {
            let field_ty = &field.field.ty;
            quote!(<#field_ty as #trait_>::default())
        };
        ctor_args.push(value);
    }
    Ok(build_ctor_args(fields_source, &ctor_args))
}

fn build_deref_for_struct(
    item: &ItemStruct,
    e: &DeriveEntry,
    fields: &[FieldEntry],
) -> Result<TokenStream> {
    let kind = e.kind;
    let (impl_g, type_g, _) = item.generics.split_for_impl();
    let this_ty_ident = &item.ident;
    let this_ty: Type = parse_quote!(#this_ty_ident #type_g);
    let trait_ = kind.to_path();

    let mut wcb = WhereClauseBuilder::new(&item.generics);
    e.push_bounds_to(&mut wcb);

    if fields.len() != 1 {
        bail!(
            Span::call_site(),
            "`#[deirve_ex({})]` supports only single field struct.",
            kind
        );
    }
    let target_ty = &fields[0].field.ty;
    let member = fields[0].member();

    let content = match kind {
        DeriveItemKind::Deref => {
            quote! {
                type Target = #target_ty;
                fn deref(&self) -> & #target_ty {
                    &self.#member
                }
            }
        }
        DeriveItemKind::DerefMut => {
            quote! {
                fn deref_mut(&mut self) -> &mut #target_ty {
                    &mut self.#member
                }
            }
        }
        _ => unreachable!(),
    };

    let wheres = wcb.build(|ty| quote!(#ty : #trait_));
    Ok(quote! {
        impl #impl_g #trait_ for #this_ty #wheres {
            #content
        }
    })
}

fn with_ref(source: &impl ToTokens, is_ref: bool) -> TokenStream {
    if is_ref {
        quote!(&#source)
    } else {
        quote!(#source)
    }
}
fn build_ctor_args(fields: &Fields, values: &[TokenStream]) -> TokenStream {
    match fields {
        Fields::Named(fields) => {
            let names = fields.named.iter().map(|f| f.ident.as_ref().unwrap());
            quote!({ #(#names: #values,)* })
        }
        Fields::Unnamed(_) => quote!((#(#values,)*)),
        Fields::Unit => quote!(),
    }
}
fn member(this: TokenStream, field: &FieldEntry) -> TokenStream {
    let member = field.member();
    quote!(#this.#member)
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
enum UnaryOp {
    Neg,
    Not,
}

impl UnaryOp {
    fn from_str(s: &str) -> Option<Self> {
        Some(match s {
            "Neg" => Self::Neg,
            "Not" => Self::Not,
            _ => return None,
        })
    }
    fn to_str(self) -> &'static str {
        match self {
            UnaryOp::Neg => "Neg",
            UnaryOp::Not => "Not",
        }
    }
    fn to_func_name(self) -> &'static str {
        match self {
            UnaryOp::Neg => "neg",
            UnaryOp::Not => "not",
        }
    }
}
impl std::fmt::Display for UnaryOp {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.to_str())
    }
}

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
enum DeriveItemKind {
    BinaryOp(BinaryOp),
    AssignOp(BinaryOp),
    UnaryOp(UnaryOp),
    Copy,
    Clone,
    Debug,
    Default,
    Deref,
    DerefMut,
    // Index,
    // IndexMut,
    // AsRef,
    // AsMut,
    // From,
    // Into,
    // TryInto,
}

impl DeriveItemKind {
    fn from_str(s: &str) -> Option<Self> {
        if let Some(s) = s.strip_suffix("Assign") {
            return Some(Self::AssignOp(BinaryOp::from_str(s)?));
        }
        if let Some(value) = BinaryOp::from_str(s) {
            return Some(Self::BinaryOp(value));
        }
        if let Some(value) = UnaryOp::from_str(s) {
            return Some(Self::UnaryOp(value));
        }
        Some(match s {
            "Copy" => Self::Copy,
            "Clone" => Self::Clone,
            "Debug" => Self::Debug,
            "Default" => Self::Default,
            "Deref" => Self::Deref,
            "DerefMut" => Self::DerefMut,
            // "Index" => Self::Index,
            // "IndexMut" => Self::IndexMut,
            // "AsRef" => Self::AsRef,
            // "AsMut" => Self::AsMut,
            // "From" => Self::From,
            // "Into" => Self::Into,
            // "TryInto" => Self::TryInto,
            _ => return None,
        })
    }
    fn from_ident(s: &Ident) -> Result<Self> {
        let span = s.span();
        let s = s.to_string();
        if let Some(value) = Self::from_str(&s) {
            Ok(value)
        } else {
            bail!(span, "unsupported trait");
        }
    }

    fn to_path(self) -> Path {
        match self {
            DeriveItemKind::BinaryOp(op) => {
                let ident = format_ident!("{}", op.to_str());
                parse_quote!(::core::ops::#ident)
            }
            DeriveItemKind::AssignOp(op) => {
                let ident = format_ident!("{}Assign", op.to_str());
                parse_quote!(::core::ops::#ident)
            }
            DeriveItemKind::UnaryOp(op) => {
                let ident = format_ident!("{}", op.to_str());
                parse_quote!(::core::ops::#ident)
            }
            DeriveItemKind::Copy => parse_quote!(::core::marker::Copy),
            DeriveItemKind::Clone => parse_quote!(::core::clone::Clone),
            DeriveItemKind::Debug => parse_quote!(::core::fmt::Debug),
            DeriveItemKind::Default => parse_quote!(::core::default::Default),
            DeriveItemKind::Deref => parse_quote!(::core::ops::Deref),
            DeriveItemKind::DerefMut => parse_quote!(::core::ops::DerefMut),
        }
    }
}
impl std::fmt::Display for DeriveItemKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            DeriveItemKind::BinaryOp(op) => write!(f, "{}", op),
            DeriveItemKind::AssignOp(op) => write!(f, "{}Assign", op),
            DeriveItemKind::UnaryOp(op) => write!(f, "{}", op),
            DeriveItemKind::Copy => write!(f, "Copy"),
            DeriveItemKind::Clone => write!(f, "Clone"),
            DeriveItemKind::Debug => write!(f, "Debug"),
            DeriveItemKind::Default => write!(f, "Default"),
            DeriveItemKind::Deref => write!(f, "Deref"),
            DeriveItemKind::DerefMut => write!(f, "DerefMut"),
        }
    }
}

struct DeriveEntry {
    kind: DeriveItemKind,
    span: Span,
    dump: bool,
    bounds_this: Bounds,
    bounds_common: Bounds,
}
impl DeriveEntry {
    fn from_root(attr: TokenStream, attrs: &[Attribute]) -> Result<Vec<Self>> {
        let mut args_list = vec![parse2(attr)?];
        args_list.extend(parse_derive_ex_attrs(attrs)?);
        Self::from_args_list(&args_list)
    }
    fn from_args_list(args_list: &[Args]) -> Result<Vec<Self>> {
        let mut results = Vec::new();
        for a in args_list {
            for item in &a.items {
                let (dump, bounds_this) =
                    if let DeriveItemArgsOption::Some { args, .. } = &item.args {
                        (args.dump, Bounds::from(&args.bound))
                    } else {
                        (false, Bounds::new())
                    };
                results.push(Self {
                    kind: DeriveItemKind::from_ident(&item.trait_ident)?,
                    span: item.trait_ident.span(),
                    dump: a.dump | dump,
                    bounds_this,
                    bounds_common: Bounds::from(&a.bound),
                });
            }
        }
        Ok(results)
    }

    fn push_bounds_to(&self, wcb: &mut WhereClauseBuilder) -> bool {
        let mut use_bounds = wcb.push_bounds(&self.bounds_this);
        if use_bounds {
            use_bounds = wcb.push_bounds(&self.bounds_common);
        }
        use_bounds
    }
    fn push_bounds_to_with(
        &self,
        hattrs: &HelperAttributes,
        kind: DeriveItemKind,
        wcb: &mut WhereClauseBuilder,
    ) -> bool {
        let mut use_bounds = hattrs.push_bounds_to(true, kind, wcb);
        if use_bounds {
            use_bounds = wcb.push_bounds(&self.bounds_this)
        }
        if use_bounds {
            use_bounds = wcb.push_bounds(&self.bounds_common);
        }
        use_bounds
    }

    fn apply_dump(&self, result: Result<TokenStream>) -> TokenStream {
        match (result, self.dump) {
            (Ok(ts), false) => ts,
            (Ok(ts), true) => Error::new(self.span, format!("dump:\n{}", ts)).to_compile_error(),
            (Err(e), _) => e.to_compile_error(),
        }
    }
}

struct VariantEntry<'a> {
    variant: &'a Variant,
    fields: Vec<FieldEntry<'a>>,
    hattrs: HelperAttributes,
}

impl<'a> VariantEntry<'a> {
    fn new(variant: &'a Variant, kinds: &HelperAttributeKinds) -> Result<Self> {
        Ok(Self {
            variant,
            fields: FieldEntry::from_fields(&variant.fields, kinds)?,
            hattrs: HelperAttributes::from_attrs(&variant.attrs, kinds)?,
        })
    }
    fn from_variants(
        variants: impl IntoIterator<Item = &'a Variant>,
        kinds: &HelperAttributeKinds,
    ) -> Result<Vec<Self>> {
        variants
            .into_iter()
            .map(|variant| Self::new(variant, kinds))
            .collect()
    }
}

struct FieldEntry<'a> {
    index: usize,
    field: &'a Field,
    hattrs: HelperAttributes,
}

impl<'a> FieldEntry<'a> {
    fn new(index: usize, field: &'a Field, kinds: &HelperAttributeKinds) -> Result<Self> {
        Ok(Self {
            index,
            field,
            hattrs: HelperAttributes::from_attrs(&field.attrs, kinds)?,
        })
    }
    fn from_fields(fields: &'a Fields, kinds: &HelperAttributeKinds) -> Result<Vec<Self>> {
        fields
            .iter()
            .enumerate()
            .map(|(index, field)| Self::new(index, field, kinds))
            .collect()
    }

    fn member(&self) -> TokenStream {
        if let Some(ident) = &self.field.ident {
            quote!(#ident)
        } else {
            let index = Index::from(self.index);
            quote!(#index)
        }
    }
    fn make_ident(&self, prefix: &str) -> Ident {
        if let Some(ident) = &self.field.ident {
            format_ident!("{}_{}", prefix, ident)
        } else {
            format_ident!("{}_{}", prefix, self.index)
        }
    }
    fn push_bounds_to(&self, use_bounds: bool, kind: DeriveItemKind, wcb: &mut WhereClauseBuilder) {
        if self.hattrs.push_bounds_to(use_bounds, kind, wcb) {
            wcb.push_bounds_for_field(self.field)
        }
    }
}

#[derive(Debug, Copy, Clone)]
struct HelperAttributeKinds {
    derive_ex: bool,
    default: bool,
    debug: bool,
}

impl HelperAttributeKinds {
    fn new(derive_ex: bool) -> Self {
        Self {
            derive_ex,
            default: false,
            debug: false,
        }
    }
    fn extend(&mut self, es: &[DeriveEntry]) {
        for e in es {
            match e.kind {
                DeriveItemKind::Default => self.default = true,
                DeriveItemKind::Debug => self.debug = true,
                _ => {}
            }
        }
    }

    fn is_match(&self, attr: &Attribute) -> bool {
        let p = &attr.path;
        (self.derive_ex && p.is_ident("derive_ex"))
            || (self.default && p.is_ident("default"))
            || (self.debug && p.is_ident("debug"))
    }

    fn without_derive_ex(&self) -> HelperAttributeKinds {
        HelperAttributeKinds {
            derive_ex: false,
            ..*self
        }
    }
}

struct HelperAttributes {
    items: HashMap<DeriveItemKind, DeriveEntry>,
    default: Option<HelperAttributeForDefault>,
    debug: Option<HelperAttributeForDebug>,
}

impl HelperAttributes {
    fn from_attrs(attrs: &[Attribute], kinds: &HelperAttributeKinds) -> Result<Self> {
        let items = if kinds.derive_ex {
            DeriveEntry::from_args_list(&parse_derive_ex_attrs(attrs)?)?
                .into_iter()
                .map(|x| (x.kind, x))
                .collect()
        } else {
            HashMap::new()
        };
        let default = if kinds.default {
            HelperAttributeForDefault::from_attrs(attrs)?
        } else {
            None
        };
        let debug = if kinds.debug {
            HelperAttributeForDebug::from_attrs(attrs)?
        } else {
            None
        };
        Ok(Self {
            items,
            default,
            debug,
        })
    }

    #[must_use]
    fn push_bounds_to(
        &self,
        mut use_bounds: bool,
        kind: DeriveItemKind,
        wcb: &mut WhereClauseBuilder,
    ) -> bool {
        if use_bounds && kind == DeriveItemKind::Default {
            if let Some(a) = &self.default {
                use_bounds = wcb.push_bounds(&a.bounds)
            }
        }
        if use_bounds && kind == DeriveItemKind::Debug {
            if let Some(a) = &self.debug {
                use_bounds = wcb.push_bounds(&a.bounds)
            }
        }
        if use_bounds {
            if let Some(a) = self.items.get(&kind) {
                use_bounds = a.push_bounds_to(wcb);
            }
        }
        use_bounds
    }
    fn default_value(&self) -> Option<&Expr> {
        if let Some(a) = &self.default {
            a.value.as_ref()
        } else {
            None
        }
    }
    fn is_debug_ignore(&self) -> bool {
        if let Some(a) = &self.debug {
            a.ignore.value()
        } else {
            false
        }
    }
}

#[derive(StructMeta, Debug, Default)]
struct ArgsForDebug {
    transparent: Flag,
    ignore: Flag,
    bound: Option<NameArgs<Vec<Bound>>>,
}

#[derive(Default)]
struct HelperAttributeForDebug {
    transparent: Flag,
    ignore: Flag,
    bounds: Bounds,
}
impl HelperAttributeForDebug {
    fn from_attrs(attrs: &[Attribute]) -> Result<Option<Self>> {
        if let Some(args) = parse_single::<ArgsForDebug>(attrs, "debug")? {
            Ok(Some(Self {
                transparent: args.transparent,
                ignore: args.ignore,
                bounds: Bounds::from(&args.bound),
            }))
        } else {
            Ok(None)
        }
    }
}

#[derive(StructMeta, Debug)]
struct ArgsForDefault {
    #[struct_meta(unnamed)]
    value: Expr,
    bound: Option<NameArgs<Vec<Bound>>>,
}
impl Default for ArgsForDefault {
    fn default() -> Self {
        Self {
            value: parse_quote!(_),
            bound: None,
        }
    }
}

#[derive(Default)]
struct HelperAttributeForDefault {
    value: Option<Expr>,
    bounds: Bounds,
}

impl HelperAttributeForDefault {
    fn from_attrs(attrs: &[Attribute]) -> Result<Option<Self>> {
        if let Some(args) = parse_single::<ArgsForDefault>(attrs, "default")? {
            let value = if args.value == parse_quote!(_) {
                None
            } else {
                Some(args.value)
            };
            Ok(Some(Self {
                value,
                bounds: Bounds::from(&args.bound),
            }))
        } else {
            Ok(None)
        }
    }
}

fn remove_attrs(attrs: &mut Vec<Attribute>, kinds: &HelperAttributeKinds) {
    attrs.retain(|attr| !kinds.is_match(attr));
}

fn parse_derive_ex_attrs<T: Parse>(attrs: &[Attribute]) -> Result<Vec<T>> {
    let mut items = Vec::new();
    for attr in attrs {
        if attr.path == parse_quote!(derive_ex) {
            items.push(attr.parse_args()?);
        }
    }
    Ok(items)
}
fn parse_single<T: Parse + Default>(attrs: &[Attribute], name: &str) -> Result<Option<T>> {
    let mut item = None;
    for attr in attrs {
        if attr.path.is_ident(name) {
            if item.is_some() {
                bail!(attr.span(), "#[{}] was specified twice", name)
            }
            item = Some(if attr.tokens.is_empty() {
                Default::default()
            } else {
                attr.parse_args()?
            });
        }
    }
    Ok(item)
}