#[macro_export]
macro_rules! include_template {
($file:expr) => {{
const CONTENT: &str = include_str!($file);
let template = $crate::TronTemplate::new(CONTENT)
.expect(concat!("Failed to parse template: ", $file));
let validator = $crate::validation::TemplateValidator::new();
let report = validator.validate(&template)
.expect("Template validation failed unexpectedly");
if report.has_errors() {
panic!("Template validation errors: {}", report);
}
template
}};
}
#[macro_export]
macro_rules! template {
($template:literal) => {{
let template = $crate::TronTemplate::new($template)
.expect(concat!("Failed to parse template: ", $template));
let validator = $crate::validation::TemplateValidator::new();
let report = validator.validate(&template)
.expect("Template validation failed unexpectedly");
if report.has_errors() {
panic!("Template validation errors: {}", report);
}
template
}};
}
#[macro_export]
macro_rules! template_ref {
($template:literal, dependencies = [$($dep:literal),* $(,)?]) => {
{
let template = $crate::TronTemplate::new($template)
.expect(concat!("Failed to parse template: ", $template));
let mut template_ref = $crate::TronRef::new(template);
$(
template_ref = template_ref.with_dependency($dep);
)*
template_ref
}
};
($template:literal) => {
{
let template = $crate::TronTemplate::new($template)
.expect(concat!("Failed to parse template: ", $template));
$crate::TronRef::new(template)
}
};
}
#[macro_export]
macro_rules! assemble_templates {
(separator = $sep:literal, $($template:literal),+ $(,)?) => {
{
let mut assembler = $crate::TronAssembler::with_separator($sep);
$(
let template = $crate::TronTemplate::new($template)
.expect(concat!("Failed to parse template: ", $template));
assembler.add_template($crate::TronRef::new(template));
)+
assembler
}
};
($($template:literal),+ $(,)?) => {
{
let mut assembler = $crate::TronAssembler::new();
$(
let template = $crate::TronTemplate::new($template)
.expect(concat!("Failed to parse template: ", $template));
assembler.add_template($crate::TronRef::new(template));
)+
assembler
}
};
}
#[macro_export]
macro_rules! generate_code {
(
template = $template:literal,
placeholders = { $($key:literal => $value:literal),* $(,)? }
) => {
{
let mut content = String::from($template);
$(
content = content.replace(
&format!("@[{}]@", $key),
$value
);
)*
content
}
};
}
#[macro_export]
macro_rules! template_builder {
(
template = $template:literal,
values = { $($key:literal => $value:literal),* $(,)? }
) => {
{
let mut builder = $crate::TronTemplateBuilder::new()
.content($template);
$(
builder = builder.set($key, $value);
)*
builder
}
};
(template = $template:literal) => {
$crate::TronTemplateBuilder::new().content($template)
};
}
#[cfg(test)]
mod tests {
#[test]
fn test_template_macro() {
let template = template!("Hello @[name]@!");
assert_eq!(template.placeholder_names().len(), 1);
assert!(template.has_placeholder("name"));
}
#[test]
fn test_template_ref_macro() {
let template_ref = template_ref!(
"use @[crate_name]@;\nfn @[name]@() { @[body]@ }",
dependencies = ["serde = \"1.0\"", "tokio = \"1.0\""]
);
assert_eq!(template_ref.dependencies().len(), 2);
assert!(template_ref.inner().has_placeholder("name"));
assert!(template_ref.inner().has_placeholder("body"));
assert!(template_ref.inner().has_placeholder("crate_name"));
}
#[test]
fn test_template_ref_macro_no_deps() {
let template_ref = template_ref!("fn @[name]@() {}");
assert_eq!(template_ref.dependencies().len(), 0);
assert!(template_ref.inner().has_placeholder("name"));
}
#[test]
fn test_assemble_templates_macro() {
let assembler = assemble_templates![
"// Header comment",
"fn @[name]@() {}",
"// Footer comment"
];
assert_eq!(assembler.len(), 3);
}
#[test]
fn test_assemble_templates_macro_with_separator() {
let assembler = assemble_templates![
separator = "\n\n",
"mod test {",
" @[content]@",
"}"
];
assert_eq!(assembler.separator(), "\n\n");
assert_eq!(assembler.len(), 3);
}
#[test]
fn test_generate_code_macro() {
let code = generate_code!(
template = "fn @[name]@() -> @[type]@ { @[body]@ }",
placeholders = {
"name" => "test_function",
"type" => "i32",
"body" => "42"
}
);
assert_eq!(code, "fn test_function() -> i32 { 42 }");
}
#[test]
fn test_template_builder_macro() {
let builder = template_builder!(
template = "@[greeting]@ @[name]@!",
values = {
"greeting" => "Hello"
}
);
let template = builder
.set("name", "World")
.build()
.unwrap();
let result = template.render().unwrap();
assert_eq!(result, "Hello World!");
}
#[test]
fn test_template_builder_macro_no_values() {
let builder = template_builder!(template = "Hello @[name]@!");
let template = builder
.set("name", "Macro")
.build()
.unwrap();
assert_eq!(template.render().unwrap(), "Hello Macro!");
}
#[test]
fn test_macro_with_complex_template() {
let template = template!(r#"
#[derive(Debug)]
pub struct @[name]@ {
@[fields]@
}
impl @[name]@ {
pub fn new(@[constructor_params]@) -> Self {
Self {
@[constructor_body]@
}
}
}
"#);
assert!(template.has_placeholder("name"));
assert!(template.has_placeholder("fields"));
assert!(template.has_placeholder("constructor_params"));
assert!(template.has_placeholder("constructor_body"));
}
#[test]
#[should_panic(expected = "Failed to parse template")]
fn test_template_macro_invalid_syntax() {
let _template = template!("Invalid @[bad name]@ template");
}
}