diff --git a/serde_valid_derive/src/attribute/field_validate/field.rs b/serde_valid_derive/src/attribute/field_validate/field.rs index ee845a5..d4a0ec4 100644 --- a/serde_valid_derive/src/attribute/field_validate/field.rs +++ b/serde_valid_derive/src/attribute/field_validate/field.rs @@ -1,5 +1,6 @@ use crate::attribute::Validator; use crate::types::Field; +use crate::warning::WithWarnings; use quote::quote; use std::borrow::Cow; use std::iter::FromIterator; @@ -7,11 +8,16 @@ use std::iter::FromIterator; pub struct FieldValidators<'a, F: Field + Clone + 'a> { field: Cow<'a, F>, validators: Vec, + pub warnings: Vec, } impl<'a, F: Field + Clone> FieldValidators<'a, F> { - pub fn new(field: Cow<'a, F>, validators: Vec) -> Self { - Self { field, validators } + pub fn new(field: Cow<'a, F>, validators: Vec>) -> Self { + Self { + field, + validators: validators.iter().map(|v| v.data.clone()).collect(), + warnings: validators.into_iter().flat_map(|v| v.warnings).collect(), + } } pub fn ident(&self) -> &syn::Ident { diff --git a/serde_valid_derive/src/attribute/field_validate/generic/validate.rs b/serde_valid_derive/src/attribute/field_validate/generic/validate.rs index a74dded..da3f4f2 100644 --- a/serde_valid_derive/src/attribute/field_validate/generic/validate.rs +++ b/serde_valid_derive/src/attribute/field_validate/generic/validate.rs @@ -1,19 +1,20 @@ use crate::attribute::Validator; use crate::serde::rename::RenameMap; use crate::types::Field; +use crate::warning::WithWarnings; use quote::quote; pub fn extract_generic_validate_validator( field: &impl Field, rename_map: &RenameMap, -) -> Result { +) -> Result, crate::Errors> { let field_ident = field.ident(); let field_name = field.name(); let field_key = field.key(); let rename = rename_map.get(field_name).unwrap_or(&field_key); let errors = field.errors_variable(); - Ok(quote!( + Ok(WithWarnings::new(quote!( if let Err(__inner_errors) = #field_ident.validate() { match __inner_errors { ::serde_valid::validation::Errors::Object(__object_errors) => { @@ -31,5 +32,5 @@ pub fn extract_generic_validate_validator( } } } - )) + ))) } diff --git a/serde_valid_derive/src/attribute/field_validate/meta.rs b/serde_valid_derive/src/attribute/field_validate/meta.rs index fdd31a0..4f9f135 100644 --- a/serde_valid_derive/src/attribute/field_validate/meta.rs +++ b/serde_valid_derive/src/attribute/field_validate/meta.rs @@ -11,6 +11,7 @@ use crate::attribute::{ use crate::serde::rename::RenameMap; use crate::types::Field; use crate::types::SingleIdentPath; +use crate::warning::WithWarnings; use meta_list::extract_field_validator_from_meta_list; use meta_name_value::extract_field_validator_from_meta_name_value; use meta_path::extract_field_validator_from_meta_path; @@ -22,7 +23,7 @@ pub fn extract_field_validator( field: &impl Field, attribute: &syn::Attribute, rename_map: &RenameMap, -) -> Result { +) -> Result, crate::Errors> { match &attribute.meta { syn::Meta::List(list) => inner_extract_field_validator(field, attribute, list, rename_map), syn::Meta::Path(_) => extract_generic_validate_validator(field, rename_map), @@ -39,7 +40,7 @@ fn inner_extract_field_validator( attribute: &syn::Attribute, meta_list: &syn::MetaList, rename_map: &RenameMap, -) -> Result { +) -> Result, crate::Errors> { let mut errors = vec![]; let nested = meta_list .parse_args_with(crate::types::CommaSeparatedMetas::parse_terminated) @@ -123,6 +124,7 @@ fn inner_extract_field_validator( message_format, rename_map, ) + .map(WithWarnings::new) } (Ok(_), _, _, _) => Err(vec![crate::Error::meta_path_validation_need_value( diff --git a/serde_valid_derive/src/attribute/field_validate/meta/meta_list.rs b/serde_valid_derive/src/attribute/field_validate/meta/meta_list.rs index 9e17d4d..a4359f0 100644 --- a/serde_valid_derive/src/attribute/field_validate/meta/meta_list.rs +++ b/serde_valid_derive/src/attribute/field_validate/meta/meta_list.rs @@ -1,11 +1,14 @@ +use syn::spanned::Spanned; + use crate::attribute::common::message_format::MessageFormat; use crate::attribute::field_validate::generic::{ extract_generic_custom_validator, extract_generic_enumerate_validator_from_list, }; -use crate::attribute::MetaListFieldValidation; -use crate::attribute::Validator; +use crate::attribute::{MetaListFieldValidation, Validator}; use crate::serde::rename::RenameMap; use crate::types::Field; +use crate::warning::Warning; +use crate::warning::WithWarnings; pub fn extract_field_validator_from_meta_list( field: &impl Field, @@ -13,16 +16,24 @@ pub fn extract_field_validator_from_meta_list( validation: &syn::MetaList, message_format: MessageFormat, rename_map: &RenameMap, -) -> Result { +) -> Result, crate::Errors> { match validation_type { MetaListFieldValidation::Enumerate => extract_generic_enumerate_validator_from_list( field, validation, message_format, rename_map, - ), + ) + .map(|data| WithWarnings { + data, + warnings: vec![Warning::new_enumerate_path_deprecated( + field.ident(), + validation.span(), + )], + }), MetaListFieldValidation::Custom => { extract_generic_custom_validator(field, validation, message_format, rename_map) + .map(WithWarnings::new) } } } diff --git a/serde_valid_derive/src/attribute/field_validate/meta/meta_path.rs b/serde_valid_derive/src/attribute/field_validate/meta/meta_path.rs index 6caa170..6851275 100644 --- a/serde_valid_derive/src/attribute/field_validate/meta/meta_path.rs +++ b/serde_valid_derive/src/attribute/field_validate/meta/meta_path.rs @@ -3,6 +3,7 @@ use crate::attribute::field_validate::array::extract_array_unique_items_validato use crate::attribute::{MetaPathFieldValidation, Validator}; use crate::serde::rename::RenameMap; use crate::types::Field; +use crate::warning::WithWarnings; pub fn extract_field_validator_from_meta_path( field: &impl Field, @@ -10,12 +11,10 @@ pub fn extract_field_validator_from_meta_path( _validation: &syn::Path, message_format: MessageFormat, rename_map: &RenameMap, -) -> Result { +) -> Result, crate::Errors> { match validation_type { - MetaPathFieldValidation::UniqueItems => Ok(extract_array_unique_items_validator( - field, - message_format, - rename_map, + MetaPathFieldValidation::UniqueItems => Ok(WithWarnings::new( + extract_array_unique_items_validator(field, message_format, rename_map), )), } } diff --git a/serde_valid_derive/src/attribute/rule/named_struct_rule.rs b/serde_valid_derive/src/attribute/rule/named_struct_rule.rs index 01269a8..9eb1ce6 100644 --- a/serde_valid_derive/src/attribute/rule/named_struct_rule.rs +++ b/serde_valid_derive/src/attribute/rule/named_struct_rule.rs @@ -5,15 +5,15 @@ use quote::{quote, ToTokens}; use syn::spanned::Spanned; use crate::{ - output_stream::OutputStream, types::{CommaSeparatedNestedMetas, CommaSeparatedTokenStreams}, warning::Warning, + warning::WithWarnings, }; pub fn collect_rules_from_named_struct( ident: &syn::Ident, attributes: &[syn::Attribute], -) -> Result<(HashSet, OutputStream), crate::Errors> { +) -> Result<(HashSet, WithWarnings), crate::Errors> { let mut errors = vec![]; let mut rule_fields = HashSet::new(); @@ -50,8 +50,8 @@ pub fn collect_rules_from_named_struct( if errors.is_empty() { Ok(( rule_fields, - OutputStream { - output: TokenStream::from_iter(rules), + WithWarnings { + data: TokenStream::from_iter(rules), warnings, }, )) diff --git a/serde_valid_derive/src/attribute/rule/unnamed_struct_rule.rs b/serde_valid_derive/src/attribute/rule/unnamed_struct_rule.rs index 2219c18..d514bf7 100644 --- a/serde_valid_derive/src/attribute/rule/unnamed_struct_rule.rs +++ b/serde_valid_derive/src/attribute/rule/unnamed_struct_rule.rs @@ -5,15 +5,15 @@ use quote::quote; use syn::spanned::Spanned; use crate::{ - output_stream::OutputStream, types::{CommaSeparatedNestedMetas, CommaSeparatedTokenStreams, NestedMeta}, warning::Warning, + warning::WithWarnings, }; pub fn collect_rules_from_unnamed_struct( ident: &syn::Ident, attributes: &[syn::Attribute], -) -> Result<(HashSet, OutputStream), crate::Errors> { +) -> Result<(HashSet, WithWarnings), crate::Errors> { let mut errors = vec![]; let mut rule_fields = HashSet::new(); @@ -50,8 +50,8 @@ pub fn collect_rules_from_unnamed_struct( if errors.is_empty() { Ok(( rule_fields, - OutputStream { - output: TokenStream::from_iter(rules), + WithWarnings { + data: TokenStream::from_iter(rules), warnings, }, )) diff --git a/serde_valid_derive/src/attribute/struct_validate.rs b/serde_valid_derive/src/attribute/struct_validate.rs index c69eb43..b471bd5 100644 --- a/serde_valid_derive/src/attribute/struct_validate.rs +++ b/serde_valid_derive/src/attribute/struct_validate.rs @@ -1,13 +1,13 @@ mod generic; mod meta; -use crate::attribute::Validator; +use crate::{attribute::Validator, warning::WithWarnings}; use self::meta::extract_struct_validator; pub fn collect_struct_custom_from_named_struct( attributes: &[syn::Attribute], -) -> Result { +) -> Result>, crate::Errors> { let mut errors = vec![]; let validations = attributes @@ -28,7 +28,7 @@ pub fn collect_struct_custom_from_named_struct( .collect::>(); if errors.is_empty() { - Ok(Validator::from_iter(validations)) + Ok(WithWarnings::from_iter(validations)) } else { Err(errors) } diff --git a/serde_valid_derive/src/attribute/struct_validate/meta.rs b/serde_valid_derive/src/attribute/struct_validate/meta.rs index f5f049a..7636781 100644 --- a/serde_valid_derive/src/attribute/struct_validate/meta.rs +++ b/serde_valid_derive/src/attribute/struct_validate/meta.rs @@ -9,6 +9,7 @@ use crate::{ Validator, }, types::SingleIdentPath, + warning::WithWarnings, }; use quote::quote; use std::str::FromStr; @@ -19,10 +20,14 @@ use self::{ meta_path::extract_struct_validator_from_meta_path, }; -pub fn extract_struct_validator(attribute: &syn::Attribute) -> Result { +pub fn extract_struct_validator( + attribute: &syn::Attribute, +) -> Result, crate::Errors> { match &attribute.meta { - syn::Meta::Path(_) => Ok(quote!()), - syn::Meta::List(list) => inner_extract_struct_validator(attribute, list), + syn::Meta::Path(_) => Ok(WithWarnings::new(quote!())), + syn::Meta::List(list) => { + inner_extract_struct_validator(attribute, list).map(WithWarnings::new) + } syn::Meta::NameValue(name_value) => { Err(vec![crate::Error::validate_meta_name_value_not_supported( name_value, diff --git a/serde_valid_derive/src/derive/enum_derive.rs b/serde_valid_derive/src/derive/enum_derive.rs index 6b24306..2099a70 100644 --- a/serde_valid_derive/src/derive/enum_derive.rs +++ b/serde_valid_derive/src/derive/enum_derive.rs @@ -2,10 +2,11 @@ use super::named_struct_derive::collect_named_fields_validators_list; use super::unnamed_struct_derive::collect_unnamed_fields_validators_list; use crate::attribute::rule::{collect_rules_from_named_struct, collect_rules_from_unnamed_struct}; use crate::attribute::variant_validate::collect_variant_custom_from_variant; +use crate::attribute::Validator; use crate::error::{array_errors_tokens, new_type_errors_tokens, object_errors_tokens}; -use crate::output_stream::OutputStream; use crate::serde::rename::collect_serde_rename_map; use crate::types::CommaSeparatedTokenStreams; +use crate::warning::WithWarnings; use proc_macro2::TokenStream; use quote::quote; use std::collections::HashSet; @@ -34,7 +35,7 @@ pub fn expand_enum_validate_derive( Ok(variant_varidates_and_rules) => variant_varidates_and_rules, Err(variant_errors) => { errors.extend(variant_errors); - OutputStream::new() + WithWarnings::new(Validator::new()) } } } @@ -48,18 +49,18 @@ pub fn expand_enum_validate_derive( Ok(variant_varidates_and_rules) => variant_varidates_and_rules, Err(variant_errors) => { errors.extend(variant_errors); - OutputStream::new() + WithWarnings::new(Validator::new()) } } } - syn::Fields::Unit => OutputStream::new(), + syn::Fields::Unit => WithWarnings::new(Validator::new()), }) .collect::>(); let validations_and_rules = TokenStream::from_iter( validations .iter() - .map(|variant| variant.output.clone()) + .map(|variant| variant.data.clone()) .collect::>(), ); let warnings = validations @@ -90,7 +91,7 @@ fn expand_enum_variant_named_fields_validation( input: &syn::DeriveInput, variant: &syn::Variant, named_fields: &syn::FieldsNamed, -) -> Result { +) -> Result, crate::Errors> { let mut errors = vec![]; let variant_ident = &variant.ident; @@ -99,15 +100,15 @@ fn expand_enum_variant_named_fields_validation( let ( rule_fields, - OutputStream { - output: rules, + WithWarnings { + data: rules, warnings, }, ) = match collect_rules_from_named_struct(&variant.ident, &variant.attrs) { Ok(field_rules) => field_rules, Err(variant_errors) => { errors.extend(variant_errors); - (HashSet::new(), OutputStream::new()) + (HashSet::new(), WithWarnings::new(Validator::new())) } }; @@ -146,8 +147,8 @@ fn expand_enum_variant_named_fields_validation( let variant_errors = object_errors_tokens(); if errors.is_empty() { - Ok(OutputStream { - output: quote!( + Ok(WithWarnings { + data: quote!( if let #ident::#variant_ident{#fields_idents} = &self { let mut __rule_vec_errors = ::serde_valid::validation::VecErrors::new(); let mut __property_vec_errors_map = ::serde_valid::validation::PropertyVecErrorsMap::new(); @@ -173,7 +174,7 @@ fn expand_enum_variant_unnamed_fields_varidation( input: &syn::DeriveInput, variant: &syn::Variant, unnamed_fields: &syn::FieldsUnnamed, -) -> Result { +) -> Result, crate::Errors> { let mut errors = vec![]; let variant_ident = &variant.ident; @@ -181,15 +182,15 @@ fn expand_enum_variant_unnamed_fields_varidation( let ( rule_fields, - OutputStream { - output: rules, + WithWarnings { + data: rules, warnings, }, ) = match collect_rules_from_unnamed_struct(&variant.ident, &variant.attrs) { Ok(field_rules) => field_rules, Err(variant_errors) => { errors.extend(variant_errors); - (HashSet::new(), OutputStream::new()) + (HashSet::new(), WithWarnings::new(Validator::new())) } }; @@ -232,8 +233,8 @@ fn expand_enum_variant_unnamed_fields_varidation( }; if errors.is_empty() { - Ok(OutputStream { - output: quote!( + Ok(WithWarnings { + data: quote!( if let #ident::#variant_ident(#fields_idents) = &self { let mut __rule_vec_errors = ::serde_valid::validation::VecErrors::new(); let mut __item_vec_errors_map = ::serde_valid::validation::ItemVecErrorsMap::new(); diff --git a/serde_valid_derive/src/derive/named_struct_derive.rs b/serde_valid_derive/src/derive/named_struct_derive.rs index ded49ce..d886f4d 100644 --- a/serde_valid_derive/src/derive/named_struct_derive.rs +++ b/serde_valid_derive/src/derive/named_struct_derive.rs @@ -1,10 +1,11 @@ use crate::attribute::field_validate::{extract_field_validator, FieldValidators}; use crate::attribute::rule::collect_rules_from_named_struct; use crate::attribute::struct_validate::collect_struct_custom_from_named_struct; +use crate::attribute::Validator; use crate::error::object_errors_tokens; -use crate::output_stream::OutputStream; use crate::serde::rename::{collect_serde_rename_map, RenameMap}; use crate::types::{Field, NamedField}; +use crate::warning::WithWarnings; use proc_macro2::TokenStream; use quote::quote; use std::borrow::Cow; @@ -23,19 +24,23 @@ pub fn expand_named_struct_derive( let ( rule_fields, - OutputStream { - output: rules, - warnings, + WithWarnings { + data: rules, + mut warnings, }, ) = match collect_rules_from_named_struct(&input.ident, &input.attrs) { Ok((rule_fields, rules)) => (rule_fields, rules), Err(rule_errors) => { errors.extend(rule_errors); - (HashSet::new(), OutputStream::new()) + (HashSet::new(), WithWarnings::new(Validator::new())) } }; + let struct_validations = match collect_struct_custom_from_named_struct(&input.attrs) { - Ok(validations) => TokenStream::from_iter(validations), + Ok(validations) => { + warnings.extend(validations.warnings); + TokenStream::from_iter(validations.data) + } Err(rule_errors) => { errors.extend(rule_errors); quote!() @@ -44,6 +49,7 @@ pub fn expand_named_struct_derive( let field_validates = match collect_named_fields_validators_list(fields, &rename_map) { Ok(field_validators) => TokenStream::from_iter(field_validators.iter().map(|validator| { + warnings.extend(validator.warnings.clone()); if validator.is_empty() && rule_fields.contains(validator.ident()) { validator.get_field_variable_token() } else { diff --git a/serde_valid_derive/src/derive/unnamed_struct_derive.rs b/serde_valid_derive/src/derive/unnamed_struct_derive.rs index f0e0bc6..7071049 100644 --- a/serde_valid_derive/src/derive/unnamed_struct_derive.rs +++ b/serde_valid_derive/src/derive/unnamed_struct_derive.rs @@ -1,9 +1,10 @@ use crate::attribute::field_validate::{extract_field_validator, FieldValidators}; use crate::attribute::rule::collect_rules_from_unnamed_struct; use crate::attribute::struct_validate::collect_struct_custom_from_named_struct; +use crate::attribute::Validator; use crate::error::{array_errors_tokens, new_type_errors_tokens}; -use crate::output_stream::OutputStream; use crate::types::{Field, UnnamedField}; +use crate::warning::WithWarnings; use proc_macro2::TokenStream; use quote::quote; use std::borrow::Cow; @@ -21,28 +22,32 @@ pub fn expand_unnamed_struct_derive( let ( rule_fields, - OutputStream { - output: rules, - warnings, + WithWarnings { + data: rules, + mut warnings, }, ) = match collect_rules_from_unnamed_struct(&input.ident, &input.attrs) { Ok((rule_fields, rules)) => (rule_fields, rules), Err(rule_errors) => { errors.extend(rule_errors); - (HashSet::new(), OutputStream::new()) + (HashSet::new(), WithWarnings::new(Validator::new())) } }; let struct_validations = match collect_struct_custom_from_named_struct(&input.attrs) { - Ok(validations) => TokenStream::from_iter(validations), + Ok(validations) => { + warnings.extend(validations.warnings); + Validator::from_iter(validations.data) + } Err(rule_errors) => { errors.extend(rule_errors); quote!() } }; - let field_validates = match collect_unnamed_fields_validators_list(fields) { + let field_validates: TokenStream = match collect_unnamed_fields_validators_list(fields) { Ok(field_validators) => TokenStream::from_iter(field_validators.iter().map(|validator| { + warnings.extend(validator.warnings.clone()); if validator.is_empty() && rule_fields.contains(validator.ident()) { validator.get_field_variable_token() } else { diff --git a/serde_valid_derive/src/lib.rs b/serde_valid_derive/src/lib.rs index 69c1180..77319c7 100644 --- a/serde_valid_derive/src/lib.rs +++ b/serde_valid_derive/src/lib.rs @@ -2,7 +2,6 @@ mod attribute; mod derive; mod error; -mod output_stream; mod serde; mod types; mod warning; diff --git a/serde_valid_derive/src/output_stream.rs b/serde_valid_derive/src/output_stream.rs deleted file mode 100644 index 478c23c..0000000 --- a/serde_valid_derive/src/output_stream.rs +++ /dev/null @@ -1,23 +0,0 @@ -use crate::warning::Warning; -use proc_macro2::TokenStream; - -#[derive(Debug, Clone)] -pub struct OutputStream { - pub output: TokenStream, - pub warnings: Vec, -} - -impl OutputStream { - pub fn new() -> Self { - Self { - output: TokenStream::new(), - warnings: vec![], - } - } - - #[allow(unused)] - pub fn extend_warnings(&mut self, warnings: Vec) -> &mut Self { - self.warnings.extend(warnings); - self - } -} diff --git a/serde_valid_derive/src/warning.rs b/serde_valid_derive/src/warning.rs index cb22d3d..b634cc6 100644 --- a/serde_valid_derive/src/warning.rs +++ b/serde_valid_derive/src/warning.rs @@ -4,6 +4,54 @@ use proc_macro2::Span; use proc_macro2::TokenStream; use quote::{quote_spanned, ToTokens}; +#[derive(Debug, Clone)] +pub struct WithWarnings { + pub data: T, + pub warnings: Vec, +} + +impl WithWarnings { + pub fn new(data: T) -> Self { + Self { + data, + warnings: vec![], + } + } + + pub fn from_iter(data: impl IntoIterator>) -> WithWarnings> { + let mut warnings = vec![]; + let data = data + .into_iter() + .map(|WithWarnings { data, warnings: w }| { + warnings.extend(w); + data + }) + .collect::>(); + WithWarnings { data, warnings } + } + + #[allow(unused)] + pub fn extend_warnings(&mut self, warnings: Vec) -> &mut Self { + self.warnings.extend(warnings); + self + } +} + +impl From> for WithWarnings> { + fn from(with_warnings: WithWarnings) -> Self { + WithWarnings { + data: vec![with_warnings.data], + warnings: with_warnings.warnings, + } + } +} + +impl From for WithWarnings { + fn from(data: T) -> Self { + Self::new(data) + } +} + #[derive(Debug, Clone)] pub enum Warning { Deprecated { @@ -49,7 +97,17 @@ impl Warning { pub fn new_rule_deprecated(ident: &syn::Ident, span: Span) -> Self { Self::Deprecated { ident: ident.clone(), - note: "#[rule(...)] is deprecated, use #[validate(custom(...)))] instead".to_string(), + note: "#[rule(...)] is deprecated, please use #[validate(custom(...)))] instead." + .to_string(), + span, + } + } + + pub fn new_enumerate_path_deprecated(ident: &syn::Ident, span: Span) -> Self { + Self::Deprecated { + ident: ident.clone(), + note: "#[validate(enumerate(...))] is deprecated, please use #[validate(enumerate = [...])] instead." + .to_string(), span, } }