From 509a1c3b7bcab9d042900ad054dc6b037a194ea1 Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Sat, 16 May 2020 16:44:44 +0100 Subject: [PATCH] Check for #[deprecated] attributes --- CHANGELOG.md | 4 ++ docs/1.1-attributes.md | 7 ++++ schemars/tests/deprecated.rs | 37 +++++++++++++++++ schemars/tests/expected/deprecated-enum.json | 40 +++++++++++++++++++ .../tests/expected/deprecated-struct.json | 20 ++++++++++ schemars_derive/src/metadata.rs | 11 ++++- schemars_derive/src/schema_exprs.rs | 12 +++--- 7 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 schemars/tests/deprecated.rs create mode 100644 schemars/tests/expected/deprecated-enum.json create mode 100644 schemars/tests/expected/deprecated-struct.json diff --git a/CHANGELOG.md b/CHANGELOG.md index a066575..78ec122 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ # Changelog +## In-dev - version TBC +### Added: +- Setting `#[deprecated]` attribute will now cause generated schemas to have the `deprecated` property set to `true` + ## [0.7.4] - 2020-05-16 ### Added: - If a struct is annotated with `#[serde(deny_unknown_fields)]`, generated schema will have `additionalProperties` set to `false` (https://github.com/GREsau/schemars/pull/30) diff --git a/docs/1.1-attributes.md b/docs/1.1-attributes.md index dde424a..47ace02 100644 --- a/docs/1.1-attributes.md +++ b/docs/1.1-attributes.md @@ -144,6 +144,13 @@ Serde docs: [container](https://serde.rs/container-attrs.html#deny_unknown_field Set on a variant or field to generate this field's schema using the given function. This function must be callable as `fn(&mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema`. +

+ +`#[deprecated]` +

+ +Set the Rust build-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/an-attribute-for-deprecation.html) attribute on a struct, enum, field or variant to set the generated schema's `deprecated` keyword to `true`. +

