use std::collections::BTreeSet;
use std::fmt::Write;
use brk_types::TreeNode;
use crate::{
ClientMetadata, GenericSyntax, LanguageSyntax, PatternField, RustSyntax, build_child_path,
escape_rust_keyword, generate_leaf_field, generate_tree_node_field, prepare_tree_node,
to_snake_case,
};
pub fn generate_tree(output: &mut String, catalog: &TreeNode, metadata: &ClientMetadata) {
writeln!(output, "// Series tree\n").unwrap();
let pattern_lookup = metadata.pattern_lookup();
let mut generated = BTreeSet::new();
generate_tree_node(
output,
"SeriesTree",
"",
catalog,
pattern_lookup,
metadata,
&mut generated,
);
}
fn generate_tree_node(
output: &mut String,
name: &str,
path: &str,
node: &TreeNode,
pattern_lookup: &std::collections::BTreeMap<Vec<PatternField>, String>,
metadata: &ClientMetadata,
generated: &mut BTreeSet<String>,
) {
let Some(ctx) = prepare_tree_node(node, name, path, pattern_lookup, metadata, generated) else {
return;
};
writeln!(output, "/// Series tree node.").unwrap();
writeln!(output, "pub struct {} {{", name).unwrap();
for child in &ctx.children {
let field_name = escape_rust_keyword(&to_snake_case(child.name));
let type_annotation = if child.should_inline {
child.inline_type_name.clone()
} else {
metadata.field_type_annotation(&child.field, false, None, GenericSyntax::RUST)
};
writeln!(output, " pub {}: {},", field_name, type_annotation).unwrap();
}
writeln!(output, "}}\n").unwrap();
writeln!(output, "impl {} {{", name).unwrap();
writeln!(
output,
" pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {{"
)
.unwrap();
writeln!(output, " Self {{").unwrap();
let syntax = RustSyntax;
for child in &ctx.children {
let field_name = escape_rust_keyword(&to_snake_case(child.name));
if child.is_leaf {
if let TreeNode::Leaf(leaf) = child.node {
generate_leaf_field(
output,
&syntax,
"client.clone()",
child.name,
leaf,
metadata,
" ",
);
}
} else if child.should_inline {
let path_expr = syntax.path_expr("base_path", &format!("_{}", child.name));
writeln!(
output,
" {}: {}::new(client.clone(), {}),",
field_name, child.inline_type_name, path_expr
)
.unwrap();
} else {
generate_tree_node_field(
output,
&syntax,
&child.field,
metadata,
" ",
"client.clone()",
&child.base_result,
);
}
}
writeln!(output, " }}").unwrap();
writeln!(output, " }}").unwrap();
writeln!(output, "}}\n").unwrap();
for child in &ctx.children {
if child.should_inline {
let child_path = build_child_path(path, child.name);
generate_tree_node(
output,
&child.inline_type_name,
&child_path,
child.node,
pattern_lookup,
metadata,
generated,
);
}
}
}