Skip to content

Commit

Permalink
refactor: custom message.
Browse files Browse the repository at this point in the history
  • Loading branch information
yassun7010 committed Jan 6, 2024
1 parent 96805ca commit 6bf3e30
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 79 deletions.
64 changes: 54 additions & 10 deletions serde_valid_derive/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use syn::spanned::Spanned;

use crate::types::CommaSeparatedNestedMetas;
#[cfg(feature = "fluent")]
use crate::validate::MetaListMessage;
use crate::validate::MetaListCustomMessage;

pub fn object_errors_tokens() -> TokenStream {
quote!(::serde_valid::validation::Errors::Object(
Expand Down Expand Up @@ -213,27 +213,57 @@ impl Error {
)
}

pub fn validate_meta_name_value_need_value(path: &syn::Path, validation_type: &str) -> Self {
pub fn meta_path_validation_need_value(path: &syn::Path, validation_type: &str) -> Self {
Self::new(
path.span(),
format!("#[validate({validation_type} = ???)] needs validation value."),
format!("#[validate({validation_type}(???))] needs validation path."),
)
}

pub fn validate_meta_path_need_value(path: &syn::Path, validation_type: &str) -> Self {
pub fn meta_path_custom_message_need_value(
path: &syn::Path,
custom_message_type: &str,
) -> Self {
Self::new(
path.span(),
format!("#[validate({validation_type}(???))] needs validation path."),
format!("#[validate(..., {custom_message_type}(???))] needs custom message path."),
)
}

pub fn validate_meta_list_need_value(path: &syn::Path, validation_type: &str) -> Self {
pub fn meta_list_validation_need_value(path: &syn::Path, validation_type: &str) -> Self {
Self::new(
path.span(),
format!("#[validate({validation_type}(???, ...))] needs validation list."),
)
}

pub fn meta_list_custom_message_need_value(
path: &syn::Path,
custom_message_type: &str,
) -> Self {
Self::new(
path.span(),
format!("#[validate(..., {custom_message_type}(???, ...))] needs custom message list."),
)
}

pub fn meta_name_value_validation_need_value(path: &syn::Path, validation_type: &str) -> Self {
Self::new(
path.span(),
format!("#[validate({validation_type} = ???)] needs validation value."),
)
}

pub fn meta_name_value_custom_message_need_value(
path: &syn::Path,
validation_type: &str,
) -> Self {
Self::new(
path.span(),
format!("#[validate(..., {validation_type} = ???)] needs custom message value."),
)
}

pub fn validate_attribute_parse_error(attribute: &syn::Attribute, error: &syn::Error) -> Self {
Self::new(
attribute.span(),
Expand All @@ -253,7 +283,7 @@ impl Error {
)
}

pub fn validate_unknown_type(path: &syn::Path, unknown: &str, candidates: &[&str]) -> Self {
pub fn unknown_validation_type(path: &syn::Path, unknown: &str, candidates: &[&str]) -> Self {
let filterd_candidates =
did_you_mean(unknown, candidates).unwrap_or_else(|| candidates.to_vec());

Expand All @@ -263,6 +293,20 @@ impl Error {
)
}

pub fn unknown_custom_message_type(
path: &syn::Path,
unknown: &str,
candidates: &[&str],
) -> Self {
let filterd_candidates =
did_you_mean(unknown, candidates).unwrap_or_else(|| candidates.to_vec());

Self::new(
path.span(),
format!("Unknown: `{unknown}` error message type. Is it one of the following?\n{filterd_candidates:#?}"),
)
}

pub fn validate_enumerate_parse_error(path: &syn::Path, error: &syn::Error) -> Self {
Self::new(
path.span(),
Expand Down Expand Up @@ -294,7 +338,7 @@ impl Error {
}

#[cfg(feature = "fluent")]
pub fn fluent_need_item(message_type: &MetaListMessage, path: &syn::Path) -> Self {
pub fn fluent_need_item(message_type: &MetaListCustomMessage, path: &syn::Path) -> Self {
Self::new(
path.span(),
format!("`{}` need items.", message_type.name()),
Expand All @@ -303,7 +347,7 @@ impl Error {

#[cfg(feature = "fluent")]
pub fn fluent_allow_key(
message_type: &MetaListMessage,
message_type: &MetaListCustomMessage,
nested_meta: &crate::types::NestedMeta,
) -> Self {
Self::new(
Expand All @@ -324,7 +368,7 @@ impl Error {

#[cfg(feature = "fluent")]
pub fn fluent_allow_args(
message_type: &MetaListMessage,
message_type: &MetaListCustomMessage,
nested_meta: &crate::types::NestedMeta,
) -> Self {
Self::new(
Expand Down
2 changes: 1 addition & 1 deletion serde_valid_derive/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ pub use field::{FieldValidators, Validator};
pub use meta::extract_meta_validator;

#[cfg(feature = "fluent")]
pub use common::MetaListMessage;
pub use common::MetaListCustomMessage;
20 changes: 10 additions & 10 deletions serde_valid_derive/src/validate/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ macro_rules! enum_str {
};
}

enum_str! {
pub enum MetaPathValidation {
UniqueItems = "unique_items",
}
}

enum_str! {
pub enum MetaListValidation {
Enumerate = "enumerate",
Expand All @@ -92,34 +98,28 @@ enum_str! {
}

enum_str! {
pub enum MetaPathValidation {
UniqueItems = "unique_items",
pub enum MetaPathCustomMessage {
}
}

#[cfg(not(feature = "fluent"))]
enum_str! {
pub enum MetaListMessage {
pub enum MetaListCustomMessage {
MessageFn = "message_fn",
}
}

#[cfg(feature = "fluent")]
enum_str! {
pub enum MetaListMessage {
pub enum MetaListCustomMessage {
MessageFn = "message_fn",
I18n = "i18n",
Fluent = "fluent",
}
}

enum_str! {
pub enum MetaNameValueMessage {
pub enum MetaNameValueCustomMessage {
Message = "message",
}
}

enum_str! {
pub enum MetaPathMessage {
}
}
113 changes: 65 additions & 48 deletions serde_valid_derive/src/validate/common/custom_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use proc_macro2::TokenStream;
use quote::quote;
use std::str::FromStr;

use super::{get_str, MetaListMessage, MetaNameValueMessage, MetaPathMessage};
use super::{get_str, MetaListCustomMessage, MetaNameValueCustomMessage, MetaPathCustomMessage};

#[derive(Debug, Default)]
pub struct CustomMessageToken {
Expand Down Expand Up @@ -51,37 +51,52 @@ impl CustomMessageToken {
pub fn extract_custom_message_tokens(
meta: &syn::Meta,
) -> Result<CustomMessageToken, crate::Errors> {
match meta {
syn::Meta::List(message_fn_list) => {
extract_custom_message_tokens_from_meta_list(message_fn_list)
let custom_message_path = match meta {
syn::Meta::Path(path) => path,
syn::Meta::List(list) => &list.path,
syn::Meta::NameValue(name_value) => &name_value.path,
};
let custom_message_name = SingleIdentPath::new(custom_message_path)
.ident()
.to_string();

match (
MetaPathCustomMessage::from_str(&custom_message_name),
MetaListCustomMessage::from_str(&custom_message_name),
MetaNameValueCustomMessage::from_str(&custom_message_name),
meta,
) {
(Ok(_), _, _, syn::Meta::Path(_)) => {
unreachable!()
}
syn::Meta::NameValue(name_value) => {
extract_custom_message_tokens_from_name_value(name_value)
(_, Ok(_), _, syn::Meta::List(custom_message)) => {
extract_custom_message_tokens_from_meta_list(custom_message)
}
syn::Meta::Path(path) => {
let path_label = SingleIdentPath::new(path).ident().to_string();
if MetaNameValueMessage::from_str(&path_label).is_ok() {
Err(crate::Error::validate_meta_name_value_need_value(
path,
&path_label,
))
} else if MetaListMessage::from_str(&path_label).is_ok() {
Err(crate::Error::validate_meta_list_need_value(
path,
&path_label,
))
} else {
Err(crate::Error::validate_unknown_type(
path,
&path_label,
&(MetaNameValueMessage::iter().map(|x| x.name()))
.chain(MetaListMessage::iter().map(|x| x.name()))
.chain(MetaPathMessage::iter().map(|x| x.name()))
.collect::<Vec<_>>(),
))
}
(_, _, Ok(_), syn::Meta::NameValue(custom_message)) => {
extract_custom_message_tokens_from_name_value(custom_message)
}
.map_err(|error| vec![error]),
(Ok(_), _, _, _) => Err(vec![crate::Error::meta_path_custom_message_need_value(
custom_message_path,
&custom_message_name,
)]),
(_, Ok(_), _, _) => Err(vec![crate::Error::meta_list_custom_message_need_value(
custom_message_path,
&custom_message_name,
)]),
(_, _, Ok(_), _) => Err(vec![
crate::Error::meta_name_value_custom_message_need_value(
custom_message_path,
&custom_message_name,
),
]),
_ => Err(vec![crate::Error::unknown_custom_message_type(
custom_message_path,
&custom_message_name,
&(MetaPathCustomMessage::iter().map(|x| x.name()))
.chain(MetaListCustomMessage::iter().map(|x| x.name()))
.chain(MetaNameValueCustomMessage::iter().map(|x| x.name()))
.collect::<Vec<_>>(),
)]),
}
}

Expand All @@ -95,24 +110,26 @@ fn extract_custom_message_tokens_from_meta_list(
.parse_args_with(CommaSeparatedNestedMetas::parse_terminated)
.map_err(|error| vec![crate::Error::message_fn_parse_error(path_ident, &error)])?;

match MetaListMessage::from_str(&path_label) {
Ok(MetaListMessage::MessageFn) => get_message_fn_from_nested_meta(path, &message_fn_define)
.map(CustomMessageToken::new_message_fn),
match MetaListCustomMessage::from_str(&path_label) {
Ok(MetaListCustomMessage::MessageFn) => {
get_message_fn_from_nested_meta(path, &message_fn_define)
.map(CustomMessageToken::new_message_fn)
}
#[cfg(feature = "fluent")]
Ok(ref message_type @ (MetaListMessage::I18n | MetaListMessage::Fluent)) => {
Ok(ref message_type @ (MetaListCustomMessage::I18n | MetaListCustomMessage::Fluent)) => {
get_fluent_message_from_nested_meta(message_type, path, &message_fn_define)
.map(CustomMessageToken::new_fluent_message)
}
Err(unknown) => {
let error = if MetaNameValueMessage::from_str(&path_label).is_ok() {
crate::Error::validate_meta_list_need_value(path, &path_label)
} else if MetaPathMessage::from_str(&path_label).is_ok() {
crate::Error::validate_meta_path_need_value(path, &path_label)
let error = if MetaNameValueCustomMessage::from_str(&path_label).is_ok() {
crate::Error::meta_list_validation_need_value(path, &path_label)
} else if MetaPathCustomMessage::from_str(&path_label).is_ok() {
crate::Error::meta_path_validation_need_value(path, &path_label)
} else {
crate::Error::validate_unknown_type(
crate::Error::unknown_validation_type(
path,
&unknown,
&MetaListMessage::iter()
&MetaListCustomMessage::iter()
.map(|x| x.name())
.collect::<Vec<_>>(),
)
Expand All @@ -129,25 +146,25 @@ fn extract_custom_message_tokens_from_name_value(
let path_ident = SingleIdentPath::new(path).ident();
let path_label = path_ident.to_string();

match MetaNameValueMessage::from_str(&path_label) {
Ok(MetaNameValueMessage::Message) => {
match MetaNameValueCustomMessage::from_str(&path_label) {
Ok(MetaNameValueCustomMessage::Message) => {
get_message_from_expr(&name_value.value).map(CustomMessageToken::new_message_fn)
}
Err(unknown) => if MetaListMessage::from_str(&path_label).is_ok() {
Err(crate::Error::validate_meta_list_need_value(
Err(unknown) => if MetaListCustomMessage::from_str(&path_label).is_ok() {
Err(crate::Error::meta_list_validation_need_value(
path,
&path_label,
))
} else if MetaPathMessage::from_str(&path_label).is_ok() {
Err(crate::Error::validate_meta_path_need_value(
} else if MetaPathCustomMessage::from_str(&path_label).is_ok() {
Err(crate::Error::meta_path_validation_need_value(
path,
&path_label,
))
} else {
Err(crate::Error::validate_unknown_type(
Err(crate::Error::unknown_validation_type(
path,
&unknown,
&MetaNameValueMessage::iter()
&MetaNameValueCustomMessage::iter()
.map(|x| x.name())
.collect::<Vec<_>>(),
))
Expand Down Expand Up @@ -190,7 +207,7 @@ fn get_message_from_lit(lit: &syn::Lit) -> Result<TokenStream, crate::Errors> {

#[cfg(feature = "fluent")]
fn get_fluent_message_from_nested_meta(
message_type: &MetaListMessage,
message_type: &MetaListCustomMessage,
path: &syn::Path,
fn_define: &CommaSeparatedNestedMetas,
) -> Result<TokenStream, crate::Errors> {
Expand Down
Loading

0 comments on commit 6bf3e30

Please sign in to comment.