diff --git a/askama_derive/src/generator/node.rs b/askama_derive/src/generator/node.rs index 84121f7d..2bb77f4f 100644 --- a/askama_derive/src/generator/node.rs +++ b/askama_derive/src/generator/node.rs @@ -943,8 +943,12 @@ impl<'a> Generator<'a, '_> { ctx: &Context<'a>, buf: &mut Buffer, ws: Ws, - expr: &'a WithSpan<'a, Expr<'a>>, + mut expr: &'a WithSpan<'a, Expr<'a>>, ) -> Result { + while let Expr::Group(inner) = &**expr { + expr = inner; + } + if let Expr::Call(call) = &**expr && let ControlFlow::Break(size_hint) = self.write_expr_call(ctx, buf, ws, expr.span(), call)? @@ -953,19 +957,26 @@ impl<'a> Generator<'a, '_> { } self.handle_ws(ws); - let items = if let Expr::Concat(exprs) = &**expr { - exprs - } else { - std::slice::from_ref(expr) - }; - - for s in items { - self.buf_writable - .push(compile_time_escape(s, self.input.escaper).unwrap_or(Writable::Expr(s))); - } + self.write_expr_item(expr); Ok(0) } + fn write_expr_item(&mut self, expr: &'a WithSpan<'a, Expr<'a>>) { + match &**expr { + Expr::Group(expr) => self.write_expr_item(expr), + Expr::Concat(items) => { + for expr in items { + self.write_expr_item(expr); + } + } + _ => { + self.buf_writable.push( + compile_time_escape(expr, self.input.escaper).unwrap_or(Writable::Expr(expr)), + ); + } + } + } + fn write_expr_call( &mut self, ctx: &Context<'a>, diff --git a/askama_derive/src/tests.rs b/askama_derive/src/tests.rs index b57eb211..7ea9f8fe 100644 --- a/askama_derive/src/tests.rs +++ b/askama_derive/src/tests.rs @@ -1410,3 +1410,34 @@ fn test_bare_cr_doc_comment() -> Result<(), syn::Error> { Ok(()) } + +#[test] +fn check_expr_ungrouping() { + // In this test we ensure that superfluous parentheses around expressions are stripped before + // handling the expression. + + compare( + r#"{{ ("hello") }}"#, + r#"__askama_writer.write_str("hello")?;"#, + &[], + 5, + ); + compare( + r#"{{ ("hello") ~ " " ~ ("world") }}"#, + r#"__askama_writer.write_str("hello world")?;"#, + &[], + 11, + ); + compare( + r#"{{ ("hello") ~ (" " ~ ("world")) }}"#, + r#"__askama_writer.write_str("hello world")?;"#, + &[], + 11, + ); + compare( + r#"{{ ((((((((((("hello") ~ " ")))) ~ ((("world"))))))))) }}"#, + r#"__askama_writer.write_str("hello world")?;"#, + &[], + 11, + ); +}