From d2a55738b71d184ac4d7fc9511c85358697d03dd Mon Sep 17 00:00:00 2001 From: Kurt Wolf Date: Mon, 16 Sep 2024 18:51:44 -0700 Subject: [PATCH] wip --- Cargo.lock | 65 +++---------------- Justfile | 6 +- codegen_rust/Cargo.toml | 4 +- codegen_rust/src/client.rs | 12 ++-- codegen_rust/src/lib.rs | 37 ++++++----- codegen_rust/src/request.rs | 122 ++++++++++++++++++------------------ libninja/Cargo.toml | 1 - 7 files changed, 104 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99c88f8..03eb94e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -601,6 +601,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kurtbuilds_std_ext" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0846203963f5253bf1387ca62651e2a0daa0126b7da9b5f9e91e3bb780f24079" + [[package]] name = "lazy_static" version = "1.4.0" @@ -654,7 +660,6 @@ dependencies = [ "tera", "text_io", "tokio", - "toml", "topo_sort", "tracing", "tracing-ez", @@ -668,6 +673,7 @@ version = "0.1.0" dependencies = [ "anyhow", "convert_case", + "kurtbuilds_std_ext", "libninja_hir", "libninja_macro", "libninja_mir", @@ -675,6 +681,7 @@ dependencies = [ "proc-macro2", "quote", "regex", + "walkdir", ] [[package]] @@ -1151,15 +1158,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" -dependencies = [ - "serde", -] - [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -1373,40 +1371,6 @@ dependencies = [ "syn", ] -[[package]] -name = "toml" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - [[package]] name = "topo_sort" version = "0.4.0" @@ -1606,9 +1570,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1846,15 +1810,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" -[[package]] -name = "winnow" -version = "0.5.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" -dependencies = [ - "memchr", -] - [[package]] name = "yansi" version = "1.0.1" diff --git a/Justfile b/Justfile index ee63e1f..1319d37 100644 --- a/Justfile +++ b/Justfile @@ -21,7 +21,6 @@ example EXAMPLE: alias e := example install: - just clean release cargo install --path libninja --force check: @@ -55,10 +54,7 @@ patch: test just version patch just publish -clean MODE='debug': - checkexec ${CARGO_TARGET_DIR:-target}/{{MODE}}/libninja $(fd . -H core/template) -- cargo clean --package libninja - -rust: clean +rust: cargo run -- gen --name PetStore --output-dir gen/rust --generator rust data/openapi-spec/petstore/petstore.yaml --github libninjacom/petstore-rs --version 0.1.0 generate: diff --git a/codegen_rust/Cargo.toml b/codegen_rust/Cargo.toml index c733bb7..f1c0f08 100644 --- a/codegen_rust/Cargo.toml +++ b/codegen_rust/Cargo.toml @@ -16,4 +16,6 @@ anyhow = "1.0.89" quote = "1.0.35" proc-macro2 = "1.0.86" convert_case = "0.6.0" -regex = "1.10.6" \ No newline at end of file +regex = "1.10.6" +walkdir = "2.5.0" +kurtbuilds_std_ext = "0.1.1" \ No newline at end of file diff --git a/codegen_rust/src/client.rs b/codegen_rust/src/client.rs index 55fafd2..07f7ece 100644 --- a/codegen_rust/src/client.rs +++ b/codegen_rust/src/client.rs @@ -18,8 +18,6 @@ pub fn make_lib_rs(spec: &HirSpec, extras: &Extras, cfg: &Config) -> File File Class { fields: instance_fields, methods, vis: Visibility::Public, - imports: vec![import!(httpclient, Client)], + imports: vec![], ..Class::default() } } diff --git a/codegen_rust/src/lib.rs b/codegen_rust/src/lib.rs index 81e4e32..2405173 100644 --- a/codegen_rust/src/lib.rs +++ b/codegen_rust/src/lib.rs @@ -21,6 +21,7 @@ use std::{ fs, path::{Path, PathBuf}, }; +use std_ext::PathExt; pub type Modified = HashSet; @@ -49,22 +50,30 @@ pub fn generate_rust_library(spec: HirSpec, cfg: Config) -> Result<()> { } fn remove_old_files(dest: &Path, modified: &HashSet) -> Result<()> { - let mut to_delete: Vec<_> = fs::read_dir(dest.join("examples")) + for f in walkdir::WalkDir::new(dest.join("src")) { + let f = f.unwrap(); + let f = f.into_path(); + if f.as_os_str() == "./src/request.rs" { + dbg!(f.ext_str()); + } + } + let to_delete = walkdir::WalkDir::new(dest.join("src")) .into_iter() - .flatten() - .chain(fs::read_dir(dest.join("src")).into_iter().flatten()) - .flat_map(|e| e.ok()) - .map(|e| e.path()) - .filter(|e| e.ends_with(".rs")) - .filter(|e| { - fs::read_to_string(&e) - .map(|content| !content.contains("libninja: static")) + .chain(walkdir::WalkDir::new(dest.join("examples")).into_iter()) + .filter_map(|e| e.ok()) + .map(|e| e.into_path()) + .filter(|p| p.ext_str() == "rs") + .filter(|e| !modified.contains(e)) + .filter(|p| { + !fs::read_to_string(&p) + .map(|content| content.contains("libninja: static")) .unwrap_or(false) - }) - .collect(); - to_delete.retain(|f| !modified.contains(f)); - for file in to_delete { - fs::remove_file(file)?; + }); + let to_delete = to_delete.collect::>(); + dbg!(&to_delete); + for e in to_delete { + fs::remove_file(&e)?; + eprintln!("{}: Remove unused file.", e.display()); } Ok(()) } diff --git a/codegen_rust/src/request.rs b/codegen_rust/src/request.rs index 778c88d..b24e020 100644 --- a/codegen_rust/src/request.rs +++ b/codegen_rust/src/request.rs @@ -19,31 +19,33 @@ pub fn write_request_module(spec: &HirSpec, cfg: &Config, m: &mut Modified) -> R let src = cfg.src(); let imports = vec![]; fs::create_dir_all(src.join("request"))?; - let modules: Vec = vec![]; + let mut modules: Vec<(Ident, Ident)> = vec![]; for operation in &spec.operations { + modules.push((Ident(operation.file_name()), Ident(operation.request_struct_name()))); let file = make_single_module(operation, &spec, cfg); let fname = operation.file_name(); let path = src.join("request").join(&fname).with_extension("rs"); - write_rust(&path, file.to_rust_code(), m)?; + write_rust(&path, file, m)?; } let items = modules .into_iter() - .map(|m| Item::Block(quote!(pub mod #m;))) + .map(|(m, s)| { + Item::Block(quote! { + pub mod #m; + pub use #m::#s; + }) + }) .collect(); let file = File { imports, items, ..File::default() }; - write_rust(&src.join("request.rs"), file.to_rust_code(), m) + write_rust(&src.join("request").join("mod.rs"), file, m) } -pub fn make_single_module( - operation: &Operation, - spec: &HirSpec, - cfg: &Config, -) -> File { +pub fn make_single_module(operation: &Operation, spec: &HirSpec, cfg: &Config) -> File { let client_name = cfg.client_name(); let authenticate = spec .has_security() @@ -97,10 +99,7 @@ pub fn make_single_module( } } }; - let mut items: Vec> = request_structs - .into_iter() - .map(|s| Item::Class(s)) - .collect(); + let mut items: Vec> = request_structs.into_iter().map(|s| Item::Class(s)).collect(); items.push(Item::Block(impl_block)); File { attributes: vec![], @@ -139,8 +138,7 @@ pub fn assign_inputs_to_request(inputs: &[Parameter]) -> TokenStream { let mut assign = { let param_key = input.to_key().to_rust_code(); - let value_identifier = if input.ty.is_iterable() && input.location != Location::Body - { + let value_identifier = if input.ty.is_iterable() && input.location != Location::Body { quote! { item } } else if input.optional { quote! { unwrapped } @@ -245,53 +243,57 @@ pub fn make_struct_fields(inputs: &[Parameter], use_references: bool) -> Vec Vec> { - operation.parameters.iter().filter(|a| a.optional).map(|a| { - let name = a.name.to_rust_ident(); - let mut arg_type = a.ty.to_reference_type(TokenStream::new()); + operation + .parameters + .iter() + .filter(|a| a.optional) + .map(|a| { + let name = a.name.to_rust_ident(); + let mut arg_type = a.ty.to_reference_type(TokenStream::new()); - let mut body = if a.ty.is_reference_type() { - quote! { - self.params.#name = Some(#name.to_owned()); - self + let mut body = if a.ty.is_reference_type() { + quote! { + self.params.#name = Some(#name.to_owned()); + self + } + } else { + quote! { + self.params.#name = Some(#name); + self + } + }; + if let Some(Ty::String) = a.ty.inner_iterable() { + arg_type = quote!(impl IntoIterator>); + body = quote! { + self.params.#name = Some(#name.into_iter().map(|s| s.as_ref().to_owned()).collect()); + self + }; } - } else { - quote! { - self.params.#name = Some(#name); - self + let name: Ident = a.name.to_rust_ident(); + Function { + doc: Some(Doc(format!("Set the value of the {} field.", name.0))), + name, + args: vec![ + Arg::SelfArg { + mutable: true, + reference: false, + }, + Arg::Basic { + name: a.name.to_rust_ident(), + ty: arg_type, + default: None, + }, + ], + ret: quote! {Self}, + body, + vis: Visibility::Public, + ..Function::default() } - }; - if let Some(Ty::String) = a.ty.inner_iterable() { - arg_type = quote!( impl IntoIterator> ); - body = quote! { - self.params.#name = Some(#name.into_iter().map(|s| s.as_ref().to_owned()).collect()); - self - }; - } - let name: Ident = a.name.to_rust_ident(); - Function { - doc: Some(Doc(format!("Set the value of the {} field.", name.0))), - name, - args: vec![ - Arg::SelfArg { mutable: true, reference: false }, - Arg::Basic { - name: a.name.to_rust_ident(), - ty: arg_type, - default: None, - }, - ], - ret: quote! {Self}, - body, - vis: Visibility::Public, - ..Function::default() - } - }).collect() + }) + .collect() } -pub fn build_request_struct( - operation: &Operation, - _spec: &HirSpec, - opt: &Config, -) -> Vec> { +pub fn build_request_struct(operation: &Operation, _spec: &HirSpec, opt: &Config) -> Vec> { let instance_fields = make_struct_fields(&operation.parameters, false); let fn_name = operation.name.to_rust_ident().0; @@ -315,11 +317,7 @@ On request success, this will return a [`{response}`]."#, }]; if operation.use_required_struct(Language::Rust) { - let lifetimes = if operation - .parameters - .iter() - .any(|param| param.ty.is_reference_type()) - { + let lifetimes = if operation.parameters.iter().any(|param| param.ty.is_reference_type()) { vec!["'a".to_string()] } else { vec![] diff --git a/libninja/Cargo.toml b/libninja/Cargo.toml index a909d58..af5b244 100644 --- a/libninja/Cargo.toml +++ b/libninja/Cargo.toml @@ -27,7 +27,6 @@ tera = "1.19.0" include_dir = "0.7.3" regex = "1.9.0" indoc = "2.0.2" -toml = "0.8.8" topo_sort = "0.4.0" url = "2.4.0" http = "1.0.0"