fix: normalize macro args on call #259

This commit is contained in:
chrisp60 2024-11-21 08:58:11 -05:00
parent 35b8433acb
commit 0018b3bf77
2 changed files with 81 additions and 2 deletions

View File

@ -848,8 +848,11 @@ impl<'a> Generator<'a> {
("", "")
};
value.write(this.visit_expr_root(ctx, expr)?);
buf.write(format_args!("let {arg} = {before}{value}{after};"));
this.locals.insert_with_default(Cow::Borrowed(arg));
// We need to normalize the arg to write it, thus we need to add it to
// locals in the normalized manner
let normalized_arg = normalize_identifier(arg);
buf.write(format_args!("let {} = {before}{value}{after};", normalized_arg));
this.locals.insert_with_default(Cow::Borrowed(normalized_arg));
}
}
}

View File

@ -282,3 +282,79 @@ fn test_default_value5() {
assert_eq!(MacroDefaultValue5.render().unwrap(), "3 3\n1 1\n1 2\n");
}
// This test ensures...
// * macro arguments can be named as rust keywords (e.g. "type", "as", "ref", etc.).
// * the keyword is escaped at definition.
// * the keyword is escaped at invocation.
#[test]
fn test_rust_keywords_as_args() {
#[derive(Template)]
#[template(
source = "
{%- macro input(type) -%}
{{ type }}
{% endmacro -%}
{%- call input(1) -%}
{%- call input(type=1) -%}
",
ext = "html"
)]
struct MacroRustKwArgs;
// primarily checking for compilation
assert_eq!(MacroRustKwArgs.render().unwrap(), "1\n1\n");
}
// This test ensures...
// * macro arguments can be named as rust keywords (e.g. "type", "as", "ref", etc.).
// * the argument has a default value.
// * the keyword is escaped at definition.
// * the keyword is escaped at invocation.
#[test]
fn test_rust_keywords_as_args_with_default() {
#[derive(Template)]
#[template(
source = "
{%- macro input(type=1) -%}
{{ type }}
{% endmacro -%}
{%- call input() -%}
{%- call input(1) -%}
{%- call input(type=1) -%}
",
ext = "html"
)]
struct MacroRustKwArgsDefault;
// primarily checking for compilation
assert_eq!(MacroRustKwArgsDefault.render().unwrap(), "1\n1\n1\n");
}
// This test ensures...
// * macro arguments can be named as rust keywords (e.g. "type", "as", "ref", etc.).
// * a non-literal expression is given as default
// * the keyword is escaped at definition.
// * the keyword is escaped at invocation.
#[test]
fn test_rust_keywords_as_args_with_default_expr() {
#[derive(Template)]
#[template(
source = "
{%- macro input(type=1+2) -%}
{{ type }}
{% endmacro -%}
{%- call input() -%}
{%- call input(1) -%}
{%- call input(type=1) -%}
",
ext = "html"
)]
struct MacroRustKwArgsDefaultExpr;
// primarily checking for compilation
assert_eq!(MacroRustKwArgsDefaultExpr.render().unwrap(), "3\n1\n1\n");
}