cgp-macro-lib 0.7.0

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

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

pub fn cgp_inherit(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream> {
    let context_struct: ItemStruct = parse2(body)?;

    let preset: SimpleType = parse2(attr)?;

    let type_generics = TypeGenerics::try_from(&context_struct.generics)?;

    let (delegate_impl, is_provider_impl) =
        derive_delegate_preset(&context_struct.ident, &Some(type_generics), &preset)?;

    Ok(quote! {
        #context_struct

        #delegate_impl

        #is_provider_impl
    })
}

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))
}