From 64544e05d6eb394de87f47c82da655b50cc70295 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Fri, 26 Jan 2024 16:34:39 -0300 Subject: [PATCH 1/3] Implement inline generics --- macros/src/types/generics.rs | 17 ++++++++++++++--- ts-rs/tests/generics.rs | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/macros/src/types/generics.rs b/macros/src/types/generics.rs index 4766de970..f808feb03 100644 --- a/macros/src/types/generics.rs +++ b/macros/src/types/generics.rs @@ -40,7 +40,7 @@ pub fn format_generics(deps: &mut Dependencies, generics: &Generics) -> TokenStr pub fn format_type(ty: &Type, dependencies: &mut Dependencies, generics: &Generics) -> TokenStream { // If the type matches one of the generic parameters, just pass the identifier: - if let Some(generic_ident) = generics + if let Some(generic) = generics .params .iter() .filter_map(|param| match param { @@ -55,9 +55,20 @@ pub fn format_type(ty: &Type, dependencies: &mut Dependencies, generics: &Generi && type_path.path.is_ident(&type_param.ident) ) }) - .map(|type_param| type_param.ident.to_string()) { - return quote!(#generic_ident.to_owned()); + let generic_ident = generic.ident.clone(); + let generic_ident_str = generic_ident.to_string(); + + if !generic.bounds.is_empty() || generic.default.is_some() { + return quote!(#generic_ident_str.to_owned()); + } + + return quote!( + match <#generic_ident>::name().as_str() { + "null" => #generic_ident_str.to_owned(), + x => x.to_owned() + } + ); } // special treatment for arrays and tuples diff --git a/ts-rs/tests/generics.rs b/ts-rs/tests/generics.rs index b4f8183cd..11ec47181 100644 --- a/ts-rs/tests/generics.rs +++ b/ts-rs/tests/generics.rs @@ -147,7 +147,7 @@ fn generic_struct() { } #[test] -#[ignore] +// #[ignore] // https://github.com/Aleph-Alpha/ts-rs/issues/56 TODO fn inline() { #[derive(TS)] @@ -167,7 +167,7 @@ fn inline() { assert_eq!(Generic::<()>::decl(), "type Generic = { t: T, }"); assert_eq!( Container::decl(), - "type Container = { g: Generic, gi: { t: string }, t: string, }" + "type Container = { g: Generic, gi: { t: string, }, t: string, }" ); } From 3667ef65fbad96d036f401f78ca1a68d98ec76d6 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 29 Jan 2024 15:33:29 -0300 Subject: [PATCH 2/3] Add a comment explaining why check for "null" --- macros/src/types/generics.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/macros/src/types/generics.rs b/macros/src/types/generics.rs index f808feb03..beacc2959 100644 --- a/macros/src/types/generics.rs +++ b/macros/src/types/generics.rs @@ -65,7 +65,13 @@ pub fn format_type(ty: &Type, dependencies: &mut Dependencies, generics: &Generi return quote!( match <#generic_ident>::name().as_str() { + // When exporting a generic, the default type used is `()`, + // which gives "null" when calling `.name()`. In this case, we + // want to preserve the type param's identifier as the name used "null" => #generic_ident_str.to_owned(), + + // If name is not "null", a type has been provided, so we use its + // name instead x => x.to_owned() } ); From 9bc22995cc02fadab935c8c5a2ba2d80aeddce47 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 29 Jan 2024 16:55:05 -0300 Subject: [PATCH 3/3] Add ignored tests for missing implementations --- ts-rs/tests/generics.rs | 52 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/ts-rs/tests/generics.rs b/ts-rs/tests/generics.rs index 11ec47181..961fffc0b 100644 --- a/ts-rs/tests/generics.rs +++ b/ts-rs/tests/generics.rs @@ -147,8 +147,6 @@ fn generic_struct() { } #[test] -// #[ignore] -// https://github.com/Aleph-Alpha/ts-rs/issues/56 TODO fn inline() { #[derive(TS)] struct Generic { @@ -171,6 +169,56 @@ fn inline() { ); } +#[test] +#[ignore = "We haven't figured out how to inline generics with bounds yet"] +fn inline_with_bounds() { + #[derive(TS)] + struct Generic { + t: T, + } + + #[derive(TS)] + struct Container { + g: Generic, + #[ts(inline)] + gi: Generic, + #[ts(flatten)] + t: Generic, + } + + assert_eq!(Generic::<&'static str>::decl(), "type Generic = { t: T, }"); + assert_eq!( + Container::decl(), + "type Container = { g: Generic, gi: { t: string, }, t: number, }" + // Actual output: { g: Generic, gi: { t: T, }, t: T, } + ); +} + +#[test] +#[ignore = "We haven't figured out how to inline generics with defaults yet"] +fn inline_with_default() { + #[derive(TS)] + struct Generic { + t: T, + } + + #[derive(TS)] + struct Container { + g: Generic, + #[ts(inline)] + gi: Generic, + #[ts(flatten)] + t: Generic, + } + + assert_eq!(Generic::<&'static str>::decl(), "type Generic = { t: T, }"); + assert_eq!( + Container::decl(), + "type Container = { g: Generic, gi: { t: string, }, t: number, }" + // Actual output: { g: Generic, gi: { t: T, }, t: T, } + ); +} + #[test] fn default() { #[derive(TS)]