From 331bb80acf403239f8c6ebb002241a3f2e2a4463 Mon Sep 17 00:00:00 2001 From: aviac Date: Fri, 19 Jan 2024 11:25:38 +0100 Subject: [PATCH 1/7] fix(typo?): remove weird line Authored-by: Aviac --- generator/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index cc02416..9e647af 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1023,7 +1023,6 @@ fn create_query_struct(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Re imp.push_str(&handler); } } - imp.push_str("s\n"); if fields.is_empty() { return Ok(String::new()); } else { From 1b6cd3467af2ea666e946446025d9c82cd3a8a62 Mon Sep 17 00:00:00 2001 From: aviac Date: Fri, 19 Jan 2024 11:26:14 +0100 Subject: [PATCH 2/7] feat(definitions): impl `Display` Instead of adding a `to_string` method on each definition struct, this commit implements `Display`. This shouldn't result in any breaking changes since the trait also exposes a method with the same name. I also tried to format the generated text here and there to make it more readable in the generate code base as well as in the generate text. Authored-by: Aviac --- generator/src/main.rs | 67 +++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index 9e647af..0796fbb 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -925,20 +925,23 @@ fn create_query_struct(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Re match ty { ParameterType::String => match param.format.as_deref() { Some("date-time" | "date") => { - writeln!(&mut handler, "s.push_str(\"{}=\");", param.name)?; - writeln!(&mut handler, "s.push_str(&{field_name}.format(&time::format_description::well_known::Rfc3339).unwrap());")?; - writeln!(&mut handler, "s.push('&');")?; + writeln!( + &mut handler, + "write!(f, \"{}={{field_name}}&\", field_name = {field_name}.format(&time::format_description::well_known::Rfc3339).unwrap())?;", + param.name)?; } _ => { - writeln!(&mut handler, "s.push_str(\"{}=\");", param.name)?; - writeln!(&mut handler, "s.push_str(&{field_name});")?; - writeln!(&mut handler, "s.push('&');")?; + writeln!( + &mut handler, + "write!(f, \"{}={{{}}}&\")?;", + param.name, field_name + )?; } }, ParameterType::Number | ParameterType::Integer | ParameterType::Boolean => { writeln!( &mut handler, - "write!(&mut s, \"{}={{}}&\", {field_name}).unwrap();", + "write!(f, \"{}={{{field_name}}}&\")?;", param.name )?; } @@ -952,17 +955,17 @@ fn create_query_struct(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Re ParameterType::String => { match param.format.as_deref() { Some("date-time" | "date") => { - "s.push_str(&item.format(&time::format_description::well_known::Rfc3339).unwrap());" + "write!(f, \"{{date}}\", item.format(&time::format_description::well_known::Rfc3339).unwrap())?;" }, _ => { - "s.push_str(&item);" + "write!(f, \"{item}\")?;" } } }, ParameterType::Number | ParameterType::Integer | ParameterType::Boolean => { - "write!(&mut s, \"{item}\").unwrap();" + "write!(f, \"{item}\")?;" }, ParameterType::Array => { eyre::bail!("nested arrays not supported in query"); @@ -1003,13 +1006,13 @@ fn create_query_struct(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Re )?); } CollectionFormat::Multi => { - writeln!(&mut handler, "")?; + writeln!(&mut handler)?; writeln!(&mut handler, "if !{field_name}.is_empty() {{")?; writeln!(&mut handler, "for item in {field_name} {{")?; - writeln!(&mut handler, "s.push_str(\"{}=\");", param.name)?; + writeln!(&mut handler, "write!(f, \"{}=\")?;", param.name)?; handler.push_str(item_pusher); handler.push('\n'); - writeln!(&mut handler, "s.push('&')")?; + writeln!(&mut handler, "write!(f, '&')?;")?; writeln!(&mut handler, "}}")?; writeln!(&mut handler, "}}")?; } @@ -1023,16 +1026,36 @@ fn create_query_struct(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Re imp.push_str(&handler); } } - if fields.is_empty() { - return Ok(String::new()); + + let result = if fields.is_empty() { + String::new() } else { let op_name = op .operation_id .as_ref() .ok_or_else(|| eyre::eyre!("no op id found"))? .to_pascal_case(); - return Ok(format!("pub struct {op_name}Query {{\n{fields}\n}}\n\nimpl {op_name}Query {{\npub(crate) fn to_string(self) -> String {{\n{imp}\n}}\n}}")); - } + // human readable format string + added whitespace so that the generate text is human + // readable as well + format!( + " +pub struct {op_name}Query {{ + {fields} +}} + +impl std::fmt::Display for {op_name}Query {{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {{ + {imp} + Ok(()) + }} +}} +", + fields = fields.replace('\n', "\n ").trim(), + imp = imp.replace('\n', "\n ").trim() + ) + }; + + Ok(result) } fn simple_query_array( @@ -1042,17 +1065,19 @@ fn simple_query_array( sep: &str, ) -> eyre::Result { let mut out = String::new(); - writeln!(&mut out, "s.push_str(\"{}=\");", param.name)?; - writeln!(&mut out, "")?; + + writeln!(&mut out)?; writeln!(&mut out, "if !{name}.is_empty() {{")?; - writeln!(&mut out, "for (i, item) in {name}.iter().enumerate() {{")?; + writeln!(&mut out, "for item in {name} {{")?; + writeln!(&mut out, "write!(f, \"{}=\")?;", param.name)?; out.push_str(item_pusher); out.push('\n'); writeln!(&mut out, "if i < {name}.len() - 1 {{")?; writeln!(&mut out, "s.push('{sep}')")?; writeln!(&mut out, "}}")?; writeln!(&mut out, "}}")?; - writeln!(&mut out, "s.push('&')")?; + writeln!(&mut out, "write!(f, '&')?;")?; writeln!(&mut out, "}}")?; + Ok(out) } From 32b6a3d1109d839efde3cc03cbf5990bd272c95e Mon Sep 17 00:00:00 2001 From: aviac Date: Mon, 22 Jan 2024 09:11:24 +0100 Subject: [PATCH 3/7] chore(cleanup): consolidate `writeln`s Authored-by: Aviac --- generator/src/main.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index 0796fbb..4e56d5e 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1066,18 +1066,21 @@ fn simple_query_array( ) -> eyre::Result { let mut out = String::new(); - writeln!(&mut out)?; - writeln!(&mut out, "if !{name}.is_empty() {{")?; - writeln!(&mut out, "for item in {name} {{")?; - writeln!(&mut out, "write!(f, \"{}=\")?;", param.name)?; - out.push_str(item_pusher); - out.push('\n'); - writeln!(&mut out, "if i < {name}.len() - 1 {{")?; - writeln!(&mut out, "s.push('{sep}')")?; - writeln!(&mut out, "}}")?; - writeln!(&mut out, "}}")?; - writeln!(&mut out, "write!(f, '&')?;")?; - writeln!(&mut out, "}}")?; + writeln!( + &mut out, + " +if !{name}.is_empty() {{ + for item in {name} {{ + write!(f, \"{}=\")?; + {item_pusher} + if i < {name}.len() - 1 {{ + write!(f, '{sep}')?; + }} + }} + write!(f, '&')?; +}}", + param.name + )?; Ok(out) } From 9566d232bf1f0333be3a89b2766713e0b74f3b61 Mon Sep 17 00:00:00 2001 From: aviac Date: Mon, 22 Jan 2024 09:21:46 +0100 Subject: [PATCH 4/7] feat(formatting): auto run rustfmt on generated file Authored-by: Aviac --- generator/src/main.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index 4e56d5e..7e2d290 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1,4 +1,4 @@ -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; mod openapi; @@ -34,7 +34,7 @@ fn main() -> eyre::Result<()> { s.push_str(&strukt); } s.push_str("\n}"); - save_generated(&mut s)?; + save_generated(&s)?; Ok(()) } @@ -49,10 +49,23 @@ fn get_spec() -> eyre::Result { fn save_generated(contents: &str) -> eyre::Result<()> { let path = std::env::var_os("FORGEJO_API_GENERATED_PATH") .unwrap_or_else(|| OsString::from("./src/generated.rs")); - std::fs::write(path, contents)?; + std::fs::write(path.as_os_str(), contents)?; + run_rustfmt_on(path.as_os_str()); Ok(()) } +fn run_rustfmt_on(path: &OsStr) { + let mut rustfmt = std::process::Command::new("rustfmt"); + + rustfmt.arg(path); + rustfmt.args(["--edition", "2021"]); + + if let Err(e) = rustfmt.status() { + println!("Tried to format {path:?}, but failed to do so! :("); + println!("Error:\n{e}"); + } +} + fn create_methods_for_path( spec: &OpenApiV2, path: &str, @@ -1049,9 +1062,7 @@ impl std::fmt::Display for {op_name}Query {{ Ok(()) }} }} -", - fields = fields.replace('\n', "\n ").trim(), - imp = imp.replace('\n', "\n ").trim() +" ) }; From a680fd921287d0acf5109e3f72517b8800ed84b7 Mon Sep 17 00:00:00 2001 From: aviac Date: Tue, 23 Jan 2024 09:23:46 +0100 Subject: [PATCH 5/7] chore(cleanup): remove comment Authored-by: Aviac --- generator/src/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index 7e2d290..b0629c1 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1048,8 +1048,6 @@ fn create_query_struct(spec: &OpenApiV2, path: &str, op: &Operation) -> eyre::Re .as_ref() .ok_or_else(|| eyre::eyre!("no op id found"))? .to_pascal_case(); - // human readable format string + added whitespace so that the generate text is human - // readable as well format!( " pub struct {op_name}Query {{ From a7299ab8411d18292394b97bfb4bc6ddc0586327 Mon Sep 17 00:00:00 2001 From: aviac Date: Tue, 23 Jan 2024 09:31:55 +0100 Subject: [PATCH 6/7] fix(list): adjust broken generated code Authored-by: Aviac --- generator/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index b0629c1..27fa5fb 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1079,7 +1079,7 @@ fn simple_query_array( &mut out, " if !{name}.is_empty() {{ - for item in {name} {{ + for (item, i) in {name}.iter().enumerate() {{ write!(f, \"{}=\")?; {item_pusher} if i < {name}.len() - 1 {{ From 5cabd12eb6a4fa5722f117a8369b09c3f11285bd Mon Sep 17 00:00:00 2001 From: aviac Date: Wed, 24 Jan 2024 21:43:03 +0100 Subject: [PATCH 7/7] fix(mistake): order of statements Authored-by: Aviac --- generator/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/src/main.rs b/generator/src/main.rs index 27fa5fb..97073ae 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -1079,8 +1079,8 @@ fn simple_query_array( &mut out, " if !{name}.is_empty() {{ + write!(f, \"{}=\")?; for (item, i) in {name}.iter().enumerate() {{ - write!(f, \"{}=\")?; {item_pusher} if i < {name}.len() - 1 {{ write!(f, '{sep}')?;