cgp-macro-lib 0.7.0

Context-generic programming core component macros implemented as a library.
Documentation
use alloc::format;
use std::collections::BTreeMap;

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

use crate::derive_component::derive_component_with_ast;
use crate::parse::{ComponentSpec, Entries};
use crate::type_component::{derive_type_providers, extract_item_type_from_trait};

pub fn cgp_type(attrs: TokenStream, body: TokenStream) -> syn::Result<TokenStream> {
    let mut entries = if let Ok(provider_ident) = parse2::<Ident>(attrs.clone()) {
        BTreeMap::from([("provider".to_owned(), provider_ident.to_token_stream())])
    } else {
        parse2::<Entries>(attrs)?.entries
    };

    let consumer_trait: ItemTrait = syn::parse2(body)?;

    let item_type = extract_item_type_from_trait(&consumer_trait)?.clone();

    entries.entry("provider".into()).or_insert_with(|| {
        let provider_name = Ident::new(
            &format!("{}TypeProvider", item_type.ident),
            item_type.ident.span(),
        );
        parse_quote!( #provider_name )
    });

    let spec = ComponentSpec::from_entries(&entries)?;

    let component = derive_component_with_ast(&spec, consumer_trait)?;

    let type_provider_impls = derive_type_providers(&spec, &component.provider_trait, &item_type)?;

    let out = quote! {
        #component

        #(#type_provider_impls)*
    };

    Ok(out)
}