Doc Comments (`#[doc = "..."]`) diff --git a/schemars/tests/deprecated.rs b/schemars/tests/deprecated.rs new file mode 100644 index 0000000..60ce0c9 --- /dev/null +++ b/schemars/tests/deprecated.rs @@ -0,0 +1,37 @@ +#![allow(deprecated)] + +mod util; +use schemars::JsonSchema; +use util::*; + +#[derive(Debug, JsonSchema)] +#[deprecated] +pub struct DeprecatedStruct { + foo: i32, + #[deprecated] + deprecated_field: bool, +} + +#[test] +fn deprecated_struct() -> TestResult { + test_default_generated_schema::("deprecated-struct") +} + +#[derive(Debug, JsonSchema)] +#[deprecated] +pub enum DeprecatedEnum { + Unit, + #[deprecated] + DeprecatedUnitVariant, + #[deprecated] + DeprecatedStructVariant { + foo: i32, + #[deprecated] + deprecated_field: bool, + }, +} + +#[test] +fn deprecated_enum() -> TestResult { + test_default_generated_schema::("deprecated-enum") +} diff --git a/schemars/tests/expected/deprecated-enum.json b/schemars/tests/expected/deprecated-enum.json new file mode 100644 index 0000000..4224f26 --- /dev/null +++ b/schemars/tests/expected/deprecated-enum.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "DeprecatedEnum", + "deprecated": true, + "anyOf": [ + { + "type": "string", + "enum": [ + "Unit", + "DeprecatedUnitVariant" + ] + }, + { + "deprecated": true, + "type": "object", + "required": [ + "DeprecatedStructVariant" + ], + "properties": { + "DeprecatedStructVariant": { + "type": "object", + "required": [ + "deprecated_field", + "foo" + ], + "properties": { + "deprecated_field": { + "deprecated": true, + "type": "boolean" + }, + "foo": { + "type": "integer", + "format": "int32" + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/schemars/tests/expected/deprecated-struct.json b/schemars/tests/expected/deprecated-struct.json new file mode 100644 index 0000000..cdb1b7f --- /dev/null +++ b/schemars/tests/expected/deprecated-struct.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "DeprecatedStruct", + "deprecated": true, + "type": "object", + "required": [ + "deprecated_field", + "foo" + ], + "properties": { + "deprecated_field": { + "deprecated": true, + "type": "boolean" + }, + "foo": { + "type": "integer", + "format": "int32" + } + } +} \ No newline at end of file diff --git a/schemars_derive/src/metadata.rs b/schemars_derive/src/metadata.rs index efd80ec..fc5e0ca 100644 --- a/schemars_derive/src/metadata.rs +++ b/schemars_derive/src/metadata.rs @@ -7,6 +7,7 @@ use syn::Attribute; pub struct SchemaMetadata { pub title: Option, pub description: Option, + pub deprecated: bool, pub read_only: bool, pub write_only: bool, pub default: Option, @@ -30,11 +31,13 @@ impl ToTokens for SchemaMetadata { } impl SchemaMetadata { - pub fn from_doc_attrs(attrs: &[Attribute]) -> SchemaMetadata { + pub fn from_attrs(attrs: &[Attribute]) -> SchemaMetadata { let (title, description) = attr::get_title_and_desc_from_doc(attrs); + let deprecated = attrs.iter().any(|a| a.path.is_ident("deprecated")); SchemaMetadata { title, description, + deprecated, ..Default::default() } } @@ -62,6 +65,12 @@ impl SchemaMetadata { }); } + if self.deprecated { + setters.push(quote! { + metadata.deprecated = true; + }); + } + if self.read_only { setters.push(quote! { metadata.read_only = true; diff --git a/schemars_derive/src/schema_exprs.rs b/schemars_derive/src/schema_exprs.rs index 72c6694..7129c02 100644 --- a/schemars_derive/src/schema_exprs.rs +++ b/schemars_derive/src/schema_exprs.rs @@ -13,7 +13,7 @@ pub fn expr_for_container(cont: &Container) -> TokenStream { Data::Enum(variants) => expr_for_enum(variants, &cont.serde_attrs), }; - let doc_metadata = SchemaMetadata::from_doc_attrs(&cont.original.attrs); + let doc_metadata = SchemaMetadata::from_attrs(&cont.original.attrs); doc_metadata.apply_to_schema(schema_expr) } @@ -121,7 +121,7 @@ fn expr_for_external_tagged_enum<'a>( ..Default::default() })), }); - let doc_metadata = SchemaMetadata::from_doc_attrs(&variant.original.attrs); + let doc_metadata = SchemaMetadata::from_attrs(&variant.original.attrs); doc_metadata.apply_to_schema(schema_expr) })); @@ -160,7 +160,7 @@ fn expr_for_internal_tagged_enum<'a>( ..Default::default() })), }); - let doc_metadata = SchemaMetadata::from_doc_attrs(&variant.original.attrs); + let doc_metadata = SchemaMetadata::from_attrs(&variant.original.attrs); let tag_schema = doc_metadata.apply_to_schema(tag_schema); match expr_for_untagged_enum_variant_for_flatten(&variant) { @@ -182,7 +182,7 @@ fn expr_for_internal_tagged_enum<'a>( fn expr_for_untagged_enum<'a>(variants: impl Iterator>) -> TokenStream { let schemas = variants.map(|variant| { let schema_expr = expr_for_untagged_enum_variant(variant); - let doc_metadata = SchemaMetadata::from_doc_attrs(&variant.original.attrs); + let doc_metadata = SchemaMetadata::from_attrs(&variant.original.attrs); doc_metadata.apply_to_schema(schema_expr) }); @@ -240,7 +240,7 @@ fn expr_for_adjacent_tagged_enum<'a>( })), }); - let doc_metadata = SchemaMetadata::from_doc_attrs(&variant.original.attrs); + let doc_metadata = SchemaMetadata::from_attrs(&variant.original.attrs); doc_metadata.apply_to_schema(outer_schema) }); @@ -334,7 +334,7 @@ fn expr_for_struct(fields: &[Field], cattrs: Option<&serde_attr::Container>) -> read_only: field.serde_attrs.skip_deserializing(), write_only: field.serde_attrs.skip_serializing(), default, - ..SchemaMetadata::from_doc_attrs(&field.original.attrs) + ..SchemaMetadata::from_attrs(&field.original.attrs) }; let (ty, type_def) = type_for_schema(field, type_defs.len());