Skip to content

Commit

Permalink
Merge pull request #42 from GuillaumeGomez/top-level-nodes-errors
Browse files Browse the repository at this point in the history
Generate better errors for top level nodes
  • Loading branch information
GuillaumeGomez authored Jul 3, 2024
2 parents b5f21c0 + d4b363b commit 37c300d
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 34 deletions.
59 changes: 34 additions & 25 deletions rinja_derive/src/heritage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)),
))
}
}
24 changes: 16 additions & 8 deletions rinja_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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)) => {
Expand Down
2 changes: 1 addition & 1 deletion rinja_parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
29 changes: 29 additions & 0 deletions testing/tests/ui/blocks_below_top_level.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 29 additions & 0 deletions testing/tests/ui/blocks_below_top_level.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 10 additions & 0 deletions testing/tests/ui/multiple_extends.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions testing/tests/ui/multiple_extends.stderr
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 37c300d

Please sign in to comment.