mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 23:35:07 +00:00
Fix #531: Allow named arguments in expr macro calls
This commit is contained in:
parent
0613a509b6
commit
48d5dba024
@ -485,6 +485,14 @@ impl<'a> Generator<'a, '_> {
|
|||||||
left: &WithSpan<'a, Expr<'a>>,
|
left: &WithSpan<'a, Expr<'a>>,
|
||||||
args: &[WithSpan<'a, Expr<'a>>],
|
args: &[WithSpan<'a, Expr<'a>>],
|
||||||
) -> Result<DisplayWrap, CompileError> {
|
) -> Result<DisplayWrap, CompileError> {
|
||||||
|
// ensure that no named args are used in normal rust call expressions
|
||||||
|
if let Some(arg) = args
|
||||||
|
.iter()
|
||||||
|
.find(|&arg| matches!(**arg, Expr::NamedArgument(_, _)))
|
||||||
|
{
|
||||||
|
return Err(ctx.generate_error("Unsupported use of named arguments", arg.span()));
|
||||||
|
}
|
||||||
|
|
||||||
match &**left {
|
match &**left {
|
||||||
Expr::AssociatedItem(sub_left, AssociatedItem { name, generics })
|
Expr::AssociatedItem(sub_left, AssociatedItem { name, generics })
|
||||||
if ***sub_left == Expr::Var("loop") =>
|
if ***sub_left == Expr::Var("loop") =>
|
||||||
|
@ -251,7 +251,6 @@ impl<'a> Expr<'a> {
|
|||||||
pub(super) fn arguments(
|
pub(super) fn arguments(
|
||||||
i: &mut &'a str,
|
i: &mut &'a str,
|
||||||
level: Level<'_>,
|
level: Level<'_>,
|
||||||
is_template_macro: bool,
|
|
||||||
) -> ParseResult<'a, Vec<WithSpan<'a, Self>>> {
|
) -> ParseResult<'a, Vec<WithSpan<'a, Self>>> {
|
||||||
let _level_guard = level.nest(i)?;
|
let _level_guard = level.nest(i)?;
|
||||||
let mut named_arguments = HashSet::new();
|
let mut named_arguments = HashSet::new();
|
||||||
@ -269,15 +268,7 @@ impl<'a> Expr<'a> {
|
|||||||
let has_named_arguments = !named_arguments.is_empty();
|
let has_named_arguments = !named_arguments.is_empty();
|
||||||
|
|
||||||
let expr = alt((
|
let expr = alt((
|
||||||
move |i: &mut _| {
|
move |i: &mut _| Self::named_argument(i, level, named_arguments, start),
|
||||||
Self::named_argument(
|
|
||||||
i,
|
|
||||||
level,
|
|
||||||
named_arguments,
|
|
||||||
start,
|
|
||||||
is_template_macro,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
move |i: &mut _| Self::parse(i, level, false),
|
move |i: &mut _| Self::parse(i, level, false),
|
||||||
))
|
))
|
||||||
.parse_next(i)?;
|
.parse_next(i)?;
|
||||||
@ -300,14 +291,7 @@ impl<'a> Expr<'a> {
|
|||||||
level: Level<'_>,
|
level: Level<'_>,
|
||||||
named_arguments: &mut HashSet<&'a str>,
|
named_arguments: &mut HashSet<&'a str>,
|
||||||
start: &'a str,
|
start: &'a str,
|
||||||
is_template_macro: bool,
|
|
||||||
) -> ParseResult<'a, WithSpan<'a, Self>> {
|
) -> ParseResult<'a, WithSpan<'a, Self>> {
|
||||||
if !is_template_macro {
|
|
||||||
// If this is not a template macro, we don't want to parse named arguments so
|
|
||||||
// we instead return an error which will allow to continue the parsing.
|
|
||||||
return fail.parse_next(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
let (argument, _, value) = (identifier, ws('='), move |i: &mut _| {
|
let (argument, _, value) = (identifier, ws('='), move |i: &mut _| {
|
||||||
Self::parse(i, level, false)
|
Self::parse(i, level, false)
|
||||||
})
|
})
|
||||||
@ -703,7 +687,7 @@ impl<'a> Filter<'a> {
|
|||||||
pub(crate) fn parse(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Self> {
|
pub(crate) fn parse(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Self> {
|
||||||
let (name, arguments) = (
|
let (name, arguments) = (
|
||||||
ws(|i: &mut _| path_or_identifier(i, level)),
|
ws(|i: &mut _| path_or_identifier(i, level)),
|
||||||
opt(|i: &mut _| Expr::arguments(i, level, true)),
|
opt(|i: &mut _| Expr::arguments(i, level)),
|
||||||
)
|
)
|
||||||
.parse_next(i)?;
|
.parse_next(i)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@ -1126,7 +1110,7 @@ impl<'a> Suffix<'a> {
|
|||||||
|
|
||||||
fn call(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Self> {
|
fn call(i: &mut &'a str, level: Level<'_>) -> ParseResult<'a, Self> {
|
||||||
(opt(|i: &mut _| call_generics(i, level)), |i: &mut _| {
|
(opt(|i: &mut _| call_generics(i, level)), |i: &mut _| {
|
||||||
Expr::arguments(i, level, false)
|
Expr::arguments(i, level)
|
||||||
})
|
})
|
||||||
.map(|(_generics, args)| Self::Call { args })
|
.map(|(_generics, args)| Self::Call { args })
|
||||||
.parse_next(i)
|
.parse_next(i)
|
||||||
|
@ -885,7 +885,7 @@ impl<'a> Call<'a> {
|
|||||||
(
|
(
|
||||||
opt((ws(identifier), ws("::"))),
|
opt((ws(identifier), ws("::"))),
|
||||||
ws(identifier),
|
ws(identifier),
|
||||||
opt(ws(|nested: &mut _| Expr::arguments(nested, s.level, true))),
|
opt(ws(|nested: &mut _| Expr::arguments(nested, s.level))),
|
||||||
opt(Whitespace::parse),
|
opt(Whitespace::parse),
|
||||||
|i: &mut _| s.tag_block_end(i),
|
|i: &mut _| s.tag_block_end(i),
|
||||||
),
|
),
|
||||||
|
@ -89,20 +89,4 @@ struct CallerInCaller1 {
|
|||||||
struct JustCaller{
|
struct JustCaller{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(
|
|
||||||
source = r#"
|
|
||||||
{% macro test() %}
|
|
||||||
{{ caller("a", one = "b") }}
|
|
||||||
{%- endmacro -%}
|
|
||||||
{%- call(two, one) test() -%}
|
|
||||||
{{- two -}} {{- one -}}
|
|
||||||
{%- endcall -%}
|
|
||||||
"#,
|
|
||||||
ext = "txt"
|
|
||||||
)]
|
|
||||||
struct NamedArguments {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
|
@ -80,18 +80,3 @@ error: block is not defined for `caller`
|
|||||||
|
|
|
|
||||||
86 | source = r#"{{caller()}}"#,
|
86 | source = r#"{{caller()}}"#,
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: failed to parse template source
|
|
||||||
--> <source attribute>:3:27
|
|
||||||
"= \"b\") }}\n {%- endmacro -%}\n {%- call(two, one) test() -%}\n {{- two"...
|
|
||||||
--> tests/ui/caller_arguments.rs:94:14
|
|
||||||
|
|
|
||||||
94 | source = r#"
|
|
||||||
| ______________^
|
|
||||||
95 | | {% macro test() %}
|
|
||||||
96 | | {{ caller("a", one = "b") }}
|
|
||||||
97 | | {%- endmacro -%}
|
|
||||||
... |
|
|
||||||
100 | | {%- endcall -%}
|
|
||||||
101 | | "#,
|
|
||||||
| |______^
|
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
error: failed to parse template source
|
error: Unsupported use of named arguments
|
||||||
--> <source attribute>:1:15
|
--> NamedArgsInRustExprMemberFn.html:1:10
|
||||||
"= 5) }}"
|
"(arg = 5) }}"
|
||||||
--> tests/ui/expr_fn_calls.rs:10:21
|
--> tests/ui/expr_fn_calls.rs:10:21
|
||||||
|
|
|
|
||||||
10 | #[template(source = "{{ test_fn(arg = 5) }}", ext = "html")]
|
10 | #[template(source = "{{ test_fn(arg = 5) }}", ext = "html")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: failed to parse template source
|
error: Unsupported use of named arguments
|
||||||
--> <source attribute>:1:23
|
--> NamedArgsInRustExprStaticCall.html:1:18
|
||||||
"= \"test\") }}"
|
"(arg = \"test\") }}"
|
||||||
--> tests/ui/expr_fn_calls.rs:21:21
|
--> tests/ui/expr_fn_calls.rs:21:21
|
||||||
|
|
|
|
||||||
21 | #[template(source = r#"{{ self::static_fn(arg = "test") }}"#, ext = "html")]
|
21 | #[template(source = r#"{{ self::static_fn(arg = "test") }}"#, ext = "html")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: failed to parse template source
|
error: Unsupported use of named arguments
|
||||||
--> <source attribute>:1:39
|
--> NamedArgsInRustExprStaticCall2.html:1:34
|
||||||
"= \"test\") }}"
|
"(arg = \"test\") }}"
|
||||||
--> tests/ui/expr_fn_calls.rs:26:21
|
--> tests/ui/expr_fn_calls.rs:26:21
|
||||||
|
|
|
|
||||||
26 | #[template(source = r#"{{ self::static_fn2("test").unwrap(arg = "test") }}"#, ext = "html")]
|
26 | #[template(source = r#"{{ self::static_fn2("test").unwrap(arg = "test") }}"#, ext = "html")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: failed to parse template source
|
error: Unsupported use of named arguments
|
||||||
--> <source attribute>:1:34
|
--> NamedArgsInRustExprStaticCall3.html:1:29
|
||||||
"= \"test\") %}"
|
"(arg = \"test\") %}"
|
||||||
--> tests/ui/expr_fn_calls.rs:31:21
|
--> tests/ui/expr_fn_calls.rs:31:21
|
||||||
|
|
|
|
||||||
31 | #[template(source = r#"{% let test = self::static_fn(arg = "test") %}"#, ext = "html")]
|
31 | #[template(source = r#"{% let test = self::static_fn(arg = "test") %}"#, ext = "html")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user