feat(codegen): implemented oneOf unions for primitive types

This commit is contained in:
pyrite 2025-05-27 19:27:59 +02:00
parent 83dfdb27ac
commit 39731f2f5d
Signed by: pyrite
GPG key ID: 7F1BA9170CD35D15
8 changed files with 380 additions and 129 deletions

View file

@ -6,7 +6,7 @@ use syn::Ident;
use crate::openapi::r#type::OpenApiType;
use super::r#enum::Enum;
use super::{r#enum::Enum, ResolvedSchema};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrimitiveType {
@ -28,7 +28,11 @@ pub enum PropertyType {
}
impl PropertyType {
pub fn codegen(&self, namespace: &mut ObjectNamespace) -> Option<TokenStream> {
pub fn codegen(
&self,
namespace: &mut ObjectNamespace,
resolved: &ResolvedSchema,
) -> Option<TokenStream> {
match self {
Self::Primitive(PrimitiveType::Bool) => Some(format_ident!("bool").into_token_stream()),
Self::Primitive(PrimitiveType::I32) => Some(format_ident!("i32").into_token_stream()),
@ -47,7 +51,7 @@ impl PropertyType {
Some(quote! { crate::models::#name })
}
Self::Enum(r#enum) => {
let code = r#enum.codegen()?;
let code = r#enum.codegen(resolved)?;
namespace.push_element(code);
let ns = namespace.get_ident();
@ -58,14 +62,14 @@ impl PropertyType {
})
}
Self::Array(array) => {
let inner_ty = array.codegen(namespace)?;
let inner_ty = array.codegen(namespace, resolved)?;
Some(quote! {
Vec<#inner_ty>
})
}
Self::Nested(nested) => {
let code = nested.codegen()?;
let code = nested.codegen(resolved)?;
namespace.push_element(code);
let ns = namespace.get_ident();
@ -233,7 +237,11 @@ impl Property {
}
}
pub fn codegen(&self, namespace: &mut ObjectNamespace) -> Option<TokenStream> {
pub fn codegen(
&self,
namespace: &mut ObjectNamespace,
resolved: &ResolvedSchema,
) -> Option<TokenStream> {
let desc = self.description.as_ref().map(|d| quote! { #[doc = #d]});
let name = &self.name;
@ -246,7 +254,7 @@ impl Property {
_ => (format_ident!("{name}"), None),
};
let ty_inner = self.r#type.codegen(namespace)?;
let ty_inner = self.r#type.codegen(namespace, resolved)?;
let ty = if !self.required || self.nullable {
quote! { Option<#ty_inner> }
@ -303,6 +311,7 @@ impl Object {
}
// TODO: implement custom enum for this (depends on overrides being added)
// Maybe this is an issue with the schema instead?
if *prop_name == "value" && name == "TornHof" {
continue;
}
@ -348,7 +357,7 @@ impl Object {
Some(result)
}
pub fn codegen(&self) -> Option<TokenStream> {
pub fn codegen(&self, resolved: &ResolvedSchema) -> Option<TokenStream> {
let doc = self.description.as_ref().map(|d| {
quote! {
#[doc = #d]
@ -363,7 +372,7 @@ impl Object {
let mut props = Vec::with_capacity(self.properties.len());
for prop in &self.properties {
props.push(prop.codegen(&mut namespace)?);
props.push(prop.codegen(&mut namespace, resolved)?);
}
let name = format_ident!("{}", self.name);
@ -422,18 +431,6 @@ mod test {
use crate::openapi::schema::test::get_schema;
#[test]
fn resolve_object() {
let schema = get_schema();
let attack = schema.components.schemas.get("FactionUpgrades").unwrap();
let resolved =
Object::from_schema_object("FactionUpgrades", attack, &schema.components.schemas)
.unwrap();
let _code = resolved.codegen().unwrap();
}
#[test]
fn resolve_objects() {
let schema = get_schema();