Skip to content

Commit

Permalink
first attempt at newtype variant support
Browse files Browse the repository at this point in the history
  • Loading branch information
msrd0 committed Mar 12, 2022
1 parent 2032822 commit 198bdb0
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 23 deletions.
42 changes: 24 additions & 18 deletions derive/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,13 @@ impl ParseData {
}
}

fn gen_struct(name: Option<&LitStr>, doc: &[String], fields: &[ParseDataField], deny_unknown_fields: bool) -> TokenStream {
let str = path!(::core::primitive::str);
let string = path!(::std::string::String);
let option = path!(::core::option::Option);

let name = match name {
Some(name) => quote!(#option::Some(#name)),
None => quote!(#option::None)
};
let doc = gen_doc_option(doc);

let fields = fields.iter().map(|f| {
let name = &f.name;
let doc = gen_doc_option(&f.doc);
let visit = match &f.ty {
TypeOrInline::Type(ty) => {
impl TypeOrInline {
fn visit_type_fn(&self) -> TokenStream {
match self {
Self::Type(ty) => {
quote_spanned!(ty.span() => <#ty as ::openapi_type::OpenapiType>::visit_type)
},
TypeOrInline::Inline(data) => {
Self::Inline(data) => {
let visit_impl = data.gen_visit_impl();
quote! {
{
Expand All @@ -61,7 +49,25 @@ fn gen_struct(name: Option<&LitStr>, doc: &[String], fields: &[ParseDataField],
}
}
}
};
}
}
}

fn gen_struct(name: Option<&LitStr>, doc: &[String], fields: &[ParseDataField], deny_unknown_fields: bool) -> TokenStream {
let str = path!(::core::primitive::str);
let string = path!(::std::string::String);
let option = path!(::core::option::Option);

let name = match name {
Some(name) => quote!(#option::Some(#name)),
None => quote!(#option::None)
};
let doc = gen_doc_option(doc);

let fields = fields.iter().map(|f| {
let name = &f.name;
let doc = gen_doc_option(&f.doc);
let visit = f.ty.visit_type_fn();

if f.flatten {
quote!({
Expand Down
18 changes: 18 additions & 0 deletions derive/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,24 @@ pub(super) fn parse_enum(ident: &Ident, inum: &DataEnum, attrs: &ContainerAttrib
}
}));
},
Fields::Unnamed(unnamed_fields) if unnamed_fields.unnamed.len() == 1 => {
let struct_name = format!("{ident}::{}", name.value());
let ty = unnamed_fields.unnamed.first().unwrap().ty.clone();
// TODO add documentation here
types.push((name.clone(), ParseData {
name: Some(struct_name.to_lit_str()),
doc: Vec::new(),
ty: ParseDataType::Struct {
fields: vec![ParseDataField {
name,
doc: Vec::new(),
ty: TypeOrInline::Type(Box::new(ty)),
flatten: false
}],
deny_unknown_fields: attrs.deny_unknown_fields
}
}));
},
Fields::Unnamed(unnamed_fields) => {
return Err(syn::Error::new(
unnamed_fields.span(),
Expand Down
16 changes: 16 additions & 0 deletions tests/custom_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,22 @@ test_type!(EnumWithOneField = {
}
});

#[derive(OpenapiType)]
enum EnumWithOneNewtypeVariant {
Success(SimpleStruct)
}
test_type!(EnumWithOneNewtypeVariant = {
"type": "object",
"title": "EnumWithOneNewtypeVariant",
"properties": {
"Success": {
"$ref": "#/components/schemas/EnumWithOneNewtypeVariant__Success"
}
},
"required": ["Success"],
"additionalProperties": false
});

#[derive(OpenapiType)]
enum EnumWithFields {
Success { value: isize },
Expand Down
23 changes: 18 additions & 5 deletions tests/util/test_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ macro_rules! test_type {
($ty:ty = $json:tt) => {
paste::paste! {
#[test]
fn [< $ty:lower >]() {
fn [< $ty:lower _no_dependencies >]() {
let schema = <$ty as OpenapiType>::schema();
let schema_json = serde_json::to_value(&schema.schema).unwrap();
let expected = serde_json::json!($json);
pretty_assertions::assert_eq!(schema_json, expected);
assert!(
schema.dependencies.is_empty(),
"Expected dependencies to be empty, but is {:#?}",
schema.dependencies
);
}
}
};
($ty:ty = $json:tt, {$($dep_name:literal: $dep_json:tt),*}) => {
test_type!($ty = $json);
test_type!(@internal $ty = $json);
paste::paste! {
#[test]
fn [< $ty:lower _dependencies >]() {
Expand All @@ -27,4 +29,15 @@ macro_rules! test_type {
}
}
};
(@internal $ty:ty = $json:tt) => {
paste::paste! {
#[test]
fn [< $ty:lower >]() {
let schema = <$ty as OpenapiType>::schema();
let schema_json = serde_json::to_value(&schema.schema).unwrap();
let expected = serde_json::json!($json);
pretty_assertions::assert_eq!(schema_json, expected);
}
}
}
}

0 comments on commit 198bdb0

Please sign in to comment.