cgp-component-macro-lib 0.3.0

Context-generic programming core component macros implemented as a library.
Documentation
use alloc::format;
use alloc::string::ToString;

use proc_macro2::{Span, TokenStream};
use quote::ToTokens;
use syn::{parse_quote, Ident, ItemTrait};

use crate::delegate_components::define_struct::define_struct;
use crate::delegate_components::delegates_to::define_delegates_to_trait;
use crate::delegate_components::impl_delegate::impl_delegate_components;
use crate::derive_component::snake_case::to_snake_case_str;
use crate::preset::ast::DefinePresetAst;
use crate::preset::impl_is_preset::impl_components_is_preset;
use crate::preset::substitution_macro::define_substitution_macro;

pub fn define_preset(body: TokenStream) -> syn::Result<TokenStream> {
    let ast: DefinePresetAst = syn::parse2(body)?;

    let preset_ident = &ast.preset_ident;

    let preset_type = {
        let type_generics = ast.preset_generics.split_for_impl().1;
        parse_quote!( #preset_ident #type_generics )
    };

    let preset_trait_name = Ident::new(&format!("Is{}", preset_ident), preset_ident.span());

    let preset_trait: ItemTrait = parse_quote! {
        pub trait #preset_trait_name <Component> {}
    };

    let impl_delegate_items =
        impl_delegate_components(&preset_type, &ast.preset_generics, &ast.delegate_entries);

    let impl_is_reset_items = impl_components_is_preset(
        &preset_trait_name,
        &preset_type,
        &ast.preset_generics,
        &ast.delegate_entries,
    );

    let item_struct = define_struct(&ast.preset_ident, &ast.preset_generics);

    let mut output = TokenStream::new();

    output.extend(item_struct.to_token_stream());

    output.extend(preset_trait.to_token_stream());

    for impl_item in impl_delegate_items {
        output.extend(impl_item.to_token_stream());
    }

    for impl_item in impl_is_reset_items {
        output.extend(impl_item.to_token_stream());
    }

    {
        let delegates_to_trait_name = format!("DelegatesTo{}", ast.preset_ident);

        let (delegates_to_trait, delegates_to_impl) = define_delegates_to_trait(
            &Ident::new(&delegates_to_trait_name, Span::call_site()),
            &preset_type,
            &ast.preset_generics,
            &ast.delegate_entries,
        );

        output.extend(delegates_to_trait.to_token_stream());
        output.extend(delegates_to_impl.to_token_stream());
    }

    {
        let with_components_macro_name =
            format!("with_{}", to_snake_case_str(&ast.preset_ident.to_string()));

        let with_components_macro = define_substitution_macro(
            &Ident::new(&with_components_macro_name, Span::call_site()),
            &ast.delegate_entries.all_components().to_token_stream(),
        );

        output.extend(with_components_macro);
    }

    Ok(output)
}