From 49d4397f515be91d451ed40637464f6e75bb7967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Mon, 23 Jun 2025 18:11:28 +0200 Subject: [PATCH] parser: introduce `askama_parser::expr::Range` --- askama_derive/src/generator/expr.rs | 4 ++-- askama_derive/src/generator/node.rs | 7 +++--- askama_parser/src/expr.rs | 36 ++++++++++++++++++++--------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/askama_derive/src/generator/expr.rs b/askama_derive/src/generator/expr.rs index ef453267..ceff24c2 100644 --- a/askama_derive/src/generator/expr.rs +++ b/askama_derive/src/generator/expr.rs @@ -76,8 +76,8 @@ impl<'a> Generator<'a, '_> { }) => self.visit_filter(ctx, buf, name, arguments, generics, expr.span())?, Expr::Unary(op, ref inner) => self.visit_unary(ctx, buf, op, inner)?, Expr::BinOp(ref v) => self.visit_binop(ctx, buf, v.op, &v.lhs, &v.rhs)?, - Expr::Range(op, ref left, ref right) => { - self.visit_range(ctx, buf, op, left.as_deref(), right.as_deref())? + Expr::Range(ref v) => { + self.visit_range(ctx, buf, v.op, v.lhs.as_ref(), v.rhs.as_ref())? } Expr::Group(ref inner) => self.visit_group(ctx, buf, inner)?, Expr::Call { diff --git a/askama_derive/src/generator/node.rs b/askama_derive/src/generator/node.rs index 3905f181..31c40975 100644 --- a/askama_derive/src/generator/node.rs +++ b/askama_derive/src/generator/node.rs @@ -199,7 +199,7 @@ impl<'a> Generator<'a, '_> { | Expr::Attr(_, _) | Expr::Index(_, _) | Expr::Filter(_) - | Expr::Range(_, _, _) + | Expr::Range(_) | Expr::Call { .. } | Expr::RustMacro(_, _) | Expr::Try(_) @@ -1649,9 +1649,8 @@ fn is_cacheable(expr: &WithSpan<'_, Expr<'_>>) -> bool { Expr::Unary(_, arg) => is_cacheable(arg), Expr::BinOp(v) => is_cacheable(&v.lhs) && is_cacheable(&v.rhs), Expr::IsDefined(_) | Expr::IsNotDefined(_) => true, - Expr::Range(_, lhs, rhs) => { - lhs.as_ref().is_none_or(|v| is_cacheable(v)) - && rhs.as_ref().is_none_or(|v| is_cacheable(v)) + Expr::Range(v) => { + v.lhs.as_ref().is_none_or(is_cacheable) && v.rhs.as_ref().is_none_or(is_cacheable) } Expr::Group(arg) => is_cacheable(arg), Expr::Tuple(args) => args.iter().all(is_cacheable), diff --git a/askama_parser/src/expr.rs b/askama_parser/src/expr.rs index c42dfd67..05880b2b 100644 --- a/askama_parser/src/expr.rs +++ b/askama_parser/src/expr.rs @@ -101,11 +101,11 @@ fn check_expr<'a>(expr: &WithSpan<'a, Expr<'a>>, allowed: Allowed) -> Result<(), check_expr(&v.lhs, Allowed::default())?; check_expr(&v.rhs, Allowed::default()) } - Expr::Range(_, elem1, elem2) => { - if let Some(elem1) = elem1 { + Expr::Range(v) => { + if let Some(elem1) = v.lhs.as_ref() { check_expr(elem1, Allowed::default())?; } - if let Some(elem2) = elem2 { + if let Some(elem2) = v.rhs.as_ref() { check_expr(elem2, Allowed::default())?; } Ok(()) @@ -170,11 +170,7 @@ pub enum Expr<'a> { NamedArgument(&'a str, Box>>), Unary(&'a str, Box>>), BinOp(Box>), - Range( - &'a str, - Option>>>, - Option>>>, - ), + Range(Box>), Group(Box>>), Tuple(Vec>>), Call { @@ -196,6 +192,13 @@ pub enum Expr<'a> { ArgumentPlaceholder, } +#[derive(Clone, Debug, PartialEq)] +pub struct Range<'a> { + pub op: &'a str, + pub lhs: Option>>, + pub rhs: Option>>, +} + #[derive(Clone, Debug, PartialEq)] pub struct BinOp<'a> { pub op: &'a str, @@ -300,12 +303,23 @@ impl<'a> Expr<'a> { }; let expr = alt(( range_right.map(move |(op, right)| { - WithSpan::new(Self::Range(op, None, right.map(Box::new)), start) + WithSpan::new( + Self::Range(Box::new(Range { + op, + lhs: None, + rhs: right, + })), + start, + ) }), (move |i: &mut _| Self::or(i, level), opt(range_right)).map(move |(left, right)| { match right { Some((op, right)) => WithSpan::new( - Self::Range(op, Some(Box::new(left)), right.map(Box::new)), + Self::Range(Box::new(Range { + op, + lhs: Some(left), + rhs: right, + })), start, ), None => left, @@ -611,7 +625,7 @@ impl<'a> Expr<'a> { | Self::RustMacro(_, _) | Self::As(_, _) | Self::Call { .. } - | Self::Range(_, _, _) + | Self::Range(_) | Self::Try(_) | Self::NamedArgument(_, _) | Self::Filter(_)