enum-helper-derive 0.2.0

Procedural macro implementation for enum-helper
Documentation
use proc_macro2::Span;

use crate::{
    ctxt::Ctxt,
    enum_all::{Ir, VariantIr, attr::VariantAttr},
};

pub fn parse_ir(input: &syn::DeriveInput) -> syn::Result<Ir<'_>> {
    let syn::Data::Enum(data_enum) = &input.data else {
        return Err(syn::Error::new(
            Span::call_site(),
            "EnumAll only supports enum",
        ));
    };

    let cx = Ctxt::new();

    let mut variants = Vec::new();
    let mut is_unit_enum = true;

    for variant in &data_enum.variants {
        let v_ir = parse_variant_ir(&cx, variant);

        let is_unit = matches!(v_ir.fields, syn::Fields::Unit);

        if !v_ir.skip && !is_unit {
            is_unit_enum = false;
        }
        variants.push(v_ir);
    }

    if !is_unit_enum {
        let e = syn::Error::new(
            Span::call_site(),
            "EnumAll only supports unit enum. Consider using `#[enum_all(skip)]` to skip non unit variant",
        );
        cx.syn_error(e);
    };

    cx.check()?;

    Ok(Ir {
        ident: &input.ident,
        generics: &input.generics,
        variants,
    })
}

fn parse_variant_ir(cx: &Ctxt, variant: &syn::Variant) -> VariantIr {
    let ident = variant.ident.clone();

    let attr = VariantAttr::from_attrs(cx, &variant.attrs);

    VariantIr {
        ident,
        fields: variant.fields.clone(),
        skip: attr.skip.get(),
    }
}