Fix handling of attributes applied to unit variant types (#152)

This commit is contained in:
Adam Leventhal 2022-08-12 07:37:34 -07:00 committed by GitHub
parent 9464118c3a
commit 76427ef384
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 28 deletions

View file

@ -185,6 +185,21 @@ impl Attrs {
}
self
}
pub fn is_default(&self) -> bool {
match self {
Self {
with: None,
title: None,
description: None,
deprecated: false,
examples,
repr: None,
crate_name: None,
} if examples.is_empty() => true,
_ => false,
}
}
}
fn is_known_serde_or_validation_keyword(meta: &syn::Meta) -> bool {

View file

@ -149,8 +149,7 @@ fn expr_for_external_tagged_enum<'a>(
unique_names.insert(v.name());
count += 1;
})
.partition(|v| v.is_unit() && v.attrs.with.is_none());
.partition(|v| v.is_unit() && v.attrs.is_default());
let unit_names = unit_variants.iter().map(|v| v.name());
let unit_schema = schema_object(quote! {
instance_type: Some(schemars::schema::InstanceType::String.into()),
@ -168,31 +167,38 @@ fn expr_for_external_tagged_enum<'a>(
schemas.extend(complex_variants.into_iter().map(|variant| {
let name = variant.name();
let sub_schema = expr_for_untagged_enum_variant(variant, deny_unknown_fields);
let mut schema_expr = schema_object(quote! {
instance_type: Some(schemars::schema::InstanceType::Object.into()),
object: Some(Box::new(schemars::schema::ObjectValidation {
properties: {
let mut props = schemars::Map::new();
props.insert(#name.to_owned(), #sub_schema);
props
},
required: {
let mut required = schemars::Set::new();
required.insert(#name.to_owned());
required
},
// Externally tagged variants must prohibit additional
// properties irrespective of the disposition of
// `deny_unknown_fields`. If additional properties were allowed
// one could easily construct an object that validated against
// multiple variants since here it's the properties rather than
// the values of a property that distingish between variants.
additional_properties: Some(Box::new(false.into())),
..Default::default()
})),
});
let mut schema_expr = if variant.is_unit() && variant.attrs.with.is_none() {
schema_object(quote! {
instance_type: Some(schemars::schema::InstanceType::String.into()),
enum_values: Some(vec![#name.into()]),
})
} else {
let sub_schema = expr_for_untagged_enum_variant(variant, deny_unknown_fields);
schema_object(quote! {
instance_type: Some(schemars::schema::InstanceType::Object.into()),
object: Some(Box::new(schemars::schema::ObjectValidation {
properties: {
let mut props = schemars::Map::new();
props.insert(#name.to_owned(), #sub_schema);
props
},
required: {
let mut required = schemars::Set::new();
required.insert(#name.to_owned());
required
},
// Externally tagged variants must prohibit additional
// properties irrespective of the disposition of
// `deny_unknown_fields`. If additional properties were allowed
// one could easily construct an object that validated against
// multiple variants since here it's the properties rather than
// the values of a property that distingish between variants.
additional_properties: Some(Box::new(false.into())),
..Default::default()
})),
})
};
variant
.attrs