Fix handling of attributes applied to unit variant types (#152)
This commit is contained in:
parent
9464118c3a
commit
76427ef384
7 changed files with 109 additions and 28 deletions
|
@ -31,7 +31,8 @@ struct MyUnitStruct;
|
||||||
#[doc = " the enum's description."]
|
#[doc = " the enum's description."]
|
||||||
enum MyEnum {
|
enum MyEnum {
|
||||||
UndocumentedUnit,
|
UndocumentedUnit,
|
||||||
/// This comment is not included in the generated schema :(
|
UndocumentedUnit2,
|
||||||
|
/// This comment is included in the generated schema :)
|
||||||
DocumentedUnit,
|
DocumentedUnit,
|
||||||
/// ## Complex variant
|
/// ## Complex variant
|
||||||
/// This is a struct-like variant.
|
/// This is a struct-like variant.
|
||||||
|
|
|
@ -118,3 +118,21 @@ enum SimpleInternal {
|
||||||
fn enum_simple_internal_tag() -> TestResult {
|
fn enum_simple_internal_tag() -> TestResult {
|
||||||
test_default_generated_schema::<SimpleInternal>("enum-simple-internal")
|
test_default_generated_schema::<SimpleInternal>("enum-simple-internal")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
enum SoundOfMusic {
|
||||||
|
/// # A deer
|
||||||
|
///
|
||||||
|
/// A female deer
|
||||||
|
Do,
|
||||||
|
/// A drop of golden sun
|
||||||
|
Re,
|
||||||
|
/// A name I call myself
|
||||||
|
Mi,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_unit_with_doc_comments() -> TestResult {
|
||||||
|
test_default_generated_schema::<SoundOfMusic>("enum-unit-doc")
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,13 @@
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"Unit",
|
"Unit"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"deprecated": true,
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
"DeprecatedUnitVariant"
|
"DeprecatedUnitVariant"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,13 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
"UndocumentedUnit",
|
"UndocumentedUnit",
|
||||||
|
"UndocumentedUnit2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "This comment is included in the generated schema :)",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
"DocumentedUnit"
|
"DocumentedUnit"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
28
schemars/tests/expected/enum-unit-doc.json
Normal file
28
schemars/tests/expected/enum-unit-doc.json
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "SoundOfMusic",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"title": "A deer",
|
||||||
|
"description": "A female deer",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Do"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "A drop of golden sun",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Re"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "A name I call myself",
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Mi"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -185,6 +185,21 @@ impl Attrs {
|
||||||
}
|
}
|
||||||
self
|
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 {
|
fn is_known_serde_or_validation_keyword(meta: &syn::Meta) -> bool {
|
||||||
|
|
|
@ -149,8 +149,7 @@ fn expr_for_external_tagged_enum<'a>(
|
||||||
unique_names.insert(v.name());
|
unique_names.insert(v.name());
|
||||||
count += 1;
|
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_names = unit_variants.iter().map(|v| v.name());
|
||||||
let unit_schema = schema_object(quote! {
|
let unit_schema = schema_object(quote! {
|
||||||
instance_type: Some(schemars::schema::InstanceType::String.into()),
|
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| {
|
schemas.extend(complex_variants.into_iter().map(|variant| {
|
||||||
let name = variant.name();
|
let name = variant.name();
|
||||||
let sub_schema = expr_for_untagged_enum_variant(variant, deny_unknown_fields);
|
|
||||||
|
|
||||||
let mut schema_expr = schema_object(quote! {
|
let mut schema_expr = if variant.is_unit() && variant.attrs.with.is_none() {
|
||||||
instance_type: Some(schemars::schema::InstanceType::Object.into()),
|
schema_object(quote! {
|
||||||
object: Some(Box::new(schemars::schema::ObjectValidation {
|
instance_type: Some(schemars::schema::InstanceType::String.into()),
|
||||||
properties: {
|
enum_values: Some(vec![#name.into()]),
|
||||||
let mut props = schemars::Map::new();
|
})
|
||||||
props.insert(#name.to_owned(), #sub_schema);
|
} else {
|
||||||
props
|
let sub_schema = expr_for_untagged_enum_variant(variant, deny_unknown_fields);
|
||||||
},
|
schema_object(quote! {
|
||||||
required: {
|
instance_type: Some(schemars::schema::InstanceType::Object.into()),
|
||||||
let mut required = schemars::Set::new();
|
object: Some(Box::new(schemars::schema::ObjectValidation {
|
||||||
required.insert(#name.to_owned());
|
properties: {
|
||||||
required
|
let mut props = schemars::Map::new();
|
||||||
},
|
props.insert(#name.to_owned(), #sub_schema);
|
||||||
// Externally tagged variants must prohibit additional
|
props
|
||||||
// properties irrespective of the disposition of
|
},
|
||||||
// `deny_unknown_fields`. If additional properties were allowed
|
required: {
|
||||||
// one could easily construct an object that validated against
|
let mut required = schemars::Set::new();
|
||||||
// multiple variants since here it's the properties rather than
|
required.insert(#name.to_owned());
|
||||||
// the values of a property that distingish between variants.
|
required
|
||||||
additional_properties: Some(Box::new(false.into())),
|
},
|
||||||
..Default::default()
|
// 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
|
variant
|
||||||
.attrs
|
.attrs
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue