From a562561286f26012e228e52e503bb40f83cba843 Mon Sep 17 00:00:00 2001 From: Gustavo Shigueo Date: Sun, 10 Nov 2024 19:41:55 -0300 Subject: [PATCH] Turn Optional into an enum --- macros/src/attr/field.rs | 9 +++------ macros/src/attr/mod.rs | 30 +++++++++++++++++++++++------- macros/src/attr/struct.rs | 5 +---- macros/src/types/named.rs | 26 +++++++------------------- 4 files changed, 34 insertions(+), 36 deletions(-) diff --git a/macros/src/attr/field.rs b/macros/src/attr/field.rs index bf255757..8994bd66 100644 --- a/macros/src/attr/field.rs +++ b/macros/src/attr/field.rs @@ -55,10 +55,7 @@ impl Attr for FieldAttr { rename: self.rename.or(other.rename), inline: self.inline || other.inline, skip: self.skip || other.skip, - optional: Optional { - optional: self.optional.optional || other.optional.optional, - nullable: self.optional.nullable || other.optional.nullable, - }, + optional: self.optional.or(other.optional), flatten: self.flatten || other.flatten, using_serde_with: self.using_serde_with || other.using_serde_with, @@ -124,7 +121,7 @@ impl Attr for FieldAttr { ); } - if self.optional.optional { + if let Optional::Optional { .. } = self.optional { syn_err_spanned!( field; "`optional` is not compatible with `flatten`" @@ -147,7 +144,7 @@ impl Attr for FieldAttr { ); } - if self.optional.optional { + if let Optional::Optional { .. } = self.optional { syn_err_spanned!( field; "`optional` cannot with tuple struct fields" diff --git a/macros/src/attr/mod.rs b/macros/src/attr/mod.rs index de2d4f08..61debed4 100644 --- a/macros/src/attr/mod.rs +++ b/macros/src/attr/mod.rs @@ -19,9 +19,28 @@ mod variant; /// `#[ts(optional)]` turns an `t: Option` into `t?: T`, while /// `#[ts(optional = nullable)]` turns it into `t?: T | null`. #[derive(Default, Clone, Copy)] -pub struct Optional { - pub optional: bool, - pub nullable: bool, +pub enum Optional { + Optional { + nullable: bool, + }, + + #[default] + NotOptional, +} + +impl Optional { + pub fn or(self, other: Optional) -> Self { + match (self, other) { + (Self::NotOptional, Self::NotOptional) => Self::NotOptional, + + (Self::Optional { nullable }, Self::NotOptional) + | (Self::NotOptional, Self::Optional { nullable }) => Self::Optional { nullable }, + + (Self::Optional { nullable: a }, Self::Optional { nullable: b }) => { + Self::Optional { nullable: a || b } + } + } + } } #[derive(Copy, Clone, Debug)] @@ -202,8 +221,5 @@ fn parse_optional(input: ParseStream) -> Result { false }; - Ok(Optional { - optional: true, - nullable, - }) + Ok(Optional::Optional { nullable }) } diff --git a/macros/src/attr/struct.rs b/macros/src/attr/struct.rs index 5a693574..9cd74054 100644 --- a/macros/src/attr/struct.rs +++ b/macros/src/attr/struct.rs @@ -91,10 +91,7 @@ impl Attr for StructAttr { (Some(bound), None) | (None, Some(bound)) => Some(bound), (None, None) => None, }, - optional: Optional { - optional: self.optional.optional || other.optional.optional, - nullable: self.optional.nullable || other.optional.nullable, - }, + optional: self.optional.or(other.optional), } } diff --git a/macros/src/types/named.rs b/macros/src/types/named.rs index e6267144..737baf85 100644 --- a/macros/src/types/named.rs +++ b/macros/src/types/named.rs @@ -105,30 +105,18 @@ fn format_field( let ty = field_attr.type_as(&field.ty); let opt = match (struct_optional, field_attr.optional) { - ( - opt @ Optional { optional: true, .. }, - Optional { - optional: false, .. - }, - ) => opt, - (_, opt @ Optional { optional: true, .. }) => opt, - ( - opt @ Optional { - optional: false, .. - }, - Optional { - optional: false, .. - }, - ) => opt, + (opt @ Optional::Optional { .. }, Optional::NotOptional) => opt, + (_, opt @ Optional::Optional { .. }) => opt, + (opt @ Optional::NotOptional, Optional::NotOptional) => opt, }; - let optional_annotation = if opt.optional { + let optional_annotation = if let Optional::Optional { .. } = opt { quote! { if <#ty as #crate_rename::TS>::IS_OPTION { "?" } else { "" } } } else { quote! { "" } }; - let optional_annotation = if field_attr.optional.optional { + let optional_annotation = if let Optional::Optional { .. } = field_attr.optional { quote! { if <#ty as #crate_rename::TS>::IS_OPTION { #optional_annotation @@ -153,7 +141,7 @@ fn format_field( if field_attr.inline { dependencies.append_from(&ty); - if opt.optional && !opt.nullable { + if let Optional::Optional { nullable: false } = opt { quote! { if <#ty as #crate_rename::TS>::IS_OPTION { <#ty as #crate_rename::TS>::option_inner_inline().unwrap() @@ -166,7 +154,7 @@ fn format_field( } } else { dependencies.push(&ty); - if opt.optional && !opt.nullable { + if let Optional::Optional { nullable: false } = opt { quote! { if <#ty as #crate_rename::TS>::IS_OPTION { <#ty as #crate_rename::TS>::option_inner_name().unwrap()