diff --git a/.github/actions/setup-environment/action.yml b/.github/actions/setup-environment/action.yml new file mode 100644 index 0000000..339e3ae --- /dev/null +++ b/.github/actions/setup-environment/action.yml @@ -0,0 +1,7 @@ +name: "Setup Environment" +description: "Setup Environment" +runs: + using: "composite" + steps: + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - uses: taiki-e/install-action@nextest diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000..7c6e40e --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,36 @@ +name: pre-commit + +on: + pull_request: + branches: + - "main" + push: + branches: + - "main" + +jobs: + pre-commit: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} + + - name: Setup backend + uses: ./.github/actions/setup-environment + + + + - uses: pre-commit/action@v3.0.1 + + - uses: stefanzweifel/git-auto-commit-action@v5 + # Always commit changes even if pre-commit failed + if: always() && github.event_name == 'pull_request' + with: + commit_message: "Automated pre-commit update" + push_options: "--no-verify" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..ae38f29 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,24 @@ +name: Test +on: + pull_request: + branches: + - "main" + push: + branches: + - "main" + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Check out the repo + uses: actions/checkout@v4 + - name: Setup Environment + uses: ./.github/actions/setup-environment + - name: Run tests + run: | + ~/.cargo/bin/cargo-nextest nextest run --workspace + env: + CARGO_TERM_COLOR: always diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 35b2c97..86b40ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,3 @@ -default_language_version: - python: python3.13 repos: diff --git a/Cargo.lock b/Cargo.lock index 5f5e827..76b6ac1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + [[package]] name = "bytes" version = "1.10.0" @@ -187,6 +193,7 @@ dependencies = [ "codegen-sdk-common", "codegen-sdk-cst-generator", "ouroboros", + "tempfile", "tree-sitter", "tree-sitter-python", "tree-sitter-typescript", @@ -296,6 +303,34 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi", + "windows-targets", +] + [[package]] name = "glob" version = "0.3.2" @@ -382,6 +417,12 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "lock_api" version = "0.4.12" @@ -598,7 +639,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -636,6 +677,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.8.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.19" @@ -782,6 +836,20 @@ dependencies = [ "windows", ] +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + [[package]] name = "tree-sitter" version = "0.25.1" @@ -846,6 +914,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "winapi" version = "0.3.9" @@ -994,6 +1071,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + [[package]] name = "yansi" version = "1.0.1" diff --git a/codegen-sdk-ast/src/lib.rs b/codegen-sdk-ast/src/lib.rs index f4aeca7..45f75e1 100644 --- a/codegen-sdk-ast/src/lib.rs +++ b/codegen-sdk-ast/src/lib.rs @@ -1,4 +1 @@ pub use codegen_sdk_cst::*; -fn main() { - println!("Hello, world!"); -} diff --git a/codegen-sdk-common/src/utils.rs b/codegen-sdk-common/src/utils.rs index 5aaef0a..a1c9e92 100644 --- a/codegen-sdk-common/src/utils.rs +++ b/codegen-sdk-common/src/utils.rs @@ -1,9 +1,9 @@ use bytes::{Bytes, BytesMut}; -use tree_sitter::{self, TextProvider}; -pub fn named_children_without_field_names<'a>(node: tree_sitter::Node) -> Vec { +use tree_sitter::{self}; +pub fn named_children_without_field_names(node: tree_sitter::Node) -> Vec { let mut children = Vec::new(); for (index, child) in node.named_children(&mut node.walk()).enumerate() { - if node.field_name_for_named_child(index as u32) == None { + if node.field_name_for_named_child(index as u32).is_none() { children.push(child); } } diff --git a/codegen-sdk-cst-generator/src/generator.rs b/codegen-sdk-cst-generator/src/generator.rs index 1def34e..0b3adec 100644 --- a/codegen-sdk-cst-generator/src/generator.rs +++ b/codegen-sdk-cst-generator/src/generator.rs @@ -1,9 +1,8 @@ -use crate::parser::{Children, Fields, Node, TypeDefinition}; -use convert_case::{Case, Casing}; +use crate::parser::Node; use enum_generator::generate_enum; use naming::normalize_type_name; use state::State; -use std::{collections::HashSet, error::Error, fmt::format}; +use std::{collections::HashSet, error::Error}; use struct_generator::generate_struct; mod enum_generator; mod format; @@ -22,7 +21,7 @@ pub(crate) fn generate_cst(node_types: &Vec) -> Result 0 { + if !node.subtypes.is_empty() { state .variants .insert(normalize_type_name(&node.type_name), node.subtypes.clone()); @@ -38,10 +37,10 @@ pub(crate) fn generate_cst(node_types: &Vec) -> Result 0 { + if !node.subtypes.is_empty() { generate_enum(&node.subtypes, &mut state, &name, true); } else { generate_struct(node, &mut state, &name); diff --git a/codegen-sdk-cst-generator/src/generator/enum_generator.rs b/codegen-sdk-cst-generator/src/generator/enum_generator.rs index 33253fe..bbc5706 100644 --- a/codegen-sdk-cst-generator/src/generator/enum_generator.rs +++ b/codegen-sdk-cst-generator/src/generator/enum_generator.rs @@ -10,12 +10,10 @@ fn get_cases( ) { for t in variants { let normalized_variant_name = normalize_type_name(&t.type_name); - if normalized_variant_name == "" { + if normalized_variant_name.is_empty() { continue; } - let variant_name = override_variant_name - .clone() - .unwrap_or_else(|| &normalized_variant_name); + let variant_name = override_variant_name.unwrap_or_else(|| &normalized_variant_name); let prefix = format!("{}::{}", "Self", variant_name); if let Some(variants) = state.variants.get(&normalized_variant_name) { get_cases(variants, cases, state, Some(variant_name), existing_cases); @@ -42,7 +40,7 @@ pub fn generate_enum( )); for t in variants { let variant_name = normalize_type_name(&t.type_name); - if variant_name == "" { + if variant_name.is_empty() { continue; } state @@ -57,8 +55,8 @@ pub fn generate_enum( let mut existing_cases = Vec::new(); get_cases(variants, &mut cases, state, None, &mut existing_cases); if anonymous_nodes { - for (name, variant_name) in state.anonymous_nodes.iter() { - if name == "" { + for (name, _variant_name) in state.anonymous_nodes.iter() { + if name.is_empty() { continue; } if existing_cases.contains(name) { diff --git a/codegen-sdk-cst-generator/src/generator/format.rs b/codegen-sdk-cst-generator/src/generator/format.rs index 213bcd7..e37da50 100644 --- a/codegen-sdk-cst-generator/src/generator/format.rs +++ b/codegen-sdk-cst-generator/src/generator/format.rs @@ -1,18 +1,10 @@ -use std::{ - fs::File, - io::{BufWriter, Write}, -}; - -use prettyplease; -use syn; - pub fn format_cst(cst: &str) -> String { - let parsed = syn::parse_str::(&cst) + let parsed = syn::parse_str::(cst) .map_err(|e| { println!("{:#?}", e); e }) .unwrap(); - let formatted = prettyplease::unparse(&parsed); - formatted + + prettyplease::unparse(&parsed) } diff --git a/codegen-sdk-cst-generator/src/generator/naming.rs b/codegen-sdk-cst-generator/src/generator/naming.rs index 602048d..c39c4a9 100644 --- a/codegen-sdk-cst-generator/src/generator/naming.rs +++ b/codegen-sdk-cst-generator/src/generator/naming.rs @@ -61,7 +61,7 @@ fn escape_char(c: char) -> String { c.to_string() } pub fn normalize_string(string: &str) -> String { - let escaped = String::from_iter(string.chars().map(|c| escape_char(c))); + let escaped = String::from_iter(string.chars().map(escape_char)); escaped } pub fn normalize_type_name(type_name: &str) -> String { @@ -69,7 +69,7 @@ pub fn normalize_type_name(type_name: &str) -> String { if type_name.chars().any(|c| c.is_ascii_alphabetic()) { cased = cased.to_case(Case::Pascal); } - let escaped = String::from_iter(cased.chars().map(|c| get_char_mapping(c))); + let escaped = String::from_iter(cased.chars().map(get_char_mapping)); debug_assert!( escaped .chars() diff --git a/codegen-sdk-cst-generator/src/generator/struct_generator.rs b/codegen-sdk-cst-generator/src/generator/struct_generator.rs index 52c4d36..0f85fcc 100644 --- a/codegen-sdk-cst-generator/src/generator/struct_generator.rs +++ b/codegen-sdk-cst-generator/src/generator/struct_generator.rs @@ -115,21 +115,20 @@ fn generate_optional_field( fn generate_fields( fields: &Fields, state: &mut State, - node_name: &str, node: &Node, constructor_fields: &mut Vec, ) { for (name, field) in &fields.fields { let field_name = normalize_field_name(name); let converted_type_name = - convert_type_definition(&field.types, state, &node.type_name, &name); + convert_type_definition(&field.types, state, &node.type_name, name); if field.multiple { generate_multiple_field( &field_name, &converted_type_name, state, constructor_fields, - &name, + name, ); } else if field.required { generate_required_field( @@ -137,7 +136,7 @@ fn generate_fields( &converted_type_name, state, constructor_fields, - &name, + name, ); } else { generate_optional_field( @@ -145,7 +144,7 @@ fn generate_fields( &converted_type_name, state, constructor_fields, - &name, + name, ); } } @@ -157,7 +156,7 @@ fn generate_children( constructor_fields: &mut Vec, ) { let converted_type_name = - convert_type_definition(&children.types, state, node_name, &"children"); + convert_type_definition(&children.types, state, node_name, "children"); state.structs.push_str(&format!( " pub children: Vec<{}>,\n", converted_type_name @@ -167,24 +166,18 @@ fn generate_children( pub fn generate_struct(node: &Node, state: &mut State, name: &str) { state .structs - .push_str(&HEADER_TEMPLATE.replace("{name}", &name)); + .push_str(&HEADER_TEMPLATE.replace("{name}", name)); let mut constructor_fields = Vec::new(); if let Some(fields) = &node.fields { - generate_fields( - fields, - state, - &node.type_name, - &node, - &mut constructor_fields, - ); + generate_fields(fields, state, node, &mut constructor_fields); } if let Some(children) = &node.children { generate_children(children, state, &node.type_name, &mut constructor_fields); } - state.structs.push_str(&FOOTER_TEMPLATE); + state.structs.push_str(FOOTER_TEMPLATE); state.structs.push_str( &CONSTRUCTOR_TEMPLATE .replace("{{fields}}", &constructor_fields.join(",\n ")) - .replace("{{name}}", &name), + .replace("{{name}}", name), ); } diff --git a/codegen-sdk-cst-generator/src/parser.rs b/codegen-sdk-cst-generator/src/parser.rs index 7839352..8b86a1d 100644 --- a/codegen-sdk-cst-generator/src/parser.rs +++ b/codegen-sdk-cst-generator/src/parser.rs @@ -45,7 +45,7 @@ pub struct Children { } pub fn parse_node_types(source: &str) -> Result, Box> { - let parsed: Vec = serde_json::from_str(&source)?; + let parsed: Vec = serde_json::from_str(source)?; Ok(parsed) } #[cfg(test)] @@ -56,6 +56,6 @@ mod tests { fn test_parse_node_types() { let source = tree_sitter_python::NODE_TYPES; let cst = parse_node_types(source).unwrap(); - panic!(); + assert!(!cst.is_empty()); } } diff --git a/codegen-sdk-cst/Cargo.toml b/codegen-sdk-cst/Cargo.toml index d69b7cc..7ff96db 100644 --- a/codegen-sdk-cst/Cargo.toml +++ b/codegen-sdk-cst/Cargo.toml @@ -15,3 +15,6 @@ codegen-sdk-cst-generator = { path = "../codegen-sdk-cst-generator" } codegen-sdk-common = { path = "../codegen-sdk-common" } tree-sitter-python = "0.23.6" tree-sitter-typescript = "0.23.2" + +[dev-dependencies] +tempfile = "3.16.0" diff --git a/codegen-sdk-cst/build.rs b/codegen-sdk-cst/build.rs index 4127913..9d2b75b 100644 --- a/codegen-sdk-cst/build.rs +++ b/codegen-sdk-cst/build.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; use codegen_sdk_cst_generator::generate_cst; -use tree_sitter_python; -use tree_sitter_typescript; fn get_node_types() -> HashMap { HashMap::from([ ( diff --git a/codegen-sdk-cst/src/lib.rs b/codegen-sdk-cst/src/lib.rs index d32c9ce..c1dce27 100644 --- a/codegen-sdk-cst/src/lib.rs +++ b/codegen-sdk-cst/src/lib.rs @@ -40,13 +40,15 @@ pub fn parse_file_typescript(file_path: &str) -> Result, Box = parse_file_typescript(&path.to_str().unwrap()).unwrap(); + assert!(module.children.len() > 0); } } diff --git a/src/main.rs b/src/main.rs index ee84f29..3a46a18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,9 +2,8 @@ use clap::Parser; use codegen_sdk_cst::{parse_file_typescript, tsx}; use glob::glob; use rayon::prelude::*; -use std::error::Error; use std::{path, time::Instant}; -use sysinfo::{Pid, Process, System}; +use sysinfo::System; #[derive(Debug, Parser)] struct Args { input: String, @@ -32,12 +31,12 @@ fn main() { return match parse_file_typescript(file.to_str().unwrap()) { Ok(program) => Some(program), Err(e) => { - tx.send(()).unwrap(); + tx.send(e.to_string()).unwrap(); None } }; } - return None; + None }) .collect(); let end = Instant::now();