From 1171bc507d41a1c0015272187da8288ad8a8ffb1 Mon Sep 17 00:00:00 2001 From: Rom's Date: Sun, 7 May 2023 08:48:41 +0700 Subject: [PATCH 1/7] :construction: add supports flatten to language trait --- core/src/language/go.rs | 4 ++++ core/src/language/kotlin.rs | 4 ++++ core/src/language/mod.rs | 1 + core/src/language/scala.rs | 4 ++++ core/src/language/swift.rs | 4 ++++ core/src/language/typescript.rs | 4 ++++ 6 files changed, 21 insertions(+) diff --git a/core/src/language/go.rs b/core/src/language/go.rs index 9cd3a9d2..305c6414 100644 --- a/core/src/language/go.rs +++ b/core/src/language/go.rs @@ -154,6 +154,10 @@ impl Language for Go { writeln!(w, "}}") } + + fn supports_flatten(&self) -> bool { + false + } } impl Go { diff --git a/core/src/language/kotlin.rs b/core/src/language/kotlin.rs index fe9703d6..6d7c01f5 100644 --- a/core/src/language/kotlin.rs +++ b/core/src/language/kotlin.rs @@ -181,6 +181,10 @@ impl Language for Kotlin { writeln!(w, "}}\n") } + + fn supports_flatten(&self) -> bool { + false + } } impl Kotlin { diff --git a/core/src/language/mod.rs b/core/src/language/mod.rs index 198a0296..dfabb509 100644 --- a/core/src/language/mod.rs +++ b/core/src/language/mod.rs @@ -293,4 +293,5 @@ pub trait Language { Ok(()) } + fn supports_flatten(&self) -> bool; } diff --git a/core/src/language/scala.rs b/core/src/language/scala.rs index be7ce99d..fb018901 100644 --- a/core/src/language/scala.rs +++ b/core/src/language/scala.rs @@ -209,6 +209,10 @@ impl Language for Scala { self.write_enum_variants(w, e)?; writeln!(w, "}}\n") } + + fn supports_flatten(&self) -> bool { + false + } } impl Scala { diff --git a/core/src/language/swift.rs b/core/src/language/swift.rs index a106def8..7ce80004 100644 --- a/core/src/language/swift.rs +++ b/core/src/language/swift.rs @@ -445,6 +445,10 @@ impl Language for Swift { writeln!(w, "}}") } + + fn supports_flatten(&self) -> bool { + false + } } impl Swift { diff --git a/core/src/language/typescript.rs b/core/src/language/typescript.rs index 32bf7ae6..efcaa76b 100644 --- a/core/src/language/typescript.rs +++ b/core/src/language/typescript.rs @@ -160,6 +160,10 @@ impl Language for TypeScript { } } } + + fn supports_flatten(&self) -> bool { + true + } } impl TypeScript { From 037a0bd70093c9d70046a2f9886514de829fc8d4 Mon Sep 17 00:00:00 2001 From: Rom's Date: Sun, 7 May 2023 08:53:13 +0700 Subject: [PATCH 2/7] :construction: propagate supports flatten parameter --- cli/src/main.rs | 3 ++- core/src/lib.rs | 2 +- core/src/parser.rs | 6 +++--- core/tests/snapshot_tests.rs | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index d9da38b5..ac982a30 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -253,12 +253,13 @@ fn main() { .filter_map(|dir_entry| dir_entry.path().to_str().map(String::from)) .collect(); + let supports_flatten = lang.supports_flatten(); let mut generated_contents = vec![]; let parsed_data = glob_paths .par_iter() .map(|filepath| { let data = std::fs::read_to_string(filepath).unwrap(); - let parsed_data = typeshare_core::parser::parse(&data); + let parsed_data = typeshare_core::parser::parse(&data, supports_flatten); if parsed_data.is_err() { panic!("{}", parsed_data.err().unwrap()); } diff --git a/core/src/lib.rs b/core/src/lib.rs index 65a8c8c3..4a57d661 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -30,7 +30,7 @@ pub fn process_input( language: &mut dyn Language, out: &mut dyn Write, ) -> Result<(), ProcessInputError> { - let parsed_data = parser::parse(input)?; + let parsed_data = parser::parse(input, language.supports_flatten())?; language.generate_types(out, &parsed_data)?; Ok(()) } diff --git a/core/src/parser.rs b/core/src/parser.rs index 36e1bc7f..dd0d250a 100644 --- a/core/src/parser.rs +++ b/core/src/parser.rs @@ -78,7 +78,7 @@ pub enum ParseError { } /// Parse the given Rust source string into `ParsedData`. -pub fn parse(input: &str) -> Result { +pub fn parse(input: &str, supports_flatten: bool) -> Result { let mut parsed_data = ParsedData::default(); // We will only produce output for files that contain the `#[typeshare]` @@ -94,7 +94,7 @@ pub fn parse(input: &str) -> Result { for item in flatten_items(source.items.iter()) { match item { syn::Item::Struct(s) if has_typeshare_annotation(&s.attrs) => { - parsed_data.push_rust_thing(parse_struct(s)?); + parsed_data.push_rust_thing(parse_struct(s, supports_flatten)?); } syn::Item::Enum(e) if has_typeshare_annotation(&e.attrs) => { parsed_data.push_rust_thing(parse_enum(e)?); @@ -131,7 +131,7 @@ fn flatten_items<'a>( /// /// This function can currently return something other than a struct, which is a /// hack. -fn parse_struct(s: &ItemStruct) -> Result { +fn parse_struct(s: &ItemStruct, supports_flatten: bool) -> Result { let serde_rename_all = serde_rename_all(&s.attrs); let generic_types = s diff --git a/core/tests/snapshot_tests.rs b/core/tests/snapshot_tests.rs index 9a1826a9..2d57dc9a 100644 --- a/core/tests/snapshot_tests.rs +++ b/core/tests/snapshot_tests.rs @@ -67,7 +67,7 @@ fn check( )?; let mut typeshare_output: Vec = Vec::new(); - let parsed_data = typeshare_core::parser::parse(&rust_input)?; + let parsed_data = typeshare_core::parser::parse(&rust_input, lang.supports_flatten())?; lang.generate_types(&mut typeshare_output, &parsed_data)?; let typeshare_output = String::from_utf8(typeshare_output)?; From a75852b4ad337fd30d1760c3015672385b6527bb Mon Sep 17 00:00:00 2001 From: Rom's Date: Sun, 7 May 2023 08:57:35 +0700 Subject: [PATCH 3/7] :construction: add flattened to rust field --- core/src/parser.rs | 14 +++++++++++--- core/src/rust_types.rs | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/src/parser.rs b/core/src/parser.rs index dd0d250a..09e283ad 100644 --- a/core/src/parser.rs +++ b/core/src/parser.rs @@ -156,6 +156,7 @@ fn parse_struct(s: &ItemStruct, supports_flatten: bool) -> Result { @@ -170,9 +171,14 @@ fn parse_struct(s: &ItemStruct, supports_flatten: bool) -> Result Result>()?; @@ -380,6 +387,7 @@ fn parse_enum_variant( comments: parse_comment_attrs(&f.attrs), has_default, decorators, + flattened: false, }) }) .collect::, ParseError>>()?, diff --git a/core/src/rust_types.rs b/core/src/rust_types.rs index 49c55393..1cb46b1f 100644 --- a/core/src/rust_types.rs +++ b/core/src/rust_types.rs @@ -77,6 +77,7 @@ pub struct RustField { /// Language-specific decorators assigned to a given field. /// The keys are language names (e.g. SupportedLanguage::TypeScript), the values are decorators (e.g. readonly) pub decorators: HashMap>, + pub flattened: bool, } /// A Rust type. From ee5923f734abfb50d7ce5054190fa4dfc9642707 Mon Sep 17 00:00:00 2001 From: Rom's Date: Sun, 7 May 2023 09:20:04 +0700 Subject: [PATCH 4/7] :sparkles: implement inheritance from flattened fields --- core/src/language/typescript.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/core/src/language/typescript.rs b/core/src/language/typescript.rs index efcaa76b..f58da201 100644 --- a/core/src/language/typescript.rs +++ b/core/src/language/typescript.rs @@ -110,13 +110,33 @@ impl Language for TypeScript { fn write_struct(&mut self, w: &mut dyn Write, rs: &RustStruct) -> std::io::Result<()> { self.write_comments(w, 0, &rs.comments)?; + let mut inheritance = "".to_string(); + let mut count = 0; + for field in rs.fields.iter() { + if field.flattened { + let ts_ty = match self.format_type(&field.ty, rs.generic_types.as_slice()) { + Ok(v) => v, + Err(e) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, e)), + }; + if count >= 1 { + inheritance.push_str(", "); + } + inheritance.push_str(ts_ty.as_str()); + count += 1; + } + } writeln!( w, - "export interface {}{} {{", + "export interface {}{}{} {{", rs.id.renamed, (!rs.generic_types.is_empty()) .then(|| format!("<{}>", rs.generic_types.join(", "))) - .unwrap_or_default() + .unwrap_or_default(), + if !inheritance.is_empty() { + format!(" extends {inheritance}") + } else { + "".to_string() + } )?; rs.fields @@ -234,6 +254,9 @@ impl TypeScript { field: &RustField, generic_types: &[String], ) -> std::io::Result<()> { + if field.flattened { + return Ok(()); + } self.write_comments(w, 1, &field.comments)?; let ts_ty = self .format_type(&field.ty, generic_types) From 6608b74d02ed0413a8f736a4f0929719069a8f3f Mon Sep 17 00:00:00 2001 From: Rom's Date: Wed, 24 May 2023 08:44:53 +0700 Subject: [PATCH 5/7] :rotating_light: fix clippy missing docs --- core/src/language/mod.rs | 1 + core/src/rust_types.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core/src/language/mod.rs b/core/src/language/mod.rs index df2ac95e..34514f00 100644 --- a/core/src/language/mod.rs +++ b/core/src/language/mod.rs @@ -294,5 +294,6 @@ pub trait Language { Ok(()) } + /// whether `#[serde(flatten)]` macro attribute is supported or not fn supports_flatten(&self) -> bool; } diff --git a/core/src/rust_types.rs b/core/src/rust_types.rs index 1cb46b1f..a80bf00e 100644 --- a/core/src/rust_types.rs +++ b/core/src/rust_types.rs @@ -77,6 +77,8 @@ pub struct RustField { /// Language-specific decorators assigned to a given field. /// The keys are language names (e.g. SupportedLanguage::TypeScript), the values are decorators (e.g. readonly) pub decorators: HashMap>, + /// Whether the field should be flattened or not, + /// as per `#[serde(flatten)]` definition. pub flattened: bool, } From 9aa71fbf91191e041c71253fa46d5ac0d5cef273 Mon Sep 17 00:00:00 2001 From: Rom's Date: Fri, 26 May 2023 06:23:38 +0700 Subject: [PATCH 6/7] :recycle: refactor from review --- core/src/language/typescript.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core/src/language/typescript.rs b/core/src/language/typescript.rs index f58da201..f7ecf44c 100644 --- a/core/src/language/typescript.rs +++ b/core/src/language/typescript.rs @@ -114,10 +114,9 @@ impl Language for TypeScript { let mut count = 0; for field in rs.fields.iter() { if field.flattened { - let ts_ty = match self.format_type(&field.ty, rs.generic_types.as_slice()) { - Ok(v) => v, - Err(e) => return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, e)), - }; + let ts_ty = self + .format_type(&field.ty, rs.generic_types.as_slice()) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?; if count >= 1 { inheritance.push_str(", "); } From c70b5368908acf1c0526ed42ef45c3d92a46ddad Mon Sep 17 00:00:00 2001 From: Rom's Date: Fri, 26 May 2023 06:25:32 +0700 Subject: [PATCH 7/7] :recycle: refactor from review --- core/src/language/typescript.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/language/typescript.rs b/core/src/language/typescript.rs index f7ecf44c..5a8f47dc 100644 --- a/core/src/language/typescript.rs +++ b/core/src/language/typescript.rs @@ -115,7 +115,7 @@ impl Language for TypeScript { for field in rs.fields.iter() { if field.flattened { let ts_ty = self - .format_type(&field.ty, rs.generic_types.as_slice()) + .format_type(&field.ty, &rs.generic_types) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?; if count >= 1 { inheritance.push_str(", ");