From 352a33aaad3f5a5486bed468aa17a5d7911bb31b Mon Sep 17 00:00:00 2001 From: Omid Rad Date: Sun, 6 Dec 2020 00:54:25 +0100 Subject: [PATCH 1/4] Fix type aliases --- CHANGELOG.md | 1 + core/src/v2/schema.rs | 12 ++++++++++++ macros/src/actix.rs | 32 +++++++++----------------------- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be3c97d71..0f121ebe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### Fixed +- Optional type aliases like `type Email = Option` will not be added to the `required` fields. ## [0.5.0] - 2020-11-28 ### Added diff --git a/core/src/v2/schema.rs b/core/src/v2/schema.rs index 9388c1516..1e85008ce 100644 --- a/core/src/v2/schema.rs +++ b/core/src/v2/schema.rs @@ -286,6 +286,10 @@ pub trait Apiv2Schema { fn security_scheme() -> Option { None } + + fn is_required() -> bool { + true + } } impl Apiv2Schema for () {} @@ -312,6 +316,10 @@ impl Apiv2Schema for Option { default fn security_scheme() -> Option { None } + + fn is_required() -> bool { + false + } } impl Apiv2Schema for Option { @@ -324,6 +332,10 @@ impl Apiv2Schema for Option { fn security_scheme() -> Option { T::security_scheme() } + + fn is_required() -> bool { + false + } } #[cfg(feature = "nightly")] diff --git a/macros/src/actix.rs b/macros/src/actix.rs index 46e309936..fef02a3bc 100644 --- a/macros/src/actix.rs +++ b/macros/src/actix.rs @@ -769,29 +769,15 @@ fn add_optional_impl(name: &Ident, generics: &Generics) -> proc_macro2::TokenStr } } -fn get_field_type(field: &Field) -> (Option, bool) { - let mut is_required = true; +fn get_field_type(field: &Field) -> Option { match field.ty { - Type::Path(ref p) => { - let ty = p - .path - .segments - .last() - .expect("expected type for struct field"); - - if p.path.segments.len() == 1 && &ty.ident == "Option" { - is_required = false; - } - - (Some(address_type_for_fn_call(&field.ty)), is_required) - } - Type::Reference(_) => (Some(address_type_for_fn_call(&field.ty)), is_required), + Type::Path(_) | Type::Reference(_) => Some(address_type_for_fn_call(&field.ty)), _ => { emit_warning!( field.ty.span().unwrap(), "unsupported field type will be ignored." ); - (None, is_required) + None } } } @@ -799,7 +785,7 @@ fn get_field_type(field: &Field) -> (Option, bool) { /// Generates code for a tuple struct with fields. fn handle_unnamed_field_struct(fields: &FieldsUnnamed, props_gen: &mut proc_macro2::TokenStream) { let field = fields.unnamed.iter().next().unwrap(); - let (ty_ref, _) = get_field_type(&field); + let ty_ref = get_field_type(&field); if let Some(ty_ref) = ty_ref { props_gen.extend(quote!({ @@ -877,7 +863,7 @@ fn handle_field_struct( field_name = prop.rename(&field_name); } - let (ty_ref, is_required) = get_field_type(&field); + let ty_ref = get_field_type(&field); let docs = extract_documentation(&field.attrs); let docs = docs.trim(); @@ -897,11 +883,11 @@ fn handle_field_struct( }) }; - if is_required { - gen.extend(quote! { + gen.extend(quote! { + if #ty_ref::is_required() { schema.required.insert(#field_name.into()); - }); - } + } + }); props_gen.extend(gen); } From 2a60566a25894b173640a9f9e57f8f832c4a6730 Mon Sep 17 00:00:00 2001 From: Omid Rad Date: Sun, 6 Dec 2020 10:08:42 +0100 Subject: [PATCH 2/4] Convert function to constant --- core/src/v2/schema.rs | 17 +++++------------ macros/src/actix.rs | 2 +- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/core/src/v2/schema.rs b/core/src/v2/schema.rs index 1e85008ce..18f18e011 100644 --- a/core/src/v2/schema.rs +++ b/core/src/v2/schema.rs @@ -250,6 +250,9 @@ pub trait Apiv2Schema { /// Description of this schema. In case the trait is derived, uses the documentation on the type. const DESCRIPTION: &'static str = ""; + /// Indicates the requirement of this schema. + const REQUIRED: bool = true; + /// Returns the raw schema for this object. fn raw_schema() -> DefaultSchemaRaw { Default::default() @@ -286,10 +289,6 @@ pub trait Apiv2Schema { fn security_scheme() -> Option { None } - - fn is_required() -> bool { - true - } } impl Apiv2Schema for () {} @@ -308,6 +307,7 @@ impl Apiv2Schema for T { #[cfg(feature = "nightly")] impl Apiv2Schema for Option { default const NAME: Option<&'static str> = None; + default const REQUIRED: bool = false; default fn raw_schema() -> DefaultSchemaRaw { Default::default() @@ -316,14 +316,11 @@ impl Apiv2Schema for Option { default fn security_scheme() -> Option { None } - - fn is_required() -> bool { - false - } } impl Apiv2Schema for Option { const NAME: Option<&'static str> = T::NAME; + const REQUIRED: bool = false; fn raw_schema() -> DefaultSchemaRaw { T::raw_schema() @@ -332,10 +329,6 @@ impl Apiv2Schema for Option { fn security_scheme() -> Option { T::security_scheme() } - - fn is_required() -> bool { - false - } } #[cfg(feature = "nightly")] diff --git a/macros/src/actix.rs b/macros/src/actix.rs index fef02a3bc..8d4fa9bff 100644 --- a/macros/src/actix.rs +++ b/macros/src/actix.rs @@ -884,7 +884,7 @@ fn handle_field_struct( }; gen.extend(quote! { - if #ty_ref::is_required() { + if #ty_ref::REQUIRED { schema.required.insert(#field_name.into()); } }); From 9e5775b486faa9d76fd22fe1b79a1c5ff3328233 Mon Sep 17 00:00:00 2001 From: Omid Rad Date: Sun, 6 Dec 2020 10:15:05 +0100 Subject: [PATCH 3/4] Just simplify a line! --- macros/src/actix.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/macros/src/actix.rs b/macros/src/actix.rs index 8d4fa9bff..0cdcfcee5 100644 --- a/macros/src/actix.rs +++ b/macros/src/actix.rs @@ -785,9 +785,8 @@ fn get_field_type(field: &Field) -> Option { /// Generates code for a tuple struct with fields. fn handle_unnamed_field_struct(fields: &FieldsUnnamed, props_gen: &mut proc_macro2::TokenStream) { let field = fields.unnamed.iter().next().unwrap(); - let ty_ref = get_field_type(&field); - if let Some(ty_ref) = ty_ref { + if let Some(ty_ref) = get_field_type(&field) { props_gen.extend(quote!({ schema = #ty_ref::raw_schema(); })); From 4c7c2d629c83ef8f2d6296060764fc3c836d5002 Mon Sep 17 00:00:00 2001 From: Omid Rad Date: Sun, 6 Dec 2020 10:58:57 +0100 Subject: [PATCH 4/4] Init an optional type alias in the tests --- tests/test_app.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_app.rs b/tests/test_app.rs index 68a093326..1db3f576d 100644 --- a/tests/test_app.rs +++ b/tests/test_app.rs @@ -24,6 +24,8 @@ use uuid_dev::Uuid; static CLIENT: Lazy = Lazy::new(|| reqwest::blocking::Client::new()); static PORTS: Lazy>> = Lazy::new(|| Mutex::new(HashSet::new())); +type OptionalUuid = Option; + #[derive(Deserialize, Serialize, Apiv2Schema)] #[serde(rename_all = "lowercase")] enum PetClass { @@ -44,7 +46,7 @@ struct Pet { birthday: chrono_dev::NaiveDate, updated_on: Option, #[serde(rename = "uuid")] - uid: Option, + uid: OptionalUuid, } impl Default for Pet {