cgp-component-macro-lib 0.3.0

Context-generic programming core component macros implemented as a library.
Documentation
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{Error, Ident, ItemTrait};

use crate::derive_component::component_spec::ComponentSpec;
use crate::derive_component::derive::derive_component_with_ast;
use crate::getter_component::blanket::derive_blanket_impl;
use crate::getter_component::getter_field::GetterField;
use crate::getter_component::parse::parse_getter_fields;
use crate::getter_component::use_field::derive_use_field_impl;
use crate::getter_component::use_fields::derive_use_fields_impl;
use crate::getter_component::with_provider::derive_with_provider_impl;

pub fn derive_getter_component(attr: TokenStream, body: TokenStream) -> syn::Result<TokenStream> {
    let spec: ComponentSpec = syn::parse2(attr)?;
    let consumer_trait: ItemTrait = syn::parse2(body)?;

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

    let fields = parse_getter_fields(&spec.context_type, &consumer_trait)?;

    let use_fields_impl = derive_use_fields_impl(&spec, &consumer_trait, &fields);

    let m_field: Option<[GetterField; 1]> = fields.try_into().ok();

    let mut derived = quote! {
        #derived_component

        #use_fields_impl
    };

    if let Some([field]) = m_field {
        let use_field_impl = derive_use_field_impl(&spec, &consumer_trait, &field);
        let use_provider_impl = derive_with_provider_impl(&spec, &consumer_trait, &field);

        derived.extend(use_field_impl);
        derived.extend(use_provider_impl);
    }

    Ok(derived)
}

pub fn derive_auto_getter_component(
    attr: TokenStream,
    body: TokenStream,
) -> syn::Result<TokenStream> {
    if !attr.is_empty() {
        return Err(Error::new(
            Span::call_site(),
            "#[derive_auto_getter] does not accept any attribute argument",
        ));
    }

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

    let context_type = Ident::new("Context", Span::call_site());

    let fields = parse_getter_fields(&context_type, &consumer_trait)?;

    let blanket_impl = derive_blanket_impl(&context_type, &consumer_trait, &fields);

    Ok(quote! {
        #consumer_trait
        #blanket_impl
    })
}