mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-28 13:30:59 +00:00
Merge pull request #42 from GuillaumeGomez/top-level-nodes-errors
Generate better errors for top level nodes
This commit is contained in:
commit
37c300d483
@ -76,26 +76,25 @@ impl Context<'_> {
|
||||
while let Some(nodes) = nested.pop() {
|
||||
for n in nodes {
|
||||
match n {
|
||||
Node::Extends(e) if top => match extends {
|
||||
Some(_) => {
|
||||
return Err(CompileError::no_file_info("multiple extend blocks found"))
|
||||
Node::Extends(e) => {
|
||||
ensure_top(top, e, path, parsed, "extends")?;
|
||||
if extends.is_some() {
|
||||
return Err(CompileError::new(
|
||||
"multiple extend blocks found",
|
||||
Some(FileInfo::of(e, path, parsed)),
|
||||
));
|
||||
}
|
||||
None => {
|
||||
extends = Some(config.find_template(e.path, Some(path))?);
|
||||
}
|
||||
},
|
||||
Node::Macro(m) if top => {
|
||||
extends = Some(config.find_template(e.path, Some(path))?);
|
||||
}
|
||||
Node::Macro(m) => {
|
||||
ensure_top(top, m, path, parsed, "macro")?;
|
||||
macros.insert(m.name, &**m);
|
||||
}
|
||||
Node::Import(import) if top => {
|
||||
Node::Import(import) => {
|
||||
ensure_top(top, import, path, parsed, "import")?;
|
||||
let path = config.find_template(import.path, Some(path))?;
|
||||
imports.insert(import.scope, path);
|
||||
}
|
||||
Node::Extends(_) | Node::Macro(_) | Node::Import(_) if !top => {
|
||||
return Err(CompileError::no_file_info(
|
||||
"extends, macro or import blocks not allowed below top level",
|
||||
));
|
||||
}
|
||||
Node::BlockDef(b) => {
|
||||
blocks.insert(b.name, &**b);
|
||||
nested.push(&b.nodes);
|
||||
@ -132,16 +131,26 @@ impl Context<'_> {
|
||||
}
|
||||
|
||||
pub(crate) fn generate_error<T>(&self, msg: &str, node: &WithSpan<'_, T>) -> CompileError {
|
||||
match self.path {
|
||||
Some(path) => CompileError::new(
|
||||
msg,
|
||||
Some(FileInfo::new(
|
||||
path,
|
||||
Some(self.parsed.source()),
|
||||
Some(node.span()),
|
||||
)),
|
||||
),
|
||||
None => CompileError::new(msg, None),
|
||||
}
|
||||
CompileError::new(
|
||||
msg,
|
||||
self.path.map(|path| FileInfo::of(node, path, self.parsed)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_top<T>(
|
||||
top: bool,
|
||||
node: &WithSpan<'_, T>,
|
||||
path: &Path,
|
||||
parsed: &Parsed,
|
||||
kind: &str,
|
||||
) -> Result<(), CompileError> {
|
||||
if top {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CompileError::new(
|
||||
format!("`{kind}` blocks are not allowed below top level"),
|
||||
Some(FileInfo::of(node, path, parsed)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use config::{read_config_file, Config};
|
||||
use generator::{Generator, MapChain};
|
||||
use heritage::{Context, Heritage};
|
||||
use input::{Print, TemplateArgs, TemplateInput};
|
||||
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError};
|
||||
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError, Parsed, WithSpan};
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
|
||||
#[cfg(not(feature = "__standalone"))]
|
||||
@ -138,7 +138,7 @@ struct CompileError {
|
||||
}
|
||||
|
||||
impl CompileError {
|
||||
fn new<S: fmt::Display>(msg: S, file_info: Option<FileInfo<'_, '_, '_>>) -> Self {
|
||||
fn new<S: fmt::Display>(msg: S, file_info: Option<FileInfo<'_>>) -> Self {
|
||||
let msg = match file_info {
|
||||
Some(file_info) => format!("{msg}{file_info}"),
|
||||
None => msg.to_string(),
|
||||
@ -178,23 +178,31 @@ impl From<ParseError> for CompileError {
|
||||
}
|
||||
}
|
||||
|
||||
struct FileInfo<'a, 'b, 'c> {
|
||||
struct FileInfo<'a> {
|
||||
path: &'a Path,
|
||||
source: Option<&'b str>,
|
||||
node_source: Option<&'c str>,
|
||||
source: Option<&'a str>,
|
||||
node_source: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> FileInfo<'a, 'b, 'c> {
|
||||
fn new(path: &'a Path, source: Option<&'b str>, node_source: Option<&'c str>) -> Self {
|
||||
impl<'a> FileInfo<'a> {
|
||||
fn new(path: &'a Path, source: Option<&'a str>, node_source: Option<&'a str>) -> Self {
|
||||
Self {
|
||||
path,
|
||||
source,
|
||||
node_source,
|
||||
}
|
||||
}
|
||||
|
||||
fn of<T>(node: &WithSpan<'a, T>, path: &'a Path, parsed: &'a Parsed) -> Self {
|
||||
Self {
|
||||
path,
|
||||
source: Some(parsed.source()),
|
||||
node_source: Some(node.span()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> fmt::Display for FileInfo<'a, 'b, 'c> {
|
||||
impl fmt::Display for FileInfo<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match (self.source, self.node_source) {
|
||||
(Some(source), Some(node_source)) => {
|
||||
|
@ -147,7 +147,7 @@ impl<'a, T> WithSpan<'a, T> {
|
||||
Self { inner, span }
|
||||
}
|
||||
|
||||
pub fn span(&self) -> &str {
|
||||
pub fn span(&self) -> &'a str {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
29
testing/tests/ui/blocks_below_top_level.rs
Normal file
29
testing/tests/ui/blocks_below_top_level.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use rinja::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(source = r#"
|
||||
{% block bla %}
|
||||
{% extends "bla.txt" %}
|
||||
{% endblock %}
|
||||
"#, ext = "txt")]
|
||||
struct MyTemplate1;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(source = r#"
|
||||
{% block bla %}
|
||||
{% macro bla() %}
|
||||
{% endmacro %}
|
||||
{% endblock %}
|
||||
"#, ext = "txt")]
|
||||
struct MyTemplate2;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(source = r#"
|
||||
{% block bla %}
|
||||
{% import "bla.txt" as blue %}
|
||||
{% endblock %}
|
||||
"#, ext = "txt")]
|
||||
struct MyTemplate3;
|
||||
|
||||
fn main() {
|
||||
}
|
29
testing/tests/ui/blocks_below_top_level.stderr
Normal file
29
testing/tests/ui/blocks_below_top_level.stderr
Normal file
@ -0,0 +1,29 @@
|
||||
error: `extends` blocks are not allowed below top level
|
||||
--> MyTemplate1.txt:3:2
|
||||
" extends \"bla.txt\" %}\n{% endblock %}\n"
|
||||
--> tests/ui/blocks_below_top_level.rs:3:10
|
||||
|
|
||||
3 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: `macro` blocks are not allowed below top level
|
||||
--> MyTemplate2.txt:3:2
|
||||
" macro bla() %}\n{% endmacro %}\n{% endblo"...
|
||||
--> tests/ui/blocks_below_top_level.rs:11:10
|
||||
|
|
||||
11 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: `import` blocks are not allowed below top level
|
||||
--> MyTemplate3.txt:3:2
|
||||
" import \"bla.txt\" as blue %}\n{% endblock"...
|
||||
--> tests/ui/blocks_below_top_level.rs:20:10
|
||||
|
|
||||
20 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
10
testing/tests/ui/multiple_extends.rs
Normal file
10
testing/tests/ui/multiple_extends.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use rinja::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(source = r#"
|
||||
{% extends "let.html" %}
|
||||
{% extends "foo.html" %}
|
||||
"#, ext = "txt")]
|
||||
struct MyTemplate4;
|
||||
|
||||
fn main() {}
|
9
testing/tests/ui/multiple_extends.stderr
Normal file
9
testing/tests/ui/multiple_extends.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error: multiple extend blocks found
|
||||
--> MyTemplate4.txt:3:2
|
||||
" extends \"foo.html\" %}\n"
|
||||
--> tests/ui/multiple_extends.rs:3:10
|
||||
|
|
||||
3 | #[derive(Template)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
|
Loading…
x
Reference in New Issue
Block a user