From b2b733ba5ca85192c80ccc40a8f39f8b8815d026 Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Mon, 5 Apr 2021 19:34:28 +0100 Subject: [PATCH] Support for #[schemars(crate = "...")] (#80) --- CHANGELOG.md | 5 +++- docs/1.1-attributes.md | 10 ++++++++ schemars/tests/crate_alias.rs | 19 +++++++++++++++ schemars/tests/expected/crate_alias.json | 19 +++++++++++++++ schemars_derive/src/attr/mod.rs | 15 ++++++++++++ schemars_derive/src/lib.rs | 31 ++++++++++++++++-------- 6 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 schemars/tests/crate_alias.rs create mode 100644 schemars/tests/expected/crate_alias.json diff --git a/CHANGELOG.md b/CHANGELOG.md index e1c60c51..bcbf6d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,11 @@ # Changelog ## [0.8.3] - **In-dev** +### Added: +- Support for `#[schemars(crate = "...")]` attribute to allow deriving JsonSchema when the schemars crate is aliased to a different name (https://github.com/GREsau/schemars/pull/55 / https://github.com/GREsau/schemars/pull/80) + ### Fixed: -- Fix deriving JsonSchema on types defined inside macros (https://github.com/GREsau/schemars/issues/66 / https://github.com/GREsau/schemars/pull/79) +- Fix deriving JsonSchema on types defined inside macros (https://github.com/GREsau/schemars/issues/59 / https://github.com/GREsau/schemars/issues/66 / https://github.com/GREsau/schemars/pull/79) ## [0.8.2] - 2021-03-27 ### Added: diff --git a/docs/1.1-attributes.md b/docs/1.1-attributes.md index 3cc38c43..50bc753c 100644 --- a/docs/1.1-attributes.md +++ b/docs/1.1-attributes.md @@ -182,6 +182,16 @@ Set on a container, variant or field to include the result of the given function Set the Rust built-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/crate_alias.rs b/schemars/tests/crate_alias.rs new file mode 100644 index 00000000..5f8d83c0 --- /dev/null +++ b/schemars/tests/crate_alias.rs @@ -0,0 +1,19 @@ +mod util; +use ::schemars as not_schemars; +use util::*; + +#[allow(unused_imports)] +use std as schemars; + +#[derive(Debug, not_schemars::JsonSchema)] +#[schemars(crate = "not_schemars")] +pub struct Struct { + /// This is a document + foo: i32, + bar: bool, +} + +#[test] +fn test_crate_alias() -> TestResult { + test_default_generated_schema::("crate_alias") +} diff --git a/schemars/tests/expected/crate_alias.json b/schemars/tests/expected/crate_alias.json new file mode 100644 index 00000000..66bf749b --- /dev/null +++ b/schemars/tests/expected/crate_alias.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Struct", + "type": "object", + "required": [ + "bar", + "foo" + ], + "properties": { + "foo": { + "description": "This is a document", + "type": "integer", + "format": "int32" + }, + "bar": { + "type": "boolean" + } + } +} \ No newline at end of file diff --git a/schemars_derive/src/attr/mod.rs b/schemars_derive/src/attr/mod.rs index 65667d9c..04c89fe2 100644 --- a/schemars_derive/src/attr/mod.rs +++ b/schemars_derive/src/attr/mod.rs @@ -11,6 +11,10 @@ use syn::Meta::{List, NameValue}; use syn::MetaNameValue; use syn::NestedMeta::{Lit, Meta}; +// FIXME using the same struct for containers+variants+fields means that +// with/schema_with are accepted (but ignored) on containers, and +// repr/crate_name are accepted (but ignored) on variants and fields etc. + #[derive(Debug, Default)] pub struct Attrs { pub with: Option, @@ -19,6 +23,7 @@ pub struct Attrs { pub deprecated: bool, pub examples: Vec, pub repr: Option, + pub crate_name: Option, } #[derive(Debug)] @@ -123,6 +128,16 @@ impl Attrs { } } + Meta(NameValue(m)) if m.path.is_ident("crate") => { + if let Ok(p) = parse_lit_into_path(errors, attr_type, "crate", &m.lit) { + if self.crate_name.is_some() { + duplicate_error(m) + } else { + self.crate_name = Some(p) + } + } + } + _ if ignore_errors => {} Meta(meta_item) => { diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs index c81eb406..7b140a55 100644 --- a/schemars_derive/src/lib.rs +++ b/schemars_derive/src/lib.rs @@ -13,6 +13,7 @@ mod schema_exprs; use ast::*; use proc_macro2::TokenStream; +use syn::spanned::Spanned; #[proc_macro_derive(JsonSchema, attributes(schemars, serde))] pub fn derive_json_schema_wrapper(input: proc_macro::TokenStream) -> proc_macro::TokenStream { @@ -39,6 +40,11 @@ fn derive_json_schema( attr::process_serde_attrs(&mut input)?; let cont = Container::from_ast(&input)?; + let crate_alias = cont.attrs.crate_name.as_ref().map(|path| { + quote_spanned! {path.span()=> + use #path as schemars; + } + }); let type_name = &cont.ident; let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl(); @@ -47,6 +53,7 @@ fn derive_json_schema( let (ty, type_def) = schema_exprs::type_for_schema(transparent_field, 0); return Ok(quote! { const _: () = { + #crate_alias #type_def #[automatically_derived] @@ -121,16 +128,20 @@ fn derive_json_schema( }; Ok(quote! { - #[automatically_derived] - #[allow(unused_braces)] - impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause { - fn schema_name() -> std::string::String { - #schema_name - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - #schema_expr - } + const _: () = { + #crate_alias + + #[automatically_derived] + #[allow(unused_braces)] + impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause { + fn schema_name() -> std::string::String { + #schema_name + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + #schema_expr + } + }; }; }) }