cgp-macro-lib 0.6.1

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, TokenStreamExt, 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_alias, derive_type_providers, extract_item_type};

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(&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 alias_type = derive_type_alias(&component.consumer_trait, &spec.context_type, &item_type)?;

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

    let mut out = quote! {
        #component

        #alias_type
    };

    out.append_all(type_provider_impls);

    Ok(out)
}