mod command;
mod operation;
use crate::derives::validate::command::ValidateCommand;
use proc_macro::TokenStream;
use std::borrow::Borrow;
use crate::parse_attribute::ParseAttribute;
use crate::to_tokenstream::ToTokenStream;
use syn::{spanned::Spanned, Data, Fields};
pub fn impl_validate_macro(ast: &syn::DeriveInput) -> TokenStream {
let target_name = &ast.ident;
let mut commands = Vec::new();
for attr in &ast.attrs {
ValidateCommand::parse_attribute(attr, None, &mut commands);
}
match ast.data.borrow() {
Data::Struct(data) => {
if let Fields::Named(named_fields) = data.fields.borrow() {
for field in &named_fields.named {
for attr in &field.attrs {
ValidateCommand::parse_attribute(attr, Some(field), &mut commands);
}
}
}
}
Data::Enum(data) => {
for variant in data.variants.iter() {
if !variant.attrs.is_empty() {
emit_error!(
variant.span(),
"validation attributes on enum variants are not supported"
);
}
for field in &variant.fields {
for attr in &field.attrs {
emit_error!(
attr.span(),
"validation attributes on enum variants are not supported"
);
}
}
}
}
Data::Union(_) => {}
}
let mut validation_quote = quote! {};
for command in commands {
let operation = command.token_stream();
validation_quote = quote! {
#validation_quote
#operation
};
}
let gen = quote! {
impl Validate for #target_name {
fn validations(&self, errors: &mut Vec<String>) {
#validation_quote
}
}
};
gen.into()
}