cgp-macro-lib 0.6.1

Context-generic programming core component macros implemented as a library.
Documentation
use quote::quote;
use syn::{Ident, ItemImpl, ItemStruct, parse_quote, parse2};

use crate::parse::{SimpleType, TypeGenerics};

pub fn derive_has_components(
    provider_name: &Ident,
    provider_generics: &Option<TypeGenerics>,
    context_struct: &ItemStruct,
) -> syn::Result<ItemImpl> {
    let context_name = &context_struct.ident;

    let mut generics = context_struct.generics.clone();
    generics.params.insert(0, parse2(quote! { __Name__ })?);

    let (impl_generics, _, _) = generics.split_for_impl();
    let (_, ty_generics, where_clause) = context_struct.generics.split_for_impl();

    parse2(quote! {
        impl #impl_generics DelegateComponent<__Name__> for #context_name #ty_generics
            #where_clause
        {
            type Delegate = #provider_name #provider_generics;
        }
    })
}

pub fn derive_delegate_preset(
    provider_name: &Ident,
    provider_generics: &Option<TypeGenerics>,
    preset: &SimpleType,
) -> syn::Result<(ItemImpl, ItemImpl)> {
    let preset_name = &preset.name;
    let preset_generics = &preset.generics;

    let provider_params = match provider_generics {
        Some(generics) => {
            let params = &generics.generics.params;
            quote! {
                , #params
            }
        }
        None => quote! {},
    };

    let preset_trait_name = quote! {
        #preset_name :: IsPreset
    };

    let preset_provider_name = quote! {
        #preset_name :: Components #preset_generics
    };

    let delegate_impl: ItemImpl = parse_quote! {
        impl< __Name__ #provider_params >
            DelegateComponent<__Name__>
            for #provider_name #provider_generics
        where
            Self: #preset_trait_name < __Name__ >,
            #preset_provider_name: DelegateComponent<__Name__>,
        {
            type Delegate = <#preset_provider_name as DelegateComponent<__Name__>>::Delegate;
        }
    };

    let is_provider_impl: ItemImpl = parse_quote! {
        impl<__Name__, __Context__, __Params__ #provider_params >
            IsProviderFor<__Name__, __Context__, __Params__>
            for #provider_name #provider_generics
        where
            Self: #preset_trait_name < __Name__ >,
            #preset_provider_name: IsProviderFor<__Name__, __Context__, __Params__>,
        {
        }
    };

    Ok((delegate_impl, is_provider_impl))
}