From 9ee2afecfadbc36ec0e8cf7b69d779b753c82fc4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 May 2025 15:46:44 +0200 Subject: [PATCH] Add support for mutable variables --- askama_derive/src/generator/node.rs | 6 ++++++ askama_parser/src/node.rs | 11 ++++++++++- testing/tests/ui/assign-to-askama.rs | 2 +- testing/tests/ui/assign-to-askama.stderr | 6 +++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/askama_derive/src/generator/node.rs b/askama_derive/src/generator/node.rs index 760409d8..a4ccbd12 100644 --- a/askama_derive/src/generator/node.rs +++ b/askama_derive/src/generator/node.rs @@ -961,6 +961,9 @@ impl<'a> Generator<'a, '_> { let Some(val) = &l.val else { self.write_buf_writable(ctx, buf)?; buf.write("let "); + if l.is_mutable { + buf.write("mut "); + } self.visit_target(buf, false, true, &l.var); buf.write(';'); return Ok(()); @@ -980,6 +983,9 @@ impl<'a> Generator<'a, '_> { || matches!(&l.var, Target::Name(name) if self.locals.get(name).is_none()) { buf.write("let "); + if l.is_mutable { + buf.write("mut "); + } } self.visit_target(buf, true, true, &l.var); diff --git a/askama_parser/src/node.rs b/askama_parser/src/node.rs index c006dc3e..d6352fbd 100644 --- a/askama_parser/src/node.rs +++ b/askama_parser/src/node.rs @@ -1204,6 +1204,7 @@ pub struct Let<'a> { pub ws: Ws, pub var: Target<'a>, pub val: Option>>, + pub is_mutable: bool, } impl<'a> Let<'a> { @@ -1212,6 +1213,7 @@ impl<'a> Let<'a> { let mut p = ( opt(Whitespace::parse), ws(alt((keyword("let"), keyword("set")))), + ws(opt(keyword("mut"))), cut_node( Some("let"), ( @@ -1224,7 +1226,7 @@ impl<'a> Let<'a> { ), ), ); - let (pws, _, (var, val, nws)) = p.parse_next(i)?; + let (pws, _, is_mut, (var, val, nws)) = p.parse_next(i)?; if val.is_none() { let kind = match &var { Target::Name(_) => None, @@ -1250,12 +1252,19 @@ impl<'a> Let<'a> { ))); } } + if is_mut.is_some() && !matches!(var, Target::Name(_)) { + return Err(winnow::error::ErrMode::Cut(ErrorContext::new( + "you can only use the `mut` keyword with a variable name", + start, + ))); + } Ok(WithSpan::new( Let { ws: Ws(pws, nws), var, val, + is_mutable: is_mut.is_some(), }, start, )) diff --git a/testing/tests/ui/assign-to-askama.rs b/testing/tests/ui/assign-to-askama.rs index f1b5e4ee..5842a150 100644 --- a/testing/tests/ui/assign-to-askama.rs +++ b/testing/tests/ui/assign-to-askama.rs @@ -45,7 +45,7 @@ test_kw!(Macro "{% let macro %}"); test_kw!(Match "{% let match %}"); test_kw!(Mod "{% let mod %}"); test_kw!(Move "{% let move %}"); -test_kw!(Mut "{% let mut %}"); +test_kw!(Mut "{% let mut mut %}"); test_kw!(Override "{% let override %}"); test_kw!(Priv "{% let priv %}"); test_kw!(Pub "{% let pub %}"); diff --git a/testing/tests/ui/assign-to-askama.stderr b/testing/tests/ui/assign-to-askama.stderr index 20f9b83e..f8344abe 100644 --- a/testing/tests/ui/assign-to-askama.stderr +++ b/testing/tests/ui/assign-to-askama.stderr @@ -247,12 +247,12 @@ error: cannot use `move` as a name: it is a rust keyword | ^^^^^^^^^^^^^^^^ error: cannot use `mut` as a name: it is a rust keyword - --> :1:7 + --> :1:11 "mut %}" --> tests/ui/assign-to-askama.rs:48:14 | -48 | test_kw!(Mut "{% let mut %}"); - | ^^^^^^^^^^^^^^^ +48 | test_kw!(Mut "{% let mut mut %}"); + | ^^^^^^^^^^^^^^^^^^^ error: cannot use `override` as a name: it is a rust keyword --> :1:7