Skip to content

Commit 37c300d

Browse files
Merge pull request #42 from GuillaumeGomez/top-level-nodes-errors
Generate better errors for top level nodes
2 parents b5f21c0 + d4b363b commit 37c300d

File tree

7 files changed

+128
-34
lines changed

7 files changed

+128
-34
lines changed

rinja_derive/src/heritage.rs

+34-25
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,25 @@ impl Context<'_> {
7676
while let Some(nodes) = nested.pop() {
7777
for n in nodes {
7878
match n {
79-
Node::Extends(e) if top => match extends {
80-
Some(_) => {
81-
return Err(CompileError::no_file_info("multiple extend blocks found"))
79+
Node::Extends(e) => {
80+
ensure_top(top, e, path, parsed, "extends")?;
81+
if extends.is_some() {
82+
return Err(CompileError::new(
83+
"multiple extend blocks found",
84+
Some(FileInfo::of(e, path, parsed)),
85+
));
8286
}
83-
None => {
84-
extends = Some(config.find_template(e.path, Some(path))?);
85-
}
86-
},
87-
Node::Macro(m) if top => {
87+
extends = Some(config.find_template(e.path, Some(path))?);
88+
}
89+
Node::Macro(m) => {
90+
ensure_top(top, m, path, parsed, "macro")?;
8891
macros.insert(m.name, &**m);
8992
}
90-
Node::Import(import) if top => {
93+
Node::Import(import) => {
94+
ensure_top(top, import, path, parsed, "import")?;
9195
let path = config.find_template(import.path, Some(path))?;
9296
imports.insert(import.scope, path);
9397
}
94-
Node::Extends(_) | Node::Macro(_) | Node::Import(_) if !top => {
95-
return Err(CompileError::no_file_info(
96-
"extends, macro or import blocks not allowed below top level",
97-
));
98-
}
9998
Node::BlockDef(b) => {
10099
blocks.insert(b.name, &**b);
101100
nested.push(&b.nodes);
@@ -132,16 +131,26 @@ impl Context<'_> {
132131
}
133132

134133
pub(crate) fn generate_error<T>(&self, msg: &str, node: &WithSpan<'_, T>) -> CompileError {
135-
match self.path {
136-
Some(path) => CompileError::new(
137-
msg,
138-
Some(FileInfo::new(
139-
path,
140-
Some(self.parsed.source()),
141-
Some(node.span()),
142-
)),
143-
),
144-
None => CompileError::new(msg, None),
145-
}
134+
CompileError::new(
135+
msg,
136+
self.path.map(|path| FileInfo::of(node, path, self.parsed)),
137+
)
138+
}
139+
}
140+
141+
fn ensure_top<T>(
142+
top: bool,
143+
node: &WithSpan<'_, T>,
144+
path: &Path,
145+
parsed: &Parsed,
146+
kind: &str,
147+
) -> Result<(), CompileError> {
148+
if top {
149+
Ok(())
150+
} else {
151+
Err(CompileError::new(
152+
format!("`{kind}` blocks are not allowed below top level"),
153+
Some(FileInfo::of(node, path, parsed)),
154+
))
146155
}
147156
}

rinja_derive/src/lib.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use config::{read_config_file, Config};
1616
use generator::{Generator, MapChain};
1717
use heritage::{Context, Heritage};
1818
use input::{Print, TemplateArgs, TemplateInput};
19-
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError};
19+
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError, Parsed, WithSpan};
2020
use proc_macro2::{Span, TokenStream};
2121

2222
#[cfg(not(feature = "__standalone"))]
@@ -138,7 +138,7 @@ struct CompileError {
138138
}
139139

140140
impl CompileError {
141-
fn new<S: fmt::Display>(msg: S, file_info: Option<FileInfo<'_, '_, '_>>) -> Self {
141+
fn new<S: fmt::Display>(msg: S, file_info: Option<FileInfo<'_>>) -> Self {
142142
let msg = match file_info {
143143
Some(file_info) => format!("{msg}{file_info}"),
144144
None => msg.to_string(),
@@ -178,23 +178,31 @@ impl From<ParseError> for CompileError {
178178
}
179179
}
180180

181-
struct FileInfo<'a, 'b, 'c> {
181+
struct FileInfo<'a> {
182182
path: &'a Path,
183-
source: Option<&'b str>,
184-
node_source: Option<&'c str>,
183+
source: Option<&'a str>,
184+
node_source: Option<&'a str>,
185185
}
186186

187-
impl<'a, 'b, 'c> FileInfo<'a, 'b, 'c> {
188-
fn new(path: &'a Path, source: Option<&'b str>, node_source: Option<&'c str>) -> Self {
187+
impl<'a> FileInfo<'a> {
188+
fn new(path: &'a Path, source: Option<&'a str>, node_source: Option<&'a str>) -> Self {
189189
Self {
190190
path,
191191
source,
192192
node_source,
193193
}
194194
}
195+
196+
fn of<T>(node: &WithSpan<'a, T>, path: &'a Path, parsed: &'a Parsed) -> Self {
197+
Self {
198+
path,
199+
source: Some(parsed.source()),
200+
node_source: Some(node.span()),
201+
}
202+
}
195203
}
196204

197-
impl<'a, 'b, 'c> fmt::Display for FileInfo<'a, 'b, 'c> {
205+
impl fmt::Display for FileInfo<'_> {
198206
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199207
match (self.source, self.node_source) {
200208
(Some(source), Some(node_source)) => {

rinja_parser/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl<'a, T> WithSpan<'a, T> {
147147
Self { inner, span }
148148
}
149149

150-
pub fn span(&self) -> &str {
150+
pub fn span(&self) -> &'a str {
151151
self.span
152152
}
153153
}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use rinja::Template;
2+
3+
#[derive(Template)]
4+
#[template(source = r#"
5+
{% block bla %}
6+
{% extends "bla.txt" %}
7+
{% endblock %}
8+
"#, ext = "txt")]
9+
struct MyTemplate1;
10+
11+
#[derive(Template)]
12+
#[template(source = r#"
13+
{% block bla %}
14+
{% macro bla() %}
15+
{% endmacro %}
16+
{% endblock %}
17+
"#, ext = "txt")]
18+
struct MyTemplate2;
19+
20+
#[derive(Template)]
21+
#[template(source = r#"
22+
{% block bla %}
23+
{% import "bla.txt" as blue %}
24+
{% endblock %}
25+
"#, ext = "txt")]
26+
struct MyTemplate3;
27+
28+
fn main() {
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error: `extends` blocks are not allowed below top level
2+
--> MyTemplate1.txt:3:2
3+
" extends \"bla.txt\" %}\n{% endblock %}\n"
4+
--> tests/ui/blocks_below_top_level.rs:3:10
5+
|
6+
3 | #[derive(Template)]
7+
| ^^^^^^^^
8+
|
9+
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
10+
11+
error: `macro` blocks are not allowed below top level
12+
--> MyTemplate2.txt:3:2
13+
" macro bla() %}\n{% endmacro %}\n{% endblo"...
14+
--> tests/ui/blocks_below_top_level.rs:11:10
15+
|
16+
11 | #[derive(Template)]
17+
| ^^^^^^^^
18+
|
19+
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)
20+
21+
error: `import` blocks are not allowed below top level
22+
--> MyTemplate3.txt:3:2
23+
" import \"bla.txt\" as blue %}\n{% endblock"...
24+
--> tests/ui/blocks_below_top_level.rs:20:10
25+
|
26+
20 | #[derive(Template)]
27+
| ^^^^^^^^
28+
|
29+
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)

testing/tests/ui/multiple_extends.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use rinja::Template;
2+
3+
#[derive(Template)]
4+
#[template(source = r#"
5+
{% extends "let.html" %}
6+
{% extends "foo.html" %}
7+
"#, ext = "txt")]
8+
struct MyTemplate4;
9+
10+
fn main() {}
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error: multiple extend blocks found
2+
--> MyTemplate4.txt:3:2
3+
" extends \"foo.html\" %}\n"
4+
--> tests/ui/multiple_extends.rs:3:10
5+
|
6+
3 | #[derive(Template)]
7+
| ^^^^^^^^
8+
|
9+
= note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)