serde_valid_derive/
error.rs

1use crate::attribute::{
2    MetaListCustomMessage, MetaListFieldValidation, MetaListStructValidation,
3    MetaNameValueCustomMessage, MetaNameValueFieldValidation, MetaNameValueStructValidation,
4    MetaPathCustomMessage, MetaPathFieldValidation, MetaPathStructValidation,
5};
6use itertools::Itertools;
7use proc_macro2::TokenStream;
8use quote::quote;
9use syn::spanned::Spanned;
10
11pub fn object_errors_tokens() -> TokenStream {
12    quote!(::serde_valid::validation::Errors::Object(
13        ::serde_valid::validation::ObjectErrors::new(
14            __rule_vec_errors,
15            __property_vec_errors_map
16                .into_iter()
17                .map(|(field, errors)| {
18                    let mut __field_items_errors = vec![];
19                    let mut __field_properties_errors = None;
20                    let mut __field_errors: ::serde_valid::validation::VecErrors = errors
21                        .into_iter()
22                        .filter_map(|error| match error {
23                            ::serde_valid::validation::Error::Items(__array_errors) => {
24                                __field_items_errors.push(__array_errors);
25                                None
26                            }
27                            ::serde_valid::validation::Error::Properties(__object_errors) => {
28                                __field_properties_errors = Some(__object_errors);
29                                None
30                            }
31                            _ => Some(error),
32                        })
33                        .collect();
34
35                    if let Some(__object_errors) = __field_properties_errors {
36                        __field_errors.extend(__object_errors.errors);
37
38                        (
39                            field,
40                            ::serde_valid::validation::Errors::Object(
41                                ::serde_valid::validation::ObjectErrors::new(
42                                    __field_errors,
43                                    __object_errors.properties,
44                                ),
45                            ),
46                        )
47                    } else if !__field_items_errors.is_empty() {
48                        let __array_errors = __field_items_errors
49                            .into_iter()
50                            .reduce(|a, b| a.merge(b))
51                            .unwrap();
52                        __field_errors.extend(__array_errors.errors);
53
54                        (
55                            field,
56                            ::serde_valid::validation::Errors::Array(
57                                ::serde_valid::validation::error::ArrayErrors::new(
58                                    __field_errors,
59                                    __array_errors.items,
60                                ),
61                            ),
62                        )
63                    } else {
64                        (
65                            field,
66                            ::serde_valid::validation::Errors::NewType(__field_errors),
67                        )
68                    }
69                })
70                .collect()
71        )
72    ))
73}
74
75pub fn array_errors_tokens() -> TokenStream {
76    quote!(::serde_valid::validation::Errors::Array(
77        ::serde_valid::validation::error::ArrayErrors::new(
78            __rule_vec_errors,
79            __item_vec_errors_map
80                .into_iter()
81                .map(|(index, errors)| {
82                    let mut __field_items_errors = vec![];
83                    let mut __field_properties_errors = None;
84                    let mut __field_errors: ::serde_valid::validation::VecErrors = errors
85                        .into_iter()
86                        .filter_map(|error| match error {
87                            ::serde_valid::validation::Error::Items(__array_errors) => {
88                                __field_items_errors.push(__array_errors);
89                                None
90                            }
91                            ::serde_valid::validation::Error::Properties(__object_errors) => {
92                                __field_properties_errors = Some(__object_errors);
93                                None
94                            }
95                            _ => Some(error),
96                        })
97                        .collect();
98
99                    if let Some(__object_errors) = __field_properties_errors {
100                        __field_errors.extend(__object_errors.errors);
101
102                        (
103                            index,
104                            ::serde_valid::validation::Errors::Object(
105                                ::serde_valid::validation::ObjectErrors::new(
106                                    __field_errors,
107                                    __object_errors.properties,
108                                ),
109                            ),
110                        )
111                    } else if !__field_items_errors.is_empty() {
112                        let __array_errors = __field_items_errors
113                            .into_iter()
114                            .reduce(|a, b| a.merge(b))
115                            .unwrap();
116                        __field_errors.extend(__array_errors.errors);
117
118                        (
119                            index,
120                            ::serde_valid::validation::Errors::Array(
121                                ::serde_valid::validation::error::ArrayErrors::new(
122                                    __field_errors,
123                                    __array_errors.items,
124                                ),
125                            ),
126                        )
127                    } else {
128                        (
129                            index,
130                            ::serde_valid::validation::Errors::NewType(__field_errors),
131                        )
132                    }
133                })
134                .collect()
135        )
136    ))
137}
138
139pub fn new_type_errors_tokens() -> TokenStream {
140    quote!(::serde_valid::validation::Errors::NewType(
141        __rule_vec_errors
142            .into_iter()
143            .chain(
144                __item_vec_errors_map
145                    .remove(&0)
146                    .unwrap_or(vec![])
147                    .into_iter()
148            )
149            .collect()
150    ))
151}
152
153#[derive(Debug)]
154pub struct Error(syn::Error);
155
156impl Error {
157    fn new<Message: Into<String>>(span: proc_macro2::Span, message: Message) -> Self {
158        Self(syn::Error::new(span, message.into()))
159    }
160
161    #[allow(dead_code)]
162    pub fn macro_debug<Message: Into<String>>(span: proc_macro2::Span, message: Message) -> Self {
163        Error::new(span, message)
164    }
165
166    pub fn unit_struct_not_supported(input: &syn::DeriveInput) -> Self {
167        Self::new(
168            input.span(),
169            "#[derive(Validate)] does not support Unit Struct.",
170        )
171    }
172
173    pub fn union_not_supported(input: &syn::DeriveInput) -> Self {
174        Self::new(input.span(), "#[derive(Validate)] does not support Union.")
175    }
176
177    pub fn validate_meta_name_value_not_supported(name_value: &syn::MetaNameValue) -> Self {
178        Self::new(name_value.span(), "#[validate = ???] not supported.")
179    }
180
181    pub fn meta_path_validation_need_value(path: &syn::Path, validation_type: &str) -> Self {
182        Self::new(
183            path.span(),
184            format!("#[validate({validation_type}(???))] needs validation path."),
185        )
186    }
187
188    pub fn meta_path_custom_message_need_value(
189        path: &syn::Path,
190        custom_message_type: &str,
191    ) -> Self {
192        Self::new(
193            path.span(),
194            format!("#[validate(..., {custom_message_type}(???))] needs custom message path."),
195        )
196    }
197
198    pub fn meta_list_validation_need_value(path: &syn::Path, validation_type: &str) -> Self {
199        Self::new(
200            path.span(),
201            format!("#[validate({validation_type}(???, ...))] needs validation list."),
202        )
203    }
204
205    pub fn meta_list_custom_message_need_value(
206        path: &syn::Path,
207        custom_message_type: &str,
208    ) -> Self {
209        Self::new(
210            path.span(),
211            format!("#[validate(..., {custom_message_type}(???, ...))] needs custom message list."),
212        )
213    }
214
215    pub fn meta_name_value_validation_need_value(path: &syn::Path, validation_type: &str) -> Self {
216        Self::new(
217            path.span(),
218            format!("#[validate({validation_type} = ???)] needs validation value."),
219        )
220    }
221
222    pub fn meta_name_value_custom_message_need_value(
223        path: &syn::Path,
224        validation_type: &str,
225    ) -> Self {
226        Self::new(
227            path.span(),
228            format!("#[validate(..., {validation_type} = ???)] needs custom message value."),
229        )
230    }
231
232    pub fn validate_attribute_parse_error(attribute: &syn::Attribute, error: &syn::Error) -> Self {
233        Self::new(
234            attribute.span(),
235            format!("#[validate] parse error: {error}"),
236        )
237    }
238
239    pub fn field_validation_type_required(attribute: &syn::Attribute) -> Self {
240        let filterd_candidates: Vec<&str> = (MetaPathFieldValidation::iter().map(|x| x.name()))
241            .chain(MetaListFieldValidation::iter().map(|x| x.name()))
242            .chain(MetaNameValueFieldValidation::iter().map(|x| x.name()))
243            .collect::<Vec<_>>();
244
245        Self::new(
246            attribute.meta.span(),
247            format!("#[validate(???)] needs validation type. Is it one of the following?\n{filterd_candidates:#?}"),
248        )
249    }
250
251    pub fn field_validation_type_unknown(path: &syn::Path, unknown: &str) -> Self {
252        let candidates = &(MetaPathFieldValidation::iter().map(|x| x.name()))
253            .chain(MetaListFieldValidation::iter().map(|x| x.name()))
254            .chain(MetaNameValueFieldValidation::iter().map(|x| x.name()))
255            .unique()
256            .sorted()
257            .collect::<Vec<_>>();
258
259        let filterd_candidates =
260            did_you_mean(unknown, candidates).unwrap_or_else(|| candidates.to_vec());
261
262        Self::new(
263            path.span(),
264            format!("`{unknown}` is unknown validation type. Is it one of the following?\n{filterd_candidates:#?}"),
265        )
266    }
267
268    pub fn struct_validation_type_required(attribute: &syn::Attribute) -> Self {
269        let filterd_candidates: Vec<&str> = (MetaPathStructValidation::iter().map(|x| x.name()))
270            .chain(MetaListStructValidation::iter().map(|x| x.name()))
271            .chain(MetaNameValueStructValidation::iter().map(|x| x.name()))
272            .collect::<Vec<_>>();
273
274        Self::new(
275            attribute.meta.span(),
276            format!("#[validate(???)] needs validation type. Is it one of the following?\n{filterd_candidates:#?}"),
277        )
278    }
279
280    pub fn struct_validation_type_unknown(path: &syn::Path, unknown: &str) -> Self {
281        let candidates = &(MetaPathStructValidation::iter().map(|x| x.name()))
282            .chain(MetaListStructValidation::iter().map(|x| x.name()))
283            .chain(MetaNameValueStructValidation::iter().map(|x| x.name()))
284            .collect::<Vec<_>>();
285
286        let filterd_candidates =
287            did_you_mean(unknown, candidates).unwrap_or_else(|| candidates.to_vec());
288
289        Self::new(
290            path.span(),
291            format!("`{unknown}` is unknown validation type. Is it one of the following?\n{filterd_candidates:#?}"),
292        )
293    }
294
295    pub fn unknown_custom_message_type(path: &syn::Path, unknown: &str) -> Self {
296        let candidates = &(MetaPathCustomMessage::iter().map(|x| x.name()))
297            .chain(MetaListCustomMessage::iter().map(|x| x.name()))
298            .chain(MetaNameValueCustomMessage::iter().map(|x| x.name()))
299            .unique()
300            .sorted()
301            .collect::<Vec<_>>();
302
303        let filterd_candidates =
304            did_you_mean(unknown, candidates).unwrap_or_else(|| candidates.to_vec());
305
306        Self::new(
307            path.span(),
308            format!("`{unknown}` is unkown error message type. Is it one of the following?\n{filterd_candidates:#?}"),
309        )
310    }
311
312    pub fn validate_enumerate_need_array(path: impl Spanned) -> Self {
313        Self::new(
314            path.span(),
315            "#[validate(enumerate = ???)] needs literal array only.",
316        )
317    }
318
319    pub fn validate_custom_meta_list_need_function_or_closure(span: impl Spanned) -> Self {
320        Self::new(
321            span.span(),
322            "#[validate(custom(???))] needs function or closure.",
323        )
324    }
325
326    pub fn validate_custom_tail_error(nested: &crate::types::NestedMeta) -> Self {
327        Self::new(
328            nested.span(),
329            "#[validate(custom(???))] supports only 1 item.",
330        )
331    }
332
333    pub fn validate_custom_meta_name_value_need_function_or_closure(span: impl Spanned) -> Self {
334        Self::new(
335            span.span(),
336            "#[validate(custom = ???)] needs function or closure.",
337        )
338    }
339
340    pub fn custom_message_parse_error(ident: &syn::Ident, error: &syn::Error) -> Self {
341        Self::new(
342            ident.span(),
343            format!("#[validate(..., {ident})] parse error: {error}"),
344        )
345    }
346
347    pub fn message_fn_meta_name_value_needs_function_or_closure(
348        meta_name_value: &syn::MetaNameValue,
349    ) -> Self {
350        Self::new(
351            meta_name_value.span(),
352            "#[validate(..., message_fn = ???)] needs function or closure.",
353        )
354    }
355
356    #[cfg(feature = "fluent")]
357    pub fn fluent_need_item(message_type: &MetaListCustomMessage, path: &syn::Path) -> Self {
358        Self::new(
359            path.span(),
360            format!("`{}` needs items.", message_type.name()),
361        )
362    }
363
364    #[cfg(feature = "fluent")]
365    pub fn fluent_allow_key(
366        message_type: &MetaListCustomMessage,
367        nested_meta: &crate::types::NestedMeta,
368    ) -> Self {
369        Self::new(
370            nested_meta.span(),
371            format!(
372                "#[validate(..., {}(???, ...))] allows only fluent key str",
373                message_type.name()
374            ),
375        )
376    }
377
378    #[cfg(feature = "fluent")]
379    pub fn fluent_allow_args(
380        message_type: &MetaListCustomMessage,
381        nested_meta: &crate::types::NestedMeta,
382    ) -> Self {
383        Self::new(
384            nested_meta.span(),
385            format!(
386                "#[validate(..., {}(..., ???))] allows only fluent args key value.",
387                message_type.name()
388            ),
389        )
390    }
391
392    #[cfg(feature = "fluent")]
393    pub fn l10n_need_fn_call(expr: &syn::Expr) -> Self {
394        Self::new(
395            expr.span(),
396            "#[validate(..., message_l10n = ???)] needs fn calling.".to_string(),
397        )
398    }
399
400    #[cfg(feature = "fluent")]
401    pub fn l10n_fn_name_not_allow(fn_name: &syn::Expr) -> Self {
402        Self::new(
403            fn_name.span(),
404            "#[validate(..., message_l10n = ???(...))] allows only \"fluent\".".to_string(),
405        )
406    }
407
408    #[cfg(feature = "fluent")]
409    pub fn fluent_id_must_be_str_lit(expr: &syn::Expr) -> Self {
410        Self::new(
411            expr.span(),
412            "#[validate(..., message_l10n = fluent(???, ...))] allow only string literal of the fluent id.",
413        )
414    }
415
416    #[cfg(feature = "fluent")]
417    pub fn fluent_id_not_found(paren: &syn::token::Paren) -> Self {
418        Self::new(
419            paren.span.span(),
420            "#[validate(..., message_l10n = fluent(???))] need the fluent id.",
421        )
422    }
423
424    #[cfg(feature = "fluent")]
425    pub fn fluent_allow_arg(expr: &syn::Expr) -> Self {
426        Self::new(
427            expr.span(),
428            "#[validate(..., message_l10n = fluent(..., ???))] allows only \"key=value\" of the fluent arg."
429                .to_string(),
430        )
431    }
432
433    pub fn literal_only(span: impl Spanned) -> Self {
434        Self::new(span.span(), "Allow literal only.")
435    }
436
437    pub fn numeric_literal_only(lit: &syn::Lit) -> Self {
438        Self::new(lit.span(), "Allow numeric literal only.")
439    }
440
441    pub fn str_literal_only(lit: &syn::Lit) -> Self {
442        Self::new(lit.span(), "Allow str literal only.")
443    }
444
445    pub fn too_many_list_items(nested_meta: &syn::Meta) -> Self {
446        Self::new(nested_meta.span(), "Too many list items.")
447    }
448
449    pub fn to_compile_error(&self) -> TokenStream {
450        self.0.to_compile_error()
451    }
452
453    pub fn validate_custom_does_not_support_custom_message(meta: &syn::Meta) -> Self {
454        Self::new(
455            meta.span(),
456            "#[validate(custon(...), ???)] does not support custom error message.",
457        )
458    }
459}
460
461fn did_you_mean<'a, T, I>(unknown: &'a str, candidates: I) -> Option<Vec<&'a str>>
462where
463    T: AsRef<str> + 'a,
464    I: IntoIterator<Item = &'a T>,
465{
466    let mut filterd = candidates
467        .into_iter()
468        .map(|candidate| {
469            (
470                ::strsim::jaro_winkler(unknown, candidate.as_ref()),
471                candidate.as_ref(),
472            )
473        })
474        .filter(|(confidence, _)| *confidence > 0.8)
475        .collect::<Vec<_>>();
476
477    if filterd.is_empty() {
478        None
479    } else {
480        filterd.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
481        Some(
482            filterd
483                .into_iter()
484                .map(|(_, candidate)| candidate)
485                .collect(),
486        )
487    }
488}
489
490pub type Errors = Vec<Error>;
491
492pub fn to_compile_errors(errors: Errors) -> TokenStream {
493    let compile_errors = errors.iter().map(Error::to_compile_error);
494    quote!(#(#compile_errors)*)
495}