cgp-component-macro-lib 0.3.0

Context-generic programming core component macros implemented as a library.
Documentation
use syn::punctuated::Punctuated;
use syn::token::Plus;
use syn::{parse_quote, Generics, Ident, ItemImpl, ItemTrait, Type, TypeParamBound};

use crate::delegate_components::ast::DelegateEntriesAst;

pub fn define_delegate_component_trait_bounds(
    target_type: &Type,
    delegate_entries: &DelegateEntriesAst,
) -> Punctuated<TypeParamBound, Plus> {
    let mut trait_bounds: Punctuated<TypeParamBound, Plus> = Punctuated::new();

    for component in delegate_entries.all_components() {
        let component_type = &component.component_type;
        let trait_bound: TypeParamBound = parse_quote!(
            DelegateComponent<#component_type, Delegate = #target_type>
        );
        trait_bounds.push(trait_bound);
    }

    trait_bounds
}

pub fn define_delegates_to_trait(
    trait_name: &Ident,
    target_type: &Type,
    target_generics: &Generics,
    delegate_entries: &DelegateEntriesAst,
) -> (ItemTrait, ItemImpl) {
    let trait_bounds = define_delegate_component_trait_bounds(target_type, delegate_entries);

    let item_trait = parse_quote! {
        pub trait #trait_name #target_generics: #trait_bounds {}
    };

    let mut impl_generics = target_generics.clone();
    impl_generics.params.push(parse_quote!(Components));

    let type_generics = target_generics.split_for_impl().1;

    let item_impl = parse_quote! {
        impl #impl_generics #trait_name #type_generics  for Components
        where
            Components: #trait_bounds
        {}
    };

    (item_trait, item_impl)
}