Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "codegen-sdk-core"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
clap = { version = "4.5.28", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion codegen-sdk-analyzer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "codegen-sdk-analyzer"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
salsa = "0.16.1"
Expand Down
2 changes: 1 addition & 1 deletion codegen-sdk-ast/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "codegen-sdk-ast"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
codegen-sdk-cst = { path = "../codegen-sdk-cst" }
Expand Down
4 changes: 3 additions & 1 deletion codegen-sdk-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "codegen-sdk-common"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
bytes = { workspace = true }
Expand All @@ -27,6 +27,8 @@ base64 = "0.22.1"
buildid = "1.0.3"
sha2 = "0.10.8"
zstd = { version = "0.13.2", features = ["zstdmt"] }
syn = "2.0.98"
quote = "1.0.38"
[features]
python = ["dep:tree-sitter-python"]
json = ["dep:tree-sitter-json"]
Expand Down
8 changes: 5 additions & 3 deletions codegen-sdk-cst-generator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
[package]
name = "codegen-sdk-cst-generator"
version = "0.1.0"
edition = "2021"
edition = "2024"

[dependencies]
convert_case = { workspace = true }
prettyplease = "0.2.29"
syn = "2.0.98"
syn = { version = "2.0.98", features = ["proc-macro"] }
tree-sitter = { workspace = true }
log = { workspace = true }
codegen-sdk-common = { path = "../codegen-sdk-common" }
anyhow = { workspace = true }

quote = "1.0.38"
proc-macro2 = "1.0.93"
tempfile = "3.8.1"
[dev-dependencies]
codegen-sdk-common = { path = "../codegen-sdk-common" , features = ["python"] }
43 changes: 28 additions & 15 deletions codegen-sdk-cst-generator/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,23 @@ mod enum_generator;
mod format;
mod state;
mod struct_generator;
const IMPORTS: &str = "
use std::sync::Arc;
use tree_sitter;
use derive_more::Debug;
use codegen_sdk_common::*;
use std::backtrace::Backtrace;
use bytes::Bytes;
use rkyv::{Archive, Deserialize, Serialize, Portable};
";
use std::io::Write;

use proc_macro2::TokenStream;
use quote::quote;
fn get_imports() -> TokenStream {
quote! {

use std::sync::Arc;
use tree_sitter;
use derive_more::Debug;
use codegen_sdk_common::*;
use std::backtrace::Backtrace;
use bytes::Bytes;
use rkyv::{Archive, Deserialize, Serialize, Portable};

}
}
pub(crate) fn generate_cst(node_types: &Vec<Node>) -> anyhow::Result<String> {
let mut state = State::default();
let mut nodes = HashSet::new();
Expand Down Expand Up @@ -47,15 +54,21 @@ pub(crate) fn generate_cst(node_types: &Vec<Node>) -> anyhow::Result<String> {
generate_struct(node, &mut state, &name);
}
}
let mut result = IMPORTS.to_string();
result.push_str(&state.enums);
result.push_str(&state.structs);
let formatted = format::format_cst(&result);
let mut result = get_imports();
result.extend_one(state.enums);
result.extend_one(state.structs);
let formatted = format::format_cst(&result.to_string());
match formatted {
Ok(formatted) => return Ok(formatted),
Err(e) => {
log::error!("Failed to format CST: {}", e);
return Ok(result.to_string());
let mut out_file = tempfile::NamedTempFile::with_suffix(".rs")?;
log::error!(
"Failed to format CST, writing to temp file at {}",
out_file.path().display()
);
out_file.write_all(result.to_string().as_bytes())?;
out_file.keep()?;
return Err(e);
}
}
}
Expand Down
93 changes: 53 additions & 40 deletions codegen-sdk-cst-generator/src/generator/enum_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,76 @@ use codegen_sdk_common::{
naming::{normalize_string, normalize_type_name},
parser::TypeDefinition,
};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};

