fromit 0.1.2

A super powerful macro for generating new structs with getters, setters, and `From` or `TryFrom` implementation based on the given struct.
Documentation
use derivit_core::setter::FieldSetter;

use super::*;

pub(crate) fn generate_setters(
  opts: &StructOpts,
  final_generics: &FinalGenerics,
) -> syn::Result<proc_macro2::TokenStream> {
  if opts.setters.ignore {
    return Ok(quote!());
  }
  let mut setters = Vec::new();
  let setters_prefix = opts
    .setters
    .prefix
    .as_ref()
    .cloned()
    .unwrap_or_else(|| format_ident!("set"));

  let mut ctr = 0;
  if let Some(extra) = &opts.extra {
    for field in extra.fields.values() {
      if field.setter.ignore {
        continue;
      }

      let src_name = field
        .name
        .clone()
        .unwrap_or_else(|| format_ident!("{}", ctr));
      ctr += usize::from(field.named);

      let field_name = field.name.as_ref().unwrap_or(&src_name);
      let vis = field.setter.vis.as_ref().unwrap_or_else(|| {
        opts
          .setters
          .vis_all
          .as_ref()
          .unwrap_or_else(|| field.vis.as_ref().unwrap_or(&opts.vis))
      });
      let fn_name = field
        .setter
        .rename
        .clone()
        .unwrap_or_else(|| format_ident!("{}_{}", setters_prefix, field_name));

      setters.push(FieldSetter {
        field_name: field_name.clone(),
        field_ty: field.src_ty.clone(),
        style: field.setter.style.unwrap_or(opts.setters.style),
        vis: vis.clone(),
        fn_name,
        bound: field.setter.bound.bound.clone(),
      });
    }
  }

  for (src_name, field) in opts.fields.iter() {
    if field.skip.is_some() || field.setter.ignore {
      continue;
    }
    let src_name = field.rename.clone().unwrap_or_else(|| {
      if field.named {
        format_ident!("{}", src_name)
      } else {
        format_ident!("{}", ctr)
      }
    });
    ctr += usize::from(field.named);

    let field_name = field.rename.as_ref().unwrap_or(&src_name);
    let vis = field.getter.vis.as_ref().unwrap_or_else(|| {
      opts
        .getters
        .vis_all
        .as_ref()
        .unwrap_or_else(|| field.vis.as_ref().unwrap_or(&opts.vis))
    });
    let fn_name = field
      .setter
      .rename
      .clone()
      .unwrap_or_else(|| format_ident!("{}_{}", setters_prefix, field_name));

    let field_ty = field.typ.as_ref().unwrap_or(&field.src_ty);
    setters.push(FieldSetter {
      field_name: field_name.clone(),
      field_ty: field_ty.clone(),
      style: field.setter.style.unwrap_or(opts.setters.style),
      vis: vis.clone(),
      fn_name,
      bound: field.setter.bound.bound.clone(),
    });
  }

  let name = &opts.name;
  let impl_generics = &final_generics.impl_generics;
  let self_ty_generics = &final_generics.ty_generics;
  let where_clause = &final_generics.where_clause;
  Ok(quote! {
    impl #impl_generics #name #self_ty_generics #where_clause {
      #(#setters)*
    }
  })
}