dynamic-graphql-derive 0.10.2

Dynamic GraphQL schema macro
Documentation
use darling::FromMeta;
use darling::ast::NestedMeta;
use proc_macro2::Span;
use quote::ToTokens;
use quote::quote;
use syn::spanned::Spanned;

use crate::utils::meta_match::MatchMetaPath;
use crate::utils::meta_match::MatchNestedMetaList;

#[derive(Debug, Clone)]
pub struct RegisterAttr {
    pub path: syn::Path,
    #[allow(dead_code)]
    pub span: Span,
}

struct MatchRegister(MatchMetaPath);

impl MatchNestedMetaList for MatchRegister {
    fn match_nested_meta_list(list: &[NestedMeta]) -> Option<darling::Result<Self>>
    where
        Self: Sized,
    {
        let inner = <(MatchMetaPath,)>::match_nested_meta_list(list);
        inner.map(|r| r.map(|(r1,)| MatchRegister(r1)))
    }
}

impl FromMeta for RegisterAttr {
    fn from_list(items: &[NestedMeta]) -> darling::Result<Self> {
        let implements = MatchRegister::match_nested_meta_list(items);
        if let Some(r) = implements {
            return r.map(|r| {
                let span = r.0.span();
                RegisterAttr { path: r.0.0, span }
            });
        }

        Err(darling::Error::custom("Invalid register attribute"))
    }
}

impl ToTokens for RegisterAttr {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        let path = &self.path;
        tokens.extend(quote! {
            let registry = registry.register::<#path>();
        });
    }
}

impl RegisterAttr {
    pub fn with_generic(&mut self, ty: syn::Type) {
        if let Some(segment) = self.path.segments.last_mut() {
            let mut args = syn::punctuated::Punctuated::new();
            args.push(syn::GenericArgument::Type(ty));
            segment.arguments =
                syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
                    colon2_token: None,
                    lt_token: syn::token::Lt::default(),
                    args,
                    gt_token: syn::token::Gt::default(),
                });
        }
    }
}