cgp-macro-lib 0.7.0

Context-generic programming core component macros implemented as a library.
Documentation
use quote::{ToTokens, quote};
use syn::punctuated::Punctuated;
use syn::token::Plus;
use syn::{Type, TypeParamBound, WherePredicate, parse_quote, parse2};

use crate::cgp_impl::use_provider::UseProviderSpec;

pub fn derive_provider_bounds(
    context_type: &Type,
    spec: &UseProviderSpec,
) -> syn::Result<WherePredicate> {
    let context_type = if spec.context_type == parse_quote! { Self } {
        context_type
    } else {
        &spec.context_type
    };

    let provider_type = &spec.provider_type;
    let mut bounds = Punctuated::<TypeParamBound, Plus>::new();

    for bound in &spec.provider_trait_bounds {
        let trait_ident = &bound.name;
        let mut m_generics = bound.generics.clone();

        let generics = m_generics.get_or_insert_with(|| parse_quote!(<>));
        generics
            .args
            .insert(0, parse2(context_type.to_token_stream())?);

        let trait_bound = parse2(quote! {
            #trait_ident #generics
        })?;
        bounds.push(trait_bound);
    }

    let predicate = parse2(quote! {
        #provider_type: #bounds
    })?;

    Ok(predicate)
}