askama
askama copied to clipboard
More specific parse errors?
I was experimenting with switching a small project from using tera to askama. All went smoothly with one small exception:
The tera templates contained some things like {% if name['test'] %}
which in askama has a different syntax of {% if name.test %}
Difference is syntax is not a problem, however to narrow down this as the cause of the error was difficult. For example, with this template
Hello, {{ user.name }}!
{% if user['verified'] %}
Bye
{% endif %]}
..I get the following error:
error: proc-macro derive panicked
--> src/main.rs:3:10
|
3 | #[derive(Template)]
| ^^^^^^^^
|
= help: message: unable to parse template:
"{% if user[\'verified\'] %}\nBye\n{% endif %]}"
error: aborting due to previous error
While the error does narrow down approximately where the error is, it was not immediately clear what the cause was (especially when the quoted line is much longer - was many lines long in my actual template)
It would be nice if there was a clearer error - even if it just narrowed down to the specific statement ({% if ... %}
) instead of the entire contents of the block would be a great improvement (since the contents can be potentially very long), but I suspect this might be harder than it sounds!
You can actually sort of assume that the specific {% if ... %}
block is causing the problem. Due to how parser combinators work (where in some cases the parser relies on trying different potential parsings in order if earlier ones fail), I think it would be pretty hard to do much better here. I agree that this could use improvements, but I'm unlikely be motivated to work on this anytime soon (unless there was an external motivation). Happy to review a design for an improvement and/or a PR, though!
The error location could be better determined by introducing cuts. E.g.
opt(tag("-")),
ws(tag("for")),
ws(alt((target_single, target_tuple))),
ws(tag("in")),
ws(expr_any),
opt(tag("-")),
|i| tag_block_end(i, s),
|i| parse_template(i, s),
|i| tag_block_start(i, s),
opt(tag("-")),
ws(tag("endfor")),
opt(tag("-")),
→
opt(tag("-")),
ws(tag("for")),
cut(tuple((
ws(alt((target_single, target_tuple))),
ws(tag("in")),
ws(expr_any),
opt(tag("-")),
|i| tag_block_end(i, s),
cut(tuple((
|i| parse_template(i, s),
cut(tuple((
|i| tag_block_start(i, s),
opt(tag("-")),
ws(tag("endfor")),
opt(tag("-")),
)))
)))
)))
@Kijewski sounds interesting. Can you give an example before/after error?
Was fixed in #513.