use crate::generator::state::State;
fn get_cases(
variants: &Vec<TypeDefinition>,
cases: &mut String,
state: &State,
override_variant_name: Option<&str>,
existing_cases: &mut Vec<String>,
) {
) -> Vec<(String, TokenStream)> {
let mut cases = Vec::new();
for t in variants {
let normalized_variant_name = normalize_type_name(&t.type_name);
if normalized_variant_name.is_empty() {
continue;
}
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);
cases.extend(get_cases(
variants,
state,
Some(variant_name),
existing_cases,
));
} else if !existing_cases.contains(&t.type_name) {
existing_cases.push(t.type_name.clone());
cases.push_str(&format!(
"\"{}\" => Ok({}({variant_name}::from_node(node, buffer)?)),",
t.type_name, prefix,
let variant_name = format_ident!("{}", variant_name);
cases.push((
t.type_name.clone(),
quote! { Self::#variant_name (#variant_name::from_node(node, buffer)?)},
));
// cases.insert(t.type_name.clone(), quote!{
// #t.type_name => Ok(#(#prefix)::from_node(node, buffer)?),
// }.to_string());
}
}
return cases;
}
pub fn generate_enum(
variants: &Vec<TypeDefinition>,
state: &mut State,
enum_name: &str,
anonymous_nodes: bool,
) {
state.enums.push_str(&format!(
"
#[derive(Debug, Clone, Archive, Portable, Deserialize, Serialize)]
#[repr(C, u8)]
pub enum {enum_name} {{\n",
enum_name = enum_name
));
let mut variant_tokens = Vec::new();
for t in variants {
let variant_name = normalize_type_name(&t.type_name);
if variant_name.is_empty() {
continue;
}
state
.enums
.push_str(&format!(" {}({variant_name}),\n", variant_name));
let variant_name = format_ident!("{}", variant_name);
variant_tokens.push(quote! {
#variant_name(#variant_name)
});
}
if anonymous_nodes {
state.enums.push_str(" Anonymous,\n");
variant_tokens.push(quote! {
Anonymous,
});
}
state.enums.push_str("}\n");
let mut cases = String::new();
let enum_name = format_ident!("{}", enum_name);
state.enums.extend_one(quote! {
#[derive(Debug, Clone, Archive, Portable, Deserialize, Serialize)]
#[repr(C, u8)]
pub enum #enum_name {
#(#variant_tokens),*
}
});
let mut existing_cases = Vec::new();
get_cases(variants, &mut cases, state, None, &mut existing_cases);
let mut cases = get_cases(variants, state, None, &mut existing_cases);
if anonymous_nodes {
for (name, _variant_name) in state.anonymous_nodes.iter() {
if name.is_empty() {
Expand All @@ -67,27 +81,26 @@ pub fn generate_enum(
continue;
}
let normalized_name = normalize_string(name);
cases.push_str(&format!(
"\"{}\" => Ok(Self::Anonymous),\n",
normalized_name
));
cases.push((normalized_name, quote! {Self::Anonymous}));
}
}
state.enums.push_str(&format!(
"
impl FromNode for {enum_name} {{
fn from_node(node: tree_sitter::Node, buffer: &Arc<Bytes>) -> Result<Self, ParseError> {{
match node.kind() {{
{cases}
_ => Err(ParseError::UnexpectedNode {{
let mut keys = Vec::new();
let mut values = Vec::new();
for (key, value) in cases {
keys.push(key);
values.push(value);
}
state.enums.extend_one(quote! {
impl FromNode for #enum_name {
fn from_node(node: tree_sitter::Node, buffer: &Arc<Bytes>) -> Result<Self, ParseError> {
match node.kind() {
#(#keys => Ok(#values)),*,
_ => Err(ParseError::UnexpectedNode {
node_type: node.kind().to_string(),
backtrace: Backtrace::capture(),
}}),
}}
}}
}}
",
enum_name = enum_name,
cases = cases
));
}),
}
}
}
});
}
6 changes: 3 additions & 3 deletions codegen-sdk-cst-generator/src/generator/state.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::collections::HashMap;

use codegen_sdk_common::parser::TypeDefinition;

use proc_macro2::TokenStream;
#[derive(Default, Debug)]
pub struct State {
pub enums: String,
pub structs: String,
pub enums: TokenStream,
pub structs: TokenStream,
pub variants: HashMap<String, Vec<TypeDefinition>>,
pub anonymous_nodes: HashMap<String, String>,
}
Loading