bluejay-typegen-codegen 0.4.0

Code generation utilities for `bluejay-typegen-macro`
Documentation
use crate::{
    attributes::doc_string,
    names::{enum_variant_ident, type_ident},
    CodeGenerator,
};
use bluejay_core::{
    definition::{EnumTypeDefinition, EnumValueDefinition, SchemaDefinition},
    AsIter,
};
use syn::parse_quote;

pub(crate) struct EnumTypeDefinitionBuilder<'a, S: SchemaDefinition, C: CodeGenerator> {
    enum_type_definition: &'a S::EnumTypeDefinition,
    code_generator: &'a C,
}

impl<'a, S: SchemaDefinition, C: CodeGenerator> EnumTypeDefinitionBuilder<'a, S, C> {
    pub(crate) fn build(
        enum_type_definition: &'a S::EnumTypeDefinition,
        code_generator: &'a C,
    ) -> Vec<syn::Item> {
        let instance = Self {
            enum_type_definition,
            code_generator,
        };

        let name_ident = instance.name_ident();
        let attributes = instance.attributes();
        let other_variant = instance.other_variant();

        let variants: Vec<syn::Variant> = instance
            .enum_type_definition
            .enum_value_definitions()
            .iter()
            .map(|evd| {
                let variant_ident = enum_variant_ident(evd.name());
                let description_attribute = evd.description().map(doc_string);
                let other_attributes = instance.code_generator.attributes_for_enum_variant(evd);

                parse_quote! {
                    #description_attribute
                    #(#other_attributes)*
                    #variant_ident
                }
            })
            .collect();

        let mut items = vec![parse_quote! {
            #(#attributes)*
            pub enum #name_ident {
                #(
                    #variants,
                )*
                #other_variant,
            }
        }];

        items.extend(
            instance
                .code_generator
                .additional_impls_for_enum(instance.enum_type_definition)
                .into_iter()
                .map(syn::Item::Impl),
        );

        items
    }

    fn name_ident(&self) -> syn::Ident {
        type_ident(self.enum_type_definition.name())
    }

    fn attributes(&self) -> Vec<syn::Attribute> {
        self.enum_type_definition
            .description()
            .map(doc_string)
            .into_iter()
            .chain(
                self.code_generator
                    .attributes_for_enum(self.enum_type_definition),
            )
            .collect()
    }

    fn other_variant(&self) -> syn::Variant {
        let attributes = self.code_generator.attributes_for_enum_variant_other();
        parse_quote! {
            #(#attributes)*
            Other
        }
    }
}