Emit compilation errors for duplicate validation attributes
This commit is contained in:
parent
af69a8ea11
commit
605db3bba8
7 changed files with 230 additions and 90 deletions
|
@ -6,4 +6,30 @@ pub struct Struct1(#[validate(regex = 0, foo, length(min = 1, equal = 2, bar))]
|
||||||
#[derive(JsonSchema)]
|
#[derive(JsonSchema)]
|
||||||
pub struct Struct2(#[schemars(regex = 0, foo, length(min = 1, equal = 2, bar))] String);
|
pub struct Struct2(#[schemars(regex = 0, foo, length(min = 1, equal = 2, bar))] String);
|
||||||
|
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
pub struct Struct3(
|
||||||
|
#[validate(
|
||||||
|
regex = "foo",
|
||||||
|
contains = "bar",
|
||||||
|
regex(path = "baz"),
|
||||||
|
phone,
|
||||||
|
email,
|
||||||
|
url
|
||||||
|
)]
|
||||||
|
String,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
pub struct Struct4(
|
||||||
|
#[schemars(
|
||||||
|
regex = "foo",
|
||||||
|
contains = "bar",
|
||||||
|
regex(path = "baz"),
|
||||||
|
phone,
|
||||||
|
email,
|
||||||
|
url
|
||||||
|
)]
|
||||||
|
String,
|
||||||
|
);
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -20,10 +20,40 @@ error: schemars attribute cannot contain both `equal` and `min`
|
||||||
--> $DIR/invalid_validation_attrs.rs:7:63
|
--> $DIR/invalid_validation_attrs.rs:7:63
|
||||||
|
|
|
|
||||||
7 | pub struct Struct2(#[schemars(regex = 0, foo, length(min = 1, equal = 2, bar))] String);
|
7 | pub struct Struct2(#[schemars(regex = 0, foo, length(min = 1, equal = 2, bar))] String);
|
||||||
| ^^^^^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: unknown item in schemars length attribute
|
error: unknown item in schemars length attribute
|
||||||
--> $DIR/invalid_validation_attrs.rs:7:74
|
--> $DIR/invalid_validation_attrs.rs:7:74
|
||||||
|
|
|
|
||||||
7 | pub struct Struct2(#[schemars(regex = 0, foo, length(min = 1, equal = 2, bar))] String);
|
7 | pub struct Struct2(#[schemars(regex = 0, foo, length(min = 1, equal = 2, bar))] String);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
|
error: schemars attribute cannot contain both `contains` and `regex`
|
||||||
|
--> $DIR/invalid_validation_attrs.rs:26:9
|
||||||
|
|
|
||||||
|
26 | contains = "bar",
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: duplicate schemars attribute `regex`
|
||||||
|
--> $DIR/invalid_validation_attrs.rs:27:9
|
||||||
|
|
|
||||||
|
27 | regex(path = "baz"),
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: schemars attribute cannot contain both `phone` and `email`
|
||||||
|
--> $DIR/invalid_validation_attrs.rs:29:9
|
||||||
|
|
|
||||||
|
29 | email,
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: schemars attribute cannot contain both `phone` and `url`
|
||||||
|
--> $DIR/invalid_validation_attrs.rs:30:9
|
||||||
|
|
|
||||||
|
30 | url
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error[E0425]: cannot find value `foo` in this scope
|
||||||
|
--> $DIR/invalid_validation_attrs.rs:12:17
|
||||||
|
|
|
||||||
|
12 | regex = "foo",
|
||||||
|
| ^^^^^ not found in this scope
|
||||||
|
|
|
@ -4,4 +4,4 @@ error: JsonSchema_repr: missing #[repr(...)] attribute
|
||||||
3 | #[derive(JsonSchema_repr)]
|
3 | #[derive(JsonSchema_repr)]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `JsonSchema_repr` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
|
@ -4,4 +4,4 @@ error: This argument to `schema_for!` is not a type - did you mean to use `schem
|
||||||
4 | let _schema = schema_for!(123);
|
4 | let _schema = schema_for!(123);
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `schema_for` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
|
@ -62,12 +62,14 @@ pub struct Struct2 {
|
||||||
min_max: f32,
|
min_max: f32,
|
||||||
#[schemars(range(min = "MIN", max = "MAX"))]
|
#[schemars(range(min = "MIN", max = "MAX"))]
|
||||||
min_max2: f32,
|
min_max2: f32,
|
||||||
|
#[validate(regex = "overridden")]
|
||||||
#[schemars(regex = "STARTS_WITH_HELLO")]
|
#[schemars(regex = "STARTS_WITH_HELLO")]
|
||||||
regex_str1: String,
|
regex_str1: String,
|
||||||
#[schemars(regex(path = "STARTS_WITH_HELLO"))]
|
#[schemars(regex(path = "STARTS_WITH_HELLO"))]
|
||||||
regex_str2: String,
|
regex_str2: String,
|
||||||
#[schemars(regex(pattern = r"^\d+$"))]
|
#[schemars(regex(pattern = r"^\d+$"))]
|
||||||
regex_str3: String,
|
regex_str3: String,
|
||||||
|
#[validate(regex = "overridden")]
|
||||||
#[schemars(contains = "substring...")]
|
#[schemars(contains = "substring...")]
|
||||||
contains_str1: String,
|
contains_str1: String,
|
||||||
#[schemars(contains(pattern = "substring..."))]
|
#[schemars(contains(pattern = "substring..."))]
|
||||||
|
|
|
@ -1,23 +1,48 @@
|
||||||
use super::{get_lit_str, get_meta_items, parse_lit_into_path, parse_lit_str};
|
use super::{get_lit_str, get_meta_items, parse_lit_into_path, parse_lit_str};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use serde_derive_internals::Ctxt;
|
use serde_derive_internals::Ctxt;
|
||||||
use syn::{Expr, ExprLit, ExprPath, Lit, Meta, MetaNameValue, NestedMeta};
|
use syn::{Expr, ExprLit, ExprPath, Lit, Meta, MetaNameValue, NestedMeta, Path};
|
||||||
|
|
||||||
pub(crate) static VALIDATION_KEYWORDS: &[&str] = &[
|
pub(crate) static VALIDATION_KEYWORDS: &[&str] = &[
|
||||||
"range", "regex", "contains", "email", "phone", "url", "length", "required",
|
"range", "regex", "contains", "email", "phone", "url", "length", "required",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
enum Format {
|
||||||
|
Email,
|
||||||
|
Uri,
|
||||||
|
Phone,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Format {
|
||||||
|
fn attr_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Format::Email => "email",
|
||||||
|
Format::Uri => "url",
|
||||||
|
Format::Phone => "phone",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Format::Email => "email",
|
||||||
|
Format::Uri => "uri",
|
||||||
|
Format::Phone => "phone",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ValidationAttrs {
|
pub struct ValidationAttrs {
|
||||||
pub length_min: Option<Expr>,
|
length_min: Option<Expr>,
|
||||||
pub length_max: Option<Expr>,
|
length_max: Option<Expr>,
|
||||||
pub length_equal: Option<Expr>,
|
length_equal: Option<Expr>,
|
||||||
pub range_min: Option<Expr>,
|
range_min: Option<Expr>,
|
||||||
pub range_max: Option<Expr>,
|
range_max: Option<Expr>,
|
||||||
pub regex: Option<Expr>,
|
regex: Option<Expr>,
|
||||||
pub contains: Option<String>,
|
contains: Option<String>,
|
||||||
pub required: bool,
|
required: bool,
|
||||||
pub format: Option<&'static str>,
|
format: Option<Format>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidationAttrs {
|
impl ValidationAttrs {
|
||||||
|
@ -27,6 +52,10 @@ impl ValidationAttrs {
|
||||||
.populate(attrs, "validate", true, errors)
|
.populate(attrs, "validate", true, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn required(&self) -> bool {
|
||||||
|
self.required
|
||||||
|
}
|
||||||
|
|
||||||
fn populate(
|
fn populate(
|
||||||
mut self,
|
mut self,
|
||||||
attrs: &[syn::Attribute],
|
attrs: &[syn::Attribute],
|
||||||
|
@ -34,23 +63,37 @@ impl ValidationAttrs {
|
||||||
ignore_errors: bool,
|
ignore_errors: bool,
|
||||||
errors: &Ctxt,
|
errors: &Ctxt,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let duplicate_error = |meta: &MetaNameValue| {
|
let duplicate_error = |path: &Path| {
|
||||||
if !ignore_errors {
|
if !ignore_errors {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"duplicate schemars attribute `{}`",
|
"duplicate schemars attribute `{}`",
|
||||||
meta.path.get_ident().unwrap()
|
path.get_ident().unwrap()
|
||||||
);
|
);
|
||||||
errors.error_spanned_by(meta, msg)
|
errors.error_spanned_by(path, msg)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mutual_exclusive_error = |meta: &MetaNameValue, other: &str| {
|
let mutual_exclusive_error = |path: &Path, other: &str| {
|
||||||
if !ignore_errors {
|
if !ignore_errors {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"schemars attribute cannot contain both `{}` and `{}`",
|
"schemars attribute cannot contain both `{}` and `{}`",
|
||||||
meta.path.get_ident().unwrap(),
|
path.get_ident().unwrap(),
|
||||||
other,
|
other,
|
||||||
);
|
);
|
||||||
errors.error_spanned_by(meta, msg)
|
errors.error_spanned_by(path, msg)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let duplicate_format_error = |existing: Format, new: Format, path: &syn::Path| {
|
||||||
|
if !ignore_errors {
|
||||||
|
let msg = if existing == new {
|
||||||
|
format!("duplicate schemars attribute `{}`", existing.attr_str())
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"schemars attribute cannot contain both `{}` and `{}`",
|
||||||
|
existing.attr_str(),
|
||||||
|
new.attr_str(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
errors.error_spanned_by(path, msg)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,29 +108,29 @@ impl ValidationAttrs {
|
||||||
match nested {
|
match nested {
|
||||||
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("min") => {
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("min") => {
|
||||||
if self.length_min.is_some() {
|
if self.length_min.is_some() {
|
||||||
duplicate_error(nv)
|
duplicate_error(&nv.path)
|
||||||
} else if self.length_equal.is_some() {
|
} else if self.length_equal.is_some() {
|
||||||
mutual_exclusive_error(nv, "equal")
|
mutual_exclusive_error(&nv.path, "equal")
|
||||||
} else {
|
} else {
|
||||||
self.length_min = str_or_num_to_expr(&errors, "min", &nv.lit);
|
self.length_min = str_or_num_to_expr(&errors, "min", &nv.lit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("max") => {
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("max") => {
|
||||||
if self.length_max.is_some() {
|
if self.length_max.is_some() {
|
||||||
duplicate_error(nv)
|
duplicate_error(&nv.path)
|
||||||
} else if self.length_equal.is_some() {
|
} else if self.length_equal.is_some() {
|
||||||
mutual_exclusive_error(nv, "equal")
|
mutual_exclusive_error(&nv.path, "equal")
|
||||||
} else {
|
} else {
|
||||||
self.length_max = str_or_num_to_expr(&errors, "max", &nv.lit);
|
self.length_max = str_or_num_to_expr(&errors, "max", &nv.lit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("equal") => {
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("equal") => {
|
||||||
if self.length_equal.is_some() {
|
if self.length_equal.is_some() {
|
||||||
duplicate_error(nv)
|
duplicate_error(&nv.path)
|
||||||
} else if self.length_min.is_some() {
|
} else if self.length_min.is_some() {
|
||||||
mutual_exclusive_error(nv, "min")
|
mutual_exclusive_error(&nv.path, "min")
|
||||||
} else if self.length_max.is_some() {
|
} else if self.length_max.is_some() {
|
||||||
mutual_exclusive_error(nv, "max")
|
mutual_exclusive_error(&nv.path, "max")
|
||||||
} else {
|
} else {
|
||||||
self.length_equal =
|
self.length_equal =
|
||||||
str_or_num_to_expr(&errors, "equal", &nv.lit);
|
str_or_num_to_expr(&errors, "equal", &nv.lit);
|
||||||
|
@ -110,14 +153,14 @@ impl ValidationAttrs {
|
||||||
match nested {
|
match nested {
|
||||||
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("min") => {
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("min") => {
|
||||||
if self.range_min.is_some() {
|
if self.range_min.is_some() {
|
||||||
duplicate_error(nv)
|
duplicate_error(&nv.path)
|
||||||
} else {
|
} else {
|
||||||
self.range_min = str_or_num_to_expr(&errors, "min", &nv.lit);
|
self.range_min = str_or_num_to_expr(&errors, "min", &nv.lit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("max") => {
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("max") => {
|
||||||
if self.range_max.is_some() {
|
if self.range_max.is_some() {
|
||||||
duplicate_error(nv)
|
duplicate_error(&nv.path)
|
||||||
} else {
|
} else {
|
||||||
self.range_max = str_or_num_to_expr(&errors, "max", &nv.lit);
|
self.range_max = str_or_num_to_expr(&errors, "max", &nv.lit);
|
||||||
}
|
}
|
||||||
|
@ -140,37 +183,56 @@ impl ValidationAttrs {
|
||||||
self.required = true;
|
self.required = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO cause compile error if format is already Some
|
NestedMeta::Meta(Meta::Path(p)) if p.is_ident(Format::Email.attr_str()) => {
|
||||||
// FIXME #[validate(...)] overrides #[schemars(...)] - should be other way around!
|
match self.format {
|
||||||
NestedMeta::Meta(Meta::Path(m)) if m.is_ident("email") => {
|
Some(f) => duplicate_format_error(f, Format::Email, p),
|
||||||
self.format = Some("email");
|
None => self.format = Some(Format::Email),
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::Path(m)) if m.is_ident("url") => {
|
|
||||||
self.format = Some("uri");
|
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::Path(m)) if m.is_ident("phone") => {
|
NestedMeta::Meta(Meta::Path(p)) if p.is_ident(Format::Uri.attr_str()) => {
|
||||||
self.format = Some("phone");
|
match self.format {
|
||||||
|
Some(f) => duplicate_format_error(f, Format::Uri, p),
|
||||||
|
None => self.format = Some(Format::Uri),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NestedMeta::Meta(Meta::Path(p)) if p.is_ident(Format::Phone.attr_str()) => {
|
||||||
|
match self.format {
|
||||||
|
Some(f) => duplicate_format_error(f, Format::Phone, p),
|
||||||
|
None => self.format = Some(Format::Phone),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO cause compile error if regex/contains are specified more than once
|
NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("regex") => {
|
||||||
// FIXME #[validate(...)] overrides #[schemars(...)] - should be other way around!
|
match (&self.regex, &self.contains) {
|
||||||
NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit, .. }))
|
(Some(_), _) => duplicate_error(&nv.path),
|
||||||
if path.is_ident("regex") =>
|
(None, Some(_)) => mutual_exclusive_error(&nv.path, "contains"),
|
||||||
{
|
(None, None) => {
|
||||||
self.regex = parse_lit_into_expr_path(errors, attr_type, "regex", lit).ok()
|
self.regex =
|
||||||
|
parse_lit_into_expr_path(errors, attr_type, "regex", &nv.lit).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NestedMeta::Meta(Meta::List(meta_list)) if meta_list.path.is_ident("regex") => {
|
NestedMeta::Meta(Meta::List(meta_list)) if meta_list.path.is_ident("regex") => {
|
||||||
|
match (&self.regex, &self.contains) {
|
||||||
|
(Some(_), _) => duplicate_error(&meta_list.path),
|
||||||
|
(None, Some(_)) => mutual_exclusive_error(&meta_list.path, "contains"),
|
||||||
|
(None, None) => {
|
||||||
for x in meta_list.nested.iter() {
|
for x in meta_list.nested.iter() {
|
||||||
match x {
|
match x {
|
||||||
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
||||||
path, lit, ..
|
path,
|
||||||
|
lit,
|
||||||
|
..
|
||||||
})) if path.is_ident("path") => {
|
})) if path.is_ident("path") => {
|
||||||
self.regex =
|
self.regex =
|
||||||
parse_lit_into_expr_path(errors, attr_type, "path", lit).ok()
|
parse_lit_into_expr_path(errors, attr_type, "path", lit)
|
||||||
|
.ok()
|
||||||
}
|
}
|
||||||
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
||||||
path, lit, ..
|
path,
|
||||||
|
lit,
|
||||||
|
..
|
||||||
})) if path.is_ident("pattern") => {
|
})) if path.is_ident("pattern") => {
|
||||||
self.regex = get_lit_str(errors, attr_type, "pattern", lit)
|
self.regex = get_lit_str(errors, attr_type, "pattern", lit)
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -192,22 +254,37 @@ impl ValidationAttrs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit, .. }))
|
NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit, .. }))
|
||||||
if path.is_ident("contains") =>
|
if path.is_ident("contains") =>
|
||||||
{
|
{
|
||||||
|
match (&self.contains, &self.regex) {
|
||||||
|
(Some(_), _) => duplicate_error(&path),
|
||||||
|
(None, Some(_)) => mutual_exclusive_error(&path, "regex"),
|
||||||
|
(None, None) => {
|
||||||
self.contains = get_lit_str(errors, attr_type, "contains", lit)
|
self.contains = get_lit_str(errors, attr_type, "contains", lit)
|
||||||
.ok()
|
|
||||||
.map(|litstr| litstr.value())
|
.map(|litstr| litstr.value())
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NestedMeta::Meta(Meta::List(meta_list)) if meta_list.path.is_ident("contains") => {
|
NestedMeta::Meta(Meta::List(meta_list)) if meta_list.path.is_ident("contains") => {
|
||||||
|
match (&self.contains, &self.regex) {
|
||||||
|
(Some(_), _) => duplicate_error(&meta_list.path),
|
||||||
|
(None, Some(_)) => mutual_exclusive_error(&meta_list.path, "regex"),
|
||||||
|
(None, None) => {
|
||||||
for x in meta_list.nested.iter() {
|
for x in meta_list.nested.iter() {
|
||||||
match x {
|
match x {
|
||||||
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
|
||||||
path, lit, ..
|
path,
|
||||||
|
lit,
|
||||||
|
..
|
||||||
})) if path.is_ident("pattern") => {
|
})) if path.is_ident("pattern") => {
|
||||||
self.contains = get_lit_str(errors, attr_type, "contains", lit)
|
self.contains =
|
||||||
|
get_lit_str(errors, attr_type, "contains", lit)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|litstr| litstr.value())
|
.map(|litstr| litstr.value())
|
||||||
}
|
}
|
||||||
|
@ -215,13 +292,17 @@ impl ValidationAttrs {
|
||||||
if !ignore_errors {
|
if !ignore_errors {
|
||||||
errors.error_spanned_by(
|
errors.error_spanned_by(
|
||||||
meta,
|
meta,
|
||||||
format!("unknown item in schemars contains attribute"),
|
format!(
|
||||||
|
"unknown item in schemars contains attribute"
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -293,6 +374,7 @@ impl ValidationAttrs {
|
||||||
}
|
}
|
||||||
|
|
||||||
let format = self.format.as_ref().map(|f| {
|
let format = self.format.as_ref().map(|f| {
|
||||||
|
let f = f.schema_str();
|
||||||
quote! {
|
quote! {
|
||||||
schema_object.format = Some(#f.to_string());
|
schema_object.format = Some(#f.to_string());
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream {
|
||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
let gen = quote!(gen);
|
let gen = quote!(gen);
|
||||||
|
|
||||||
let mut schema_expr = if field.validation_attrs.required {
|
let mut schema_expr = if field.validation_attrs.required() {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen)
|
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen)
|
||||||
}
|
}
|
||||||
|
@ -439,7 +439,7 @@ fn expr_for_struct(
|
||||||
|
|
||||||
let (ty, type_def) = type_for_field_schema(field);
|
let (ty, type_def) = type_for_field_schema(field);
|
||||||
|
|
||||||
let maybe_insert_required = match (&default, field.validation_attrs.required) {
|
let maybe_insert_required = match (&default, field.validation_attrs.required()) {
|
||||||
(Some(_), _) => TokenStream::new(),
|
(Some(_), _) => TokenStream::new(),
|
||||||
(None, false) => {
|
(None, false) => {
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -461,7 +461,7 @@ fn expr_for_struct(
|
||||||
};
|
};
|
||||||
|
|
||||||
let gen = quote!(gen);
|
let gen = quote!(gen);
|
||||||
let mut schema_expr = if field.validation_attrs.required {
|
let mut schema_expr = if field.validation_attrs.required() {
|
||||||
quote_spanned! {ty.span()=>
|
quote_spanned! {ty.span()=>
|
||||||
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen)
|
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen)
|
||||||
}
|
}
|
||||||
|
@ -489,7 +489,7 @@ fn expr_for_struct(
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let (ty, type_def) = type_for_field_schema(field);
|
let (ty, type_def) = type_for_field_schema(field);
|
||||||
|
|
||||||
let required = field.validation_attrs.required;
|
let required = field.validation_attrs.required();
|
||||||
|
|
||||||
let args = quote!(gen, #required);
|
let args = quote!(gen, #required);
|
||||||
let mut schema_expr = quote_spanned! {ty.span()=>
|
let mut schema_expr = quote_spanned! {ty.span()=>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue