diff --git a/Cargo.lock b/Cargo.lock index 414ee74..db3813c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -480,12 +480,14 @@ version = "0.0.1" dependencies = [ "base64", "chrono", + "prettyplease", "progenitor", "progenitor-client", "rand", "reqwest", "serde", "serde_json", + "syn 1.0.109", "uuid", ] @@ -1217,6 +1219,16 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "proc-macro2" version = "1.0.56" @@ -1245,6 +1257,7 @@ dependencies = [ "rand", "regress", "reqwest", + "rustfmt-wrapper", "schemars", "serde", "serde_json", diff --git a/example-build/Cargo.toml b/example-build/Cargo.toml index d1eaac9..7c9d5b3 100644 --- a/example-build/Cargo.toml +++ b/example-build/Cargo.toml @@ -14,5 +14,7 @@ serde = { version = "1.0", features = ["derive"] } uuid = { version = "1.3", features = ["serde", "v4"] } [build-dependencies] +prettyplease = "0.1.25" progenitor = { path = "../progenitor" } serde_json = "1.0" +syn = "1.0" diff --git a/example-build/build.rs b/example-build/build.rs index ffb0ab4..2119be5 100644 --- a/example-build/build.rs +++ b/example-build/build.rs @@ -13,7 +13,9 @@ fn main() { let spec = serde_json::from_reader(file).unwrap(); let mut generator = progenitor::Generator::default(); - let content = generator.generate_text(&spec).unwrap(); + let tokens = generator.generate_tokens(&spec).unwrap(); + let ast = syn::parse2(tokens).unwrap(); + let content = prettyplease::unparse(&ast); let mut out_file = Path::new(&env::var("OUT_DIR").unwrap()).to_path_buf(); out_file.push("codegen.rs"); diff --git a/progenitor-impl/Cargo.toml b/progenitor-impl/Cargo.toml index 65afa01..2362d3d 100644 --- a/progenitor-impl/Cargo.toml +++ b/progenitor-impl/Cargo.toml @@ -16,7 +16,6 @@ openapiv3 = "1.0.0" proc-macro2 = "1.0" quote = "1.0" regex = "1.8" -rustfmt-wrapper = "0.2.0" schemars = { version = "0.8.12", features = ["chrono", "uuid1"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" @@ -32,5 +31,6 @@ dropshot = { git = "https://github.com/oxidecomputer/dropshot", default-features expectorate = "1.0" http = "0.2.9" hyper = "0.14.26" +rustfmt-wrapper = "0.2.0" serde_yaml = "0.9" serde_json = "1.0.96" diff --git a/progenitor-impl/src/cli.rs b/progenitor-impl/src/cli.rs index 505a2cb..1e9981b 100644 --- a/progenitor-impl/src/cli.rs +++ b/progenitor-impl/src/cli.rs @@ -10,7 +10,6 @@ use crate::{ method::{ OperationParameterKind, OperationParameterType, OperationResponseStatus, }, - space_out_items, to_schema::ToSchema, util::{sanitize, Case}, validate_openapi, Generator, Result, @@ -23,25 +22,6 @@ struct CliOperation { } impl Generator { - pub fn cli_text( - &mut self, - spec: &OpenAPI, - crate_name: &str, - ) -> Result { - let output = self.cli(spec, crate_name)?; - - let content = rustfmt_wrapper::rustfmt_config( - rustfmt_wrapper::config::Config { - format_strings: Some(true), - ..Default::default() - }, - output, - ) - .unwrap(); - - space_out_items(content) - } - /// Generate a `clap`-based CLI. pub fn cli( &mut self, diff --git a/progenitor-impl/src/lib.rs b/progenitor-impl/src/lib.rs index 4a1bed7..532b767 100644 --- a/progenitor-impl/src/lib.rs +++ b/progenitor-impl/src/lib.rs @@ -506,41 +506,7 @@ impl Generator { /// Render text output. pub fn generate_text(&mut self, spec: &OpenAPI) -> Result { - self.generate_text_impl( - spec, - rustfmt_wrapper::config::Config::default(), - ) - } - - /// Render text output and normalize doc comments - /// - /// Requires a nightly install of `rustfmt` (even if the target project is - /// not using nightly). - pub fn generate_text_normalize_comments( - &mut self, - spec: &OpenAPI, - ) -> Result { - self.generate_text_impl( - spec, - rustfmt_wrapper::config::Config { - normalize_doc_attributes: Some(true), - wrap_comments: Some(true), - ..Default::default() - }, - ) - } - - fn generate_text_impl( - &mut self, - spec: &OpenAPI, - config: rustfmt_wrapper::config::Config, - ) -> Result { - let output = self.generate_tokens(spec)?; - - // Format the file with rustfmt. - let content = rustfmt_wrapper::rustfmt_config(config, output).unwrap(); - - space_out_items(content) + Ok(self.generate_tokens(spec)?.to_string()) } // TODO deprecate? diff --git a/progenitor-impl/src/to_schema.rs b/progenitor-impl/src/to_schema.rs index 4f33a47..009d17b 100644 --- a/progenitor-impl/src/to_schema.rs +++ b/progenitor-impl/src/to_schema.rs @@ -89,7 +89,7 @@ impl Convert for openapiv3::Schema { // 2. It can be used within a oneOf or anyOf schema to determine which // subschema is relevant. This is easier to detect because it doesn't - // required chasing references. For each subschema we can then make it + // require chasing references. For each subschema we can then make it // an allOf union of the actual subschema along with a fixed-field // structure. diff --git a/progenitor-impl/tests/output/nexus-builder-tagged.out b/progenitor-impl/tests/output/nexus-builder-tagged.out index 798ebe8..7e7a3d7 100644 --- a/progenitor-impl/tests/output/nexus-builder-tagged.out +++ b/progenitor-impl/tests/output/nexus-builder-tagged.out @@ -2510,7 +2510,20 @@ pub mod types { impl std::str::FromStr for Ipv4Net { type Err = &'static str; fn from_str(value: &str) -> Result { - if regress :: Regex :: new ("^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([8-9]|1[0-9]|2[0-9]|3[0-2])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([8-9]|1[0-9]|2[0-9]|3[0-2])$\"") ; } + if regress::Regex::new( + "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.\ + ){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/\ + ([8-9]|1[0-9]|2[0-9]|3[0-2])$", + ) + .unwrap() + .find(value) + .is_none() + { + return Err("doesn't match pattern \ + \"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.\ + ){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/\ + ([8-9]|1[0-9]|2[0-9]|3[0-2])$\""); + } Ok(Self(value.to_string())) } } @@ -2593,7 +2606,19 @@ pub mod types { impl std::str::FromStr for Ipv6Net { type Err = &'static str; fn from_str(value: &str) -> Result { - if regress :: Regex :: new ("^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\"") ; } + if regress::Regex::new( + "^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,\ + 4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$", + ) + .unwrap() + .find(value) + .is_none() + { + return Err("doesn't match pattern \ + \"^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,\ + 4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/\ + ([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\""); + } Ok(Self(value.to_string())) } } @@ -5241,7 +5266,9 @@ pub mod types { .find(value) .is_none() { - return Err ("doesn't match pattern \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*)\"") ; + return Err("doesn't match pattern \ + \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*\ + )(_([a-z0-9]+))*)\""); } Ok(Self(value.to_string())) } @@ -23979,7 +24006,10 @@ pub mod builder { where V: std::convert::TryInto>, { - self . end_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" . to_string ()) ; + self.end_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" + .to_string() + }); self } @@ -24008,7 +24038,11 @@ pub mod builder { where V: std::convert::TryInto>, { - self . start_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time failed" . to_string ()) ; + self.start_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time \ + failed" + .to_string() + }); self } @@ -34202,7 +34236,10 @@ pub mod builder { where V: std::convert::TryInto>, { - self . end_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" . to_string ()) ; + self.end_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" + .to_string() + }); self } @@ -34241,7 +34278,11 @@ pub mod builder { where V: std::convert::TryInto>, { - self . start_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time failed" . to_string ()) ; + self.start_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time \ + failed" + .to_string() + }); self } diff --git a/progenitor-impl/tests/output/nexus-builder.out b/progenitor-impl/tests/output/nexus-builder.out index 0915ab2..55fac85 100644 --- a/progenitor-impl/tests/output/nexus-builder.out +++ b/progenitor-impl/tests/output/nexus-builder.out @@ -2530,7 +2530,20 @@ pub mod types { impl std::str::FromStr for Ipv4Net { type Err = &'static str; fn from_str(value: &str) -> Result { - if regress :: Regex :: new ("^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([8-9]|1[0-9]|2[0-9]|3[0-2])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([8-9]|1[0-9]|2[0-9]|3[0-2])$\"") ; } + if regress::Regex::new( + "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.\ + ){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/\ + ([8-9]|1[0-9]|2[0-9]|3[0-2])$", + ) + .unwrap() + .find(value) + .is_none() + { + return Err("doesn't match pattern \ + \"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.\ + ){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/\ + ([8-9]|1[0-9]|2[0-9]|3[0-2])$\""); + } Ok(Self(value.to_string())) } } @@ -2613,7 +2626,19 @@ pub mod types { impl std::str::FromStr for Ipv6Net { type Err = &'static str; fn from_str(value: &str) -> Result { - if regress :: Regex :: new ("^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\"") ; } + if regress::Regex::new( + "^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,\ + 4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$", + ) + .unwrap() + .find(value) + .is_none() + { + return Err("doesn't match pattern \ + \"^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,\ + 4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/\ + ([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\""); + } Ok(Self(value.to_string())) } } @@ -5283,7 +5308,9 @@ pub mod types { .find(value) .is_none() { - return Err ("doesn't match pattern \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*)\"") ; + return Err("doesn't match pattern \ + \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*\ + )(_([a-z0-9]+))*)\""); } Ok(Self(value.to_string())) } @@ -23771,7 +23798,10 @@ pub mod builder { where V: std::convert::TryInto>, { - self . end_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" . to_string ()) ; + self.end_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" + .to_string() + }); self } @@ -23800,7 +23830,11 @@ pub mod builder { where V: std::convert::TryInto>, { - self . start_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time failed" . to_string ()) ; + self.start_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time \ + failed" + .to_string() + }); self } @@ -33994,7 +34028,10 @@ pub mod builder { where V: std::convert::TryInto>, { - self . end_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" . to_string ()) ; + self.end_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for end_time failed" + .to_string() + }); self } @@ -34033,7 +34070,11 @@ pub mod builder { where V: std::convert::TryInto>, { - self . start_time = value . try_into () . map (Some) . map_err (| _ | "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time failed" . to_string ()) ; + self.start_time = value.try_into().map(Some).map_err(|_| { + "conversion to `chrono :: DateTime < chrono :: offset :: Utc >` for start_time \ + failed" + .to_string() + }); self } diff --git a/progenitor-impl/tests/output/nexus-positional.out b/progenitor-impl/tests/output/nexus-positional.out index 1ce08ac..43f0f90 100644 --- a/progenitor-impl/tests/output/nexus-positional.out +++ b/progenitor-impl/tests/output/nexus-positional.out @@ -2216,7 +2216,20 @@ pub mod types { impl std::str::FromStr for Ipv4Net { type Err = &'static str; fn from_str(value: &str) -> Result { - if regress :: Regex :: new ("^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([8-9]|1[0-9]|2[0-9]|3[0-2])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/([8-9]|1[0-9]|2[0-9]|3[0-2])$\"") ; } + if regress::Regex::new( + "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.\ + ){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/\ + ([8-9]|1[0-9]|2[0-9]|3[0-2])$", + ) + .unwrap() + .find(value) + .is_none() + { + return Err("doesn't match pattern \ + \"^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.\ + ){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/\ + ([8-9]|1[0-9]|2[0-9]|3[0-2])$\""); + } Ok(Self(value.to_string())) } } @@ -2293,7 +2306,19 @@ pub mod types { impl std::str::FromStr for Ipv6Net { type Err = &'static str; fn from_str(value: &str) -> Result { - if regress :: Regex :: new ("^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$") . unwrap () . find (value) . is_none () { return Err ("doesn't match pattern \"^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\"") ; } + if regress::Regex::new( + "^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,\ + 4}:){1,6}:)\\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$", + ) + .unwrap() + .find(value) + .is_none() + { + return Err("doesn't match pattern \ + \"^([fF][dD])[0-9a-fA-F]{2}:(([0-9a-fA-F]{1,4}:){6}[0-9a-fA-F]{1,\ + 4}|([0-9a-fA-F]{1,4}:){1,6}:)\\/\ + ([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$\""); + } Ok(Self(value.to_string())) } } @@ -4635,7 +4660,9 @@ pub mod types { .find(value) .is_none() { - return Err ("doesn't match pattern \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*)\"") ; + return Err("doesn't match pattern \ + \"(([a-z]+[a-z0-9]*)(_([a-z0-9]+))*):(([a-z]+[a-z0-9]*\ + )(_([a-z0-9]+))*)\""); } Ok(Self(value.to_string())) } diff --git a/progenitor-impl/tests/output/propolis-server-builder-tagged.out b/progenitor-impl/tests/output/propolis-server-builder-tagged.out index 584f83e..64b485d 100644 --- a/progenitor-impl/tests/output/propolis-server-builder-tagged.out +++ b/progenitor-impl/tests/output/propolis-server-builder-tagged.out @@ -964,9 +964,9 @@ pub mod types { name: Err("no value supplied for name".to_string()), read_only: Err("no value supplied for read_only".to_string()), slot: Err("no value supplied for slot".to_string()), - volume_construction_request: Err( - "no value supplied for volume_construction_request".to_string(), - ), + volume_construction_request: Err("no value supplied for \ + volume_construction_request" + .to_string()), } } } diff --git a/progenitor-impl/tests/output/propolis-server-builder.out b/progenitor-impl/tests/output/propolis-server-builder.out index a0d3a2b..17ebb84 100644 --- a/progenitor-impl/tests/output/propolis-server-builder.out +++ b/progenitor-impl/tests/output/propolis-server-builder.out @@ -970,9 +970,9 @@ pub mod types { name: Err("no value supplied for name".to_string()), read_only: Err("no value supplied for read_only".to_string()), slot: Err("no value supplied for slot".to_string()), - volume_construction_request: Err( - "no value supplied for volume_construction_request".to_string(), - ), + volume_construction_request: Err("no value supplied for \ + volume_construction_request" + .to_string()), } } } diff --git a/progenitor-impl/tests/test_output.rs b/progenitor-impl/tests/test_output.rs index abad9f8..a587530 100644 --- a/progenitor-impl/tests/test_output.rs +++ b/progenitor-impl/tests/test_output.rs @@ -6,11 +6,12 @@ use std::{ }; use progenitor_impl::{ - GenerationSettings, Generator, InterfaceStyle, TagStyle, TypeImpl, - TypePatch, + space_out_items, GenerationSettings, Generator, InterfaceStyle, TagStyle, + TypeImpl, TypePatch, }; use openapiv3::OpenAPI; +use proc_macro2::TokenStream; fn load_api

(p: P) -> OpenAPI where @@ -26,6 +27,24 @@ where } } +fn generate_formatted(generator: &mut Generator, spec: &OpenAPI) -> String { + let content = generator.generate_tokens(&spec).unwrap(); + reformat_code(content) +} + +fn reformat_code(content: TokenStream) -> String { + let rustfmt_config = rustfmt_wrapper::config::Config { + format_strings: Some(true), + normalize_doc_attributes: Some(true), + wrap_comments: Some(true), + ..Default::default() + }; + space_out_items( + rustfmt_wrapper::rustfmt_config(rustfmt_config, content).unwrap(), + ) + .unwrap() +} + #[track_caller] fn verify_apis(openapi_file: &str) { let mut in_path = PathBuf::from("../sample_openapi"); @@ -36,7 +55,7 @@ fn verify_apis(openapi_file: &str) { // Positional generation. let mut generator = Generator::default(); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}-positional.out", openapi_stem), &output, @@ -61,7 +80,7 @@ fn verify_apis(openapi_file: &str) { [TypeImpl::Display].into_iter(), ), ); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}-builder.out", openapi_stem), &output, @@ -73,14 +92,16 @@ fn verify_apis(openapi_file: &str) { .with_interface(InterfaceStyle::Builder) .with_tag(TagStyle::Separate), ); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}-builder-tagged.out", openapi_stem), &output, ); // CLI generation. - let output = generator.cli_text(&spec, "sdk").unwrap(); + let tokens = generator.cli(&spec, "sdk").unwrap(); + let output = reformat_code(tokens); + expectorate::assert_contents( format!("tests/output/{}-cli.out", openapi_stem), &output, diff --git a/progenitor-impl/tests/test_specific.rs b/progenitor-impl/tests/test_specific.rs index 5f794dc..4ca5f68 100644 --- a/progenitor-impl/tests/test_specific.rs +++ b/progenitor-impl/tests/test_specific.rs @@ -9,10 +9,25 @@ use dropshot::{ use http::Response; use hyper::Body; use openapiv3::OpenAPI; -use progenitor_impl::{GenerationSettings, Generator, InterfaceStyle}; +use progenitor_impl::{ + space_out_items, GenerationSettings, Generator, InterfaceStyle, +}; use schemars::JsonSchema; use serde::Deserialize; +fn generate_formatted(generator: &mut Generator, spec: &OpenAPI) -> String { + let content = generator.generate_tokens(&spec).unwrap(); + let rustfmt_config = rustfmt_wrapper::config::Config { + normalize_doc_attributes: Some(true), + wrap_comments: Some(true), + ..Default::default() + }; + space_out_items( + rustfmt_wrapper::rustfmt_config(rustfmt_config, content).unwrap(), + ) + .unwrap() +} + #[allow(dead_code)] #[derive(Deserialize, JsonSchema)] struct CursedPath { @@ -65,7 +80,7 @@ fn test_renamed_parameters() { let spec = serde_json::from_str::(out).unwrap(); let mut generator = Generator::default(); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}.out", "test_renamed_parameters"), &output, @@ -98,7 +113,7 @@ fn test_freeform_response() { let spec = serde_json::from_str::(out).unwrap(); let mut generator = Generator::default(); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}.out", "test_freeform_response"), &output, @@ -152,7 +167,7 @@ fn test_default_params() { let spec = serde_json::from_str::(out).unwrap(); let mut generator = Generator::default(); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}.out", "test_default_params_positional"), &output, @@ -161,7 +176,7 @@ fn test_default_params() { let mut generator = Generator::new( GenerationSettings::default().with_interface(InterfaceStyle::Builder), ); - let output = generator.generate_text_normalize_comments(&spec).unwrap(); + let output = generate_formatted(&mut generator, &spec); expectorate::assert_contents( format!("tests/output/{}.out", "test_default_params_builder"), &output, diff --git a/progenitor/Cargo.toml b/progenitor/Cargo.toml index 2b2e84d..d20122c 100644 --- a/progenitor/Cargo.toml +++ b/progenitor/Cargo.toml @@ -16,6 +16,7 @@ progenitor-impl = { version = "0.2.1-dev", path = "../progenitor-impl" } progenitor-macro = { version = "0.2.1-dev", path = "../progenitor-macro" } anyhow = "1.0" openapiv3 = "1.0.0" +rustfmt-wrapper = "0.2.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_yaml = "0.9" diff --git a/progenitor/src/main.rs b/progenitor/src/main.rs index 6e1397c..8871ecf 100644 --- a/progenitor/src/main.rs +++ b/progenitor/src/main.rs @@ -11,6 +11,7 @@ use anyhow::{bail, Result}; use clap::{Parser, ValueEnum}; use openapiv3::OpenAPI; use progenitor::{GenerationSettings, Generator, InterfaceStyle, TagStyle}; +use progenitor_impl::space_out_items; pub mod built_info { // The file has been placed there by the build script. @@ -84,6 +85,16 @@ impl From for TagStyle { } } +fn reformat_code(input: String) -> String { + let config = rustfmt_wrapper::config::Config { + normalize_doc_attributes: Some(true), + wrap_comments: Some(true), + ..Default::default() + }; + space_out_items(rustfmt_wrapper::rustfmt_config(config, input).unwrap()) + .unwrap() +} + fn save

(p: P, data: &str) -> Result<()> where P: AsRef, @@ -179,6 +190,8 @@ fn main() -> Result<()> { } else { api_code }; + let lib_code = reformat_code(lib_code); + let mut librs = src.clone(); librs.push("lib.rs"); save(librs, lib_code.as_str())?;