annotation-rs-codegen 0.1.0

proc-macro lib for annotation-rs
Documentation
use crate::field::Fields;

use helpers::get_mod_path;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, ToTokens};
use syn::{Data, DeriveInput, Error, Ident};

pub struct Annotation {
    ident: Ident,
    path: String,
    fields: Fields,
    mod_path: Option<TokenStream>,
}

impl Annotation {
    pub fn from_ast(input: &DeriveInput) -> Result<Self, Error> {
        match &input.data {
            Data::Struct(data_struct) => {
                let path = input.ident.to_string();

                Ok(Annotation {
                    ident: input.ident.clone(),
                    path,
                    fields: Fields::from_ast(&data_struct.fields)?,
                    mod_path: get_mod_path(&input.attrs)?,
                })
            }
            _ => Err(Error::new_spanned(&input, "Attribute must be a struct")),
        }
    }

    pub fn get_implement(&self) -> TokenStream {
        let name = self.ident.clone();
        let from_attributes_args = self
            .fields
            .parse_attributes_args_token_stream(format_ident!("input"), name.clone());
        let from_meta = self.fields.parse_meta_token_stream(&self.ident);
        let path = self.path.clone();
        let to_token_temp_value = self.fields.get_to_token_temp_value_token_stream();
        let struct_path = match &self.mod_path {
            Some(path) => quote::quote! {
                #path::#name
            },
            None => name.to_token_stream(),
        };
        let to_token = self.fields.get_to_token_token_stream(struct_path);

        quote! {
            impl annotation_rs::AnnotationStructure for #name {
                fn get_path() -> annotation_rs::Symbol {
                    annotation_rs::Symbol::new(#path)
                }

                fn from_meta(
                    input: &syn::Meta
                ) -> Result<Self, syn::Error>
                where
                    Self: std::marker::Sized {
                    #from_meta
                }

                fn from_attribute_args(input: syn::AttributeArgs) -> Result<Self, syn::Error>
                where
                    Self: std::marker::Sized {
                    #from_attributes_args
                }
            }

            impl syn::parse_macro_input::ParseMacroInput for #name {
                fn parse(input: syn::parse::ParseStream) -> Result<Self, syn::Error> {
                    let attribute_args = syn::AttributeArgs::parse(input)?;
                    use annotation_rs::AnnotationStructure;
                    Self::from_attribute_args(attribute_args)
                }
            }

            impl quote::ToTokens for #name {
                 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
                    use quote::TokenStreamExt;
                    #(#to_token_temp_value;)*
                    (quote::quote! {
                        #to_token
                    }).to_tokens(tokens);
                 }
            }
        }
    }
}