From d16eaf662347069f7642590ab34ef6a387ab3889 Mon Sep 17 00:00:00 2001 From: Ross MacArthur Date: Fri, 21 Oct 2022 16:33:00 +0200 Subject: [PATCH] Add template name to error, update error format --- src/error.rs | 96 +++++++++++++++------------ src/lib.rs | 22 +++++-- tests/compile.rs | 162 ++++++++++++++++++++++++++++++++++++---------- tests/filters.rs | 29 +++++++-- tests/lex.rs | 57 ++++++++++++---- tests/render.rs | 101 ++++++++++++++++++++++------- tests/to_value.rs | 4 +- 7 files changed, 349 insertions(+), 122 deletions(-) diff --git a/src/error.rs b/src/error.rs index f2e536a..418b877 100644 --- a/src/error.rs +++ b/src/error.rs @@ -9,6 +9,9 @@ pub struct Error { /// The type of error, possibly carries a source error. kind: ErrorKind, + /// Optional template name. + name: Option, + /// Optional additional reason for this kind of error. reason: Option, @@ -59,6 +62,7 @@ impl Error { pub(crate) fn syntax(reason: impl Into, source: &str, span: impl Into) -> Self { Self { kind: ErrorKind::Syntax, + name: None, reason: Some(reason.into()), pretty: Some(Pretty::build(source, span.into())), } @@ -68,6 +72,7 @@ impl Error { pub(crate) fn render(reason: impl Into, source: &str, span: impl Into) -> Self { Self { kind: ErrorKind::Render, + name: None, reason: Some(reason.into()), pretty: Some(Pretty::build(source, span.into())), } @@ -77,11 +82,18 @@ impl Error { pub(crate) fn max_include_depth(max: usize) -> Self { Self { kind: ErrorKind::Render, + name: None, reason: Some(format!("reached maximum include depth ({})", max)), pretty: None, } } + /// Attaches a template name to the error, if it is not already set. + pub(crate) fn with_template_name(mut self, name: &str) -> Self { + self.name.get_or_insert(name.into()); + self + } + /// Attaches pretty information to the error and converts it to a render /// error kind. pub(crate) fn into_render(mut self, source: &str, span: impl Into) -> Self { @@ -96,6 +108,7 @@ impl From for Error { fn from(err: io::Error) -> Self { Self { kind: ErrorKind::Io(err), + name: None, reason: None, pretty: None, } @@ -106,6 +119,7 @@ impl From for Error { fn from(err: fmt::Error) -> Self { Self { kind: ErrorKind::Fmt(err), + name: None, reason: None, pretty: None, } @@ -116,6 +130,7 @@ impl From for Error { fn from(msg: String) -> Self { Self { kind: ErrorKind::Other, + name: None, reason: Some(msg), pretty: None, } @@ -131,6 +146,7 @@ impl serde::ser::Error for Error { { Self { kind: ErrorKind::Serialize, + name: None, reason: Some(msg.to_string()), pretty: None, } @@ -149,44 +165,36 @@ impl std::error::Error for Error { impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if !f.alternate() { + writeln!(f, "{:#}", self)?; + } + f.debug_struct("Error") .field("kind", &self.kind) + .field("name", &self.name) .field("reason", &self.reason) .field("pretty", &self.pretty) .finish()?; - - match (&self.pretty, &self.reason) { - (Some(p), Some(r)) if !f.alternate() => { - write!(f, "\n\n{}", self.kind)?; - p.fmt_with_reason(f, r)? - } - _ => {} - } Ok(()) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.kind.fmt(f)?; - match (&self.pretty, &self.reason) { - (Some(p), Some(r)) if f.alternate() => p.fmt_with_reason(f, r)?, - (_, Some(r)) => write!(f, ": {}", r)?, - _ => {} - } - Ok(()) - } -} - -impl fmt::Display for ErrorKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Syntax => write!(f, "invalid syntax"), - Self::Render => write!(f, "failed to render"), - Self::Serialize => write!(f, "failed to serialize value"), - Self::Io(_) => write!(f, "io error"), - Self::Fmt(_) => write!(f, "format error"), - Self::Other => write!(f, "other error"), + let msg = match &self.kind { + ErrorKind::Syntax => "invalid syntax", + ErrorKind::Render | ErrorKind::Other => "render error", + ErrorKind::Serialize => "serialize error", + ErrorKind::Io(_) => "io error", + ErrorKind::Fmt(_) => "format error", + }; + match (&self.reason, &self.pretty) { + (Some(r), Some(p)) if f.alternate() => { + write!(f, "{}", msg)?; + p.fmt_with_reason(f, self.name.as_deref(), r) + } + (Some(reason), _) => write!(f, "{msg}: {reason}"), + _ => write!(f, "{msg}"), } } } @@ -225,25 +233,33 @@ impl Pretty { } } - fn fmt_with_reason(&self, f: &mut fmt::Formatter<'_>, reason: &str) -> fmt::Result { + fn fmt_with_reason( + &self, + f: &mut fmt::Formatter<'_>, + name: Option<&str>, + reason: &str, + ) -> fmt::Result { let num = (self.ln + 1).to_string(); + let col = self.col + 1; let pad = display_width(&num); + let align = self.col + self.width; + + let z = ""; let pipe = "|"; + let equals = "="; let underline = "^".repeat(self.width); + let extra = "-".repeat(3_usize.saturating_sub(self.width)); + let name = name.unwrap_or(""); + let text = &self.text; + write!( f, - "\n \ - {0:pad$} {pipe}\n \ - {num:>} {pipe} {text}\n \ - {0:pad$} {pipe} {underline:>width$} {msg}\n", - "", - pad = pad, - pipe = pipe, - num = num, - text = self.text, - underline = underline, - width = self.col + self.width, - msg = reason + "\n\n {z:pad$}--> {name}:{num}:{col}\ + \n {z:pad$} {pipe}\ + \n {num:>} {pipe} {text}\ + \n {z:pad$} {pipe} {underline:>align$}{extra}\ + \n {z:pad$} {pipe}\ + \n {z:pad$} {equals} reason: {reason}\n", ) } } diff --git a/src/lib.rs b/src/lib.rs index 7abb3d0..c423ebf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -251,6 +251,7 @@ pub struct Template<'engine, 'source> { #[cfg_attr(internal_debug, derive(Debug))] pub struct TemplateRef<'engine> { engine: &'engine Engine<'engine>, + name: &'engine str, template: &'engine program::Template<'engine>, } @@ -356,18 +357,23 @@ impl<'engine> Engine<'engine> { N: Into>, S: Into>, { - let template = compile::template(self, source.into())?; - self.templates.insert(name.into(), template); + let name = name.into(); + let source = source.into(); + let template = compile::template(self, source).map_err(|e| e.with_template_name(&name))?; + self.templates.insert(name, template); Ok(()) } /// Lookup a template by name. #[inline] pub fn get_template(&self, name: &str) -> Option> { - self.templates.get(name).map(|template| TemplateRef { - engine: self, - template, - }) + self.templates + .get_key_value(name) + .map(|(name, template)| TemplateRef { + engine: self, + name, + template, + }) } /// Compile a template. @@ -470,6 +476,7 @@ impl<'engine> TemplateRef<'engine> { S: serde::Serialize, { render::template(self.engine, self.template, to_value(ctx)?) + .map_err(|e| e.with_template_name(self.name)) } /// Render the template to a writer using the provided value. @@ -482,6 +489,7 @@ impl<'engine> TemplateRef<'engine> { S: serde::Serialize, { render::template_to(self.engine, self.template, writer, to_value(ctx)?) + .map_err(|e| e.with_template_name(self.name)) } /// Render the template to a string using the provided value. @@ -491,6 +499,7 @@ impl<'engine> TemplateRef<'engine> { V: Into, { render::template(self.engine, self.template, ctx.into()) + .map_err(|e| e.with_template_name(self.name)) } /// Render the template to a writer using the provided value. @@ -501,6 +510,7 @@ impl<'engine> TemplateRef<'engine> { V: Into, { render::template_to(self.engine, self.template, writer, ctx.into()) + .map_err(|e| e.with_template_name(self.name)) } /// Returns the original template source. diff --git a/tests/compile.rs b/tests/compile.rs index 1e4711b..f9b44b8 100644 --- a/tests/compile.rs +++ b/tests/compile.rs @@ -85,9 +85,12 @@ fn compile_inline_expr_err_eof() { &err, "expected identifier, found EOF", " + --> :1:23 | 1 | lorem {{ ipsum.dolor | - | ^ REASON + | ^-- + | + = reason: REASON ", ) } @@ -101,9 +104,12 @@ fn compile_inline_expr_err_args_eof() { &err, "expected token, found EOF", " + --> :1:24 | 1 | lorem {{ ipsum | dolor: - | ^ REASON + | ^-- + | + = reason: REASON ", ) } @@ -117,9 +123,12 @@ fn compile_inline_expr_err_unexpected_keyword() { &err, "unexpected keyword `for`", r#" + --> :1:25 | 1 | lorem {{ ipsum | dolor: for }} - | ^^^ REASON + | ^^^ + | + = reason: REASON "#, ) } @@ -133,9 +142,12 @@ fn compile_inline_expr_err_integer_invalid_digit() { &err, "invalid digit for base 2 literal", " + --> :1:29 | 1 | lorem {{ ipsum | dolor: 0b0131 }} - | ^ REASON + | ^-- + | + = reason: REASON ", ) } @@ -149,9 +161,12 @@ fn compile_inline_expr_err_integer_overflow() { &err, "base 16 literal out of range for 64-bit integer", " + --> :1:25 | 1 | lorem {{ ipsum | dolor: 0xffffffffffffffff }} - | ^^^^^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^^^^^ + | + = reason: REASON ", ) } @@ -165,9 +180,12 @@ fn compile_inline_expr_err_float_invalid() { &err, "invalid float literal", " + --> :1:25 | 1 | lorem {{ ipsum | dolor: +0.23d5 }} - | ^^^^^^^ REASON + | ^^^^^^^ + | + = reason: REASON ", ) } @@ -181,9 +199,12 @@ fn compile_inline_expr_err_unknown_escape_character() { &err, "unknown escape character", r#" + --> :1:31 | 1 | lorem {{ ipsum | dolor: "sit \x" }} - | ^ REASON + | ^-- + | + = reason: REASON "#, ) } @@ -197,9 +218,12 @@ fn compile_inline_expr_err_unexpected_comma_token() { &err, "expected expression, found comma", " + --> :1:25 | 1 | lorem {{ ipsum | dolor: , - | ^ REASON + | ^-- + | + = reason: REASON ", ) } @@ -213,9 +237,12 @@ fn compile_inline_expr_err_empty() { &err, "expected expression, found end expression", " + --> :1:10 | 1 | lorem {{ }} ipsum dolor - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -229,9 +256,12 @@ fn compile_inline_expr_err_unexpected_pipe_token() { &err, "expected expression, found pipe", " + --> :1:10 | 1 | lorem {{ | }} ipsum dolor - | ^ REASON + | ^-- + | + = reason: REASON ", ); } @@ -245,9 +275,12 @@ fn compile_inline_expr_err_unexpected_period_token() { &err, "expected identifier, found period", " + --> :1:18 | 1 | lorem {{ ipsum | . }} dolor - | ^ REASON + | ^-- + | + = reason: REASON ", ); } @@ -261,9 +294,12 @@ fn compile_inline_expr_err_expected_function() { &err, "expected identifier, found end expression", " + --> :1:24 | 1 | lorem {{ ipsum.dolor | }} sit - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -277,9 +313,12 @@ fn compile_inline_expr_err_expected_end_expression() { &err, "expected end expression, found identifier", " + --> :1:16 | 1 | lorem {{ ipsum dolor }} sit - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -332,9 +371,12 @@ fn compile_if_statement_err_expected_keyword() { &err, "expected keyword, found identifier", " + --> :1:10 | 1 | lorem {% fi ipsum %} dolor {% endif %} sit - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -348,9 +390,12 @@ fn compile_if_statement_err_unexpected_keyword() { &err, "unexpected keyword `in`", " + --> :1:10 | 1 | lorem {% in ipsum %} dolor {% endif %} sit - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -364,9 +409,12 @@ fn compile_if_statement_err_unexpected_endif_block() { &err, "unexpected `endif` block", " + --> :1:7 | 1 | lorem {% endif %} ipsum - | ^^^^^^^^^^^ REASON + | ^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -380,9 +428,12 @@ fn compile_if_statement_err_unexpected_else_if_block() { &err, "unexpected `else if` block", " + --> :1:7 | 1 | lorem {% else if cond %} {% endif %} ipsum - | ^^^^^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -396,9 +447,12 @@ fn compile_if_statement_err_unexpected_else_block() { &err, "unexpected `else` block", " + --> :1:7 | 1 | lorem {% else %} {% endif %} ipsum - | ^^^^^^^^^^ REASON + | ^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -412,9 +466,12 @@ fn compile_if_statement_err_unexpected_endfor_block() { &err, "unexpected `endfor` block", " + --> :1:22 | 1 | lorem {% if ipsum %} {% endfor %} dolor - | ^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -428,9 +485,12 @@ fn compile_if_else_statement_err_unclosed_if_block() { &err, "unclosed `if` block", " + --> :1:7 | 1 | lorem {% if ipsum %} dolor {% else if sit %} - | ^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -444,9 +504,12 @@ fn compile_if_statement_err_unclosed_if_block() { &err, "unclosed `if` block", " + --> :1:7 | 1 | lorem {% if ipsum %} dolor - | ^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -474,9 +537,12 @@ fn compile_for_statement_err_trailing_comma() { &err, "expected identifier, found keyword", " + --> :1:21 | 1 | lorem {% for ipsum, in dolor %} sit - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -490,9 +556,12 @@ fn compile_for_statement_err_unexpected_keyword() { &err, "expected keyword `in`, found keyword `endif`", " + --> :1:20 | 1 | lorem {% for ipsum endif %} dolor - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -506,9 +575,12 @@ fn compile_for_statement_err_missing_iterable() { &err, "expected expression, found end block", " + --> :1:23 | 1 | lorem {% for ipsum in %} dolor - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -522,9 +594,12 @@ fn compile_for_statement_err_unexpected_endfor_block() { &err, "unexpected `endfor` block", " + --> :1:7 | 1 | lorem {% endfor %} ipsum - | ^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -538,9 +613,12 @@ fn compile_for_statement_err_unexpected_else_block() { &err, "unexpected `else` block", " + --> :1:35 | 1 | lorem {% for _, ipsum in dolor %} {% else %} {% endif %} - | ^^^^^^^^^^ REASON + | ^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -554,9 +632,12 @@ fn compile_for_statement_err_unexpected_else_if_block() { &err, "unexpected `else if` block", " + --> :1:35 | 1 | lorem {% for _, ipsum in dolor %} {% else if cond %} - | ^^^^^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -570,9 +651,12 @@ fn compile_for_statement_err_unexpected_endif_block() { &err, "unexpected `endif` block", " + --> :1:35 | 1 | lorem {% for _, ipsum in dolor %} {% endif %} - | ^^^^^^^^^^^ REASON + | ^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -586,9 +670,12 @@ fn compile_for_statement_err_unclosed_for_block() { &err, "unclosed `for` block", " + --> :1:7 | 1 | lorem {% for ipsum, dolor in sit %} amet - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -609,9 +696,12 @@ fn compile_with_statement_err_unclosed_with_block() { &err, "unclosed `with` block", " + --> :1:7 | 1 | lorem {% with ipsum as dolor %} sit - | ^^^^^^^^^^^^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -625,9 +715,12 @@ fn compile_with_statement_err_unexpected_endwith_block() { &err, "unexpected `else` block", " + --> :1:37 | 1 | lorem {% with ipsum as dolor %} sit {% else %} {% endif %} - | ^^^^^^^^^^ REASON + | ^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -641,9 +734,12 @@ fn compile_with_statement_err_unexpected_else_block() { &err, "unexpected `endwith` block", " + --> :1:7 | 1 | lorem {% endwith %} ipsum - | ^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -672,7 +768,7 @@ fn compile_include_with_statement_filters() { #[track_caller] fn assert_err(err: &Error, reason: &str, pretty: &str) { let display = format!("invalid syntax: {}", reason); - let display_alt = format!("invalid syntax{}", pretty.replace("REASON", reason)); + let display_alt = format!("invalid syntax\n{}", pretty.replace("REASON", reason)); assert_eq!(err.to_string(), display); assert_eq!(format!("{:#}", err), display_alt); } diff --git a/tests/filters.rs b/tests/filters.rs index 02ca2ad..3d5934f 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -97,9 +97,12 @@ fn render_filter_err_expected_0_args() { &err, "filter expected 0 arguments", " + --> :1:11 | 1 | {{ name | test: 123 }} - | ^^^^ REASON + | ^^^^ + | + = reason: REASON ", ); } @@ -117,9 +120,12 @@ fn render_filter_err_expected_n_args() { &err, "filter expected 3 arguments", " + --> :1:11 | 1 | {{ name | test }} - | ^^^^ REASON + | ^^^^ + | + = reason: REASON ", ); } @@ -200,9 +206,12 @@ fn render_filter_err_expected_value_type() { &err, "filter expected bool value, found string", " + --> :1:11 | 1 | {{ name | test }} - | ^^^^ REASON + | ^^^^ + | + = reason: REASON ", ); } @@ -220,9 +229,12 @@ fn render_filter_err_expected_arg_type() { &err, "filter expected bool argument, found integer", " + --> :1:17 | 1 | {{ name | test: 123 }} - | ^^^ REASON + | ^^^ + | + = reason: REASON ", ); } @@ -248,17 +260,20 @@ fn render_filter_err_expected_arg_reference() { &err, "filter expected reference argument but this string can only be passed as owned", " + --> :2:23 | 2 | {{ surname | prepend: name }} - | ^^^^ REASON + | ^^^^ + | + = reason: REASON ", ); } #[track_caller] fn assert_err(err: &Error, reason: &str, pretty: &str) { - let display = format!("failed to render: {}", reason); - let display_alt = format!("failed to render{}", pretty.replace("REASON", reason)); + let display = format!("render error: {}", reason); + let display_alt = format!("render error\n{}", pretty.replace("REASON", reason)); assert_eq!(err.to_string(), display); assert_eq!(format!("{:#}", err), display_alt); } diff --git a/tests/lex.rs b/tests/lex.rs index a0eacfd..db4dc5a 100644 --- a/tests/lex.rs +++ b/tests/lex.rs @@ -7,9 +7,12 @@ fn lex_while_eof() { &err, "expected end expression, found EOF", " + --> :1:15 | 1 | lorem {{ ipsum - | ^ REASON + | ^-- + | + = reason: REASON ", ); } @@ -54,9 +57,12 @@ fn lex_err_unexpected_end_expr() { &err, "unexpected end expression", " + --> :1:13 | 1 | lorem ipsum }} dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -70,9 +76,12 @@ fn lex_err_unexpected_end_block() { &err, "unexpected end block", " + --> :1:13 | 1 | lorem ipsum %} dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -86,9 +95,12 @@ fn lex_err_unclosed_begin_expr() { &err, "unclosed begin expression", " + --> :1:13 | 1 | lorem ipsum {{ {{ dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -102,9 +114,12 @@ fn lex_err_unclosed_begin_block() { &err, "unclosed begin block", " + --> :1:13 | 1 | lorem ipsum {% {{ dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -118,9 +133,12 @@ fn lex_err_unexpected_end_tag_after_begin_block() { &err, "unexpected end block", " + --> :1:16 | 1 | lorem ipsum {{ %} dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -134,9 +152,12 @@ fn lex_err_unexpected_character() { &err, "unexpected character", " + --> :1:16 | 1 | lorem ipsum {{ ✨ }} dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -150,9 +171,12 @@ fn lex_err_unclosed_begin_comment() { &err, "unclosed begin comment", " + --> :1:13 | 1 | lorem ipsum {# {{ dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -166,9 +190,12 @@ fn lex_err_unexpected_end_tag_after_begin_comment() { &err, "unexpected end block", " + --> :1:16 | 1 | lorem ipsum {# %} dolor sit amet - | ^^ REASON + | ^^- + | + = reason: REASON ", ); } @@ -180,9 +207,12 @@ fn lex_err_undelimited_string_eof() { &err, "undelimited string", r#" + --> :1:10 | 1 | lorem {% "ipsum - | ^^^^^^ REASON + | ^^^^^^ + | + = reason: REASON "#, ); } @@ -196,9 +226,12 @@ fn lex_err_undelimited_string_newline() { &err, "undelimited string", r#" + --> :1:10 | 1 | lorem {% "ipsum - | ^^^^^^ REASON + | ^^^^^^ + | + = reason: REASON "#, ); } @@ -206,7 +239,7 @@ fn lex_err_undelimited_string_newline() { #[track_caller] fn assert_err(err: &Error, reason: &str, pretty: &str) { let display = format!("invalid syntax: {}", reason); - let display_alt = format!("invalid syntax{}", pretty.replace("REASON", reason)); + let display_alt = format!("invalid syntax\n{}", pretty.replace("REASON", reason)); assert_eq!(err.to_string(), display); assert_eq!(format!("{:#}", err), display_alt); } diff --git a/tests/render.rs b/tests/render.rs index 432b0a7..52d1dc6 100644 --- a/tests/render.rs +++ b/tests/render.rs @@ -149,9 +149,12 @@ fn render_inline_expr_custom_formatter_err() { &err, "expected list", " + --> :1:10 | 1 | lorem {{ ipsum | format_list }} - | ^^^^^^^^^^^^^^^^^^^ REASON + | ^^^^^^^^^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -182,9 +185,12 @@ fn render_inline_expr_err_unknown_filter_or_formatter() { &err, "unknown filter or formatter", " + --> :1:18 | 1 | lorem {{ ipsum | unknown }} - | ^^^^^^^ REASON + | ^^^^^^^ + | + = reason: REASON ", ); } @@ -202,9 +208,12 @@ fn render_inline_expr_err_unknown_filter_found_formatter() { &err, "expected filter, found formatter", " + --> :1:18 | 1 | lorem {{ ipsum | another | unknown }} - | ^^^^^^^ REASON + | ^^^^^^^ + | + = reason: REASON ", ); } @@ -220,9 +229,12 @@ fn render_inline_expr_err_unknown_filter() { &err, "unknown filter", " + --> :1:18 | 1 | lorem {{ ipsum | another | unknown }} - | ^^^^^^^ REASON + | ^^^^^^^ + | + = reason: REASON ", ); } @@ -238,9 +250,12 @@ fn render_inline_expr_err_unrenderable() { &err, "expression evaluated to unformattable type map", " + --> :1:10 | 1 | lorem {{ ipsum }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -256,9 +271,12 @@ fn render_inline_expr_err_cannot_index_into_none() { &err, "cannot index into none", " + --> :1:16 | 1 | lorem {{ ipsum.dolor }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -274,9 +292,12 @@ fn render_inline_expr_err_cannot_index_into_string() { &err, "cannot index into string", " + --> :1:16 | 1 | lorem {{ ipsum.dolor }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -292,9 +313,12 @@ fn render_inline_expr_err_cannot_index_list_with_string() { &err, "cannot index list with string", " + --> :1:16 | 1 | lorem {{ ipsum.dolor }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -310,9 +334,12 @@ fn render_inline_expr_err_not_found_in_map() { &err, "not found in map", " + --> :1:16 | 1 | lorem {{ ipsum.dolor }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -422,9 +449,12 @@ fn render_if_statement_err_cond_not_bool() { &err, "expected bool, but expression evaluated to map", " + --> :1:13 | 1 | lorem {% if ipsum.dolor %}{{ sit }}{% endif %} - | ^^^^^^^^^^^ REASON + | ^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -440,9 +470,12 @@ fn render_if_statement_err_cond_not_not_bool() { &err, "expected bool, but expression evaluated to map", " + --> :1:17 | 1 | lorem {% if not ipsum.dolor %}{{ sit }}{% endif %} - | ^^^^^^^^^^^ REASON + | ^^^^^^^^^^^ + | + = reason: REASON ", ); } @@ -521,9 +554,12 @@ fn render_for_statement_err_not_iterable() { &err, "expected iterable, but expression evaluated to bool", " + --> :1:23 | 1 | lorem {% for ipsum in dolor %}{{ ipsum }}{% endfor %} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -539,9 +575,12 @@ fn render_for_statement_err_list_with_two_vars() { &err, "cannot unpack list item into two variables", " + --> :1:14 | 1 | lorem {% for _, ipsum in dolor %}{{ ipsum }}{% endfor %} - | ^^^^^^^^ REASON + | ^^^^^^^^ + | + = reason: REASON ", ); } @@ -557,9 +596,12 @@ fn render_for_statement_err_map_with_one_var() { &err, "cannot unpack map item into one variable", " + --> :1:14 | 1 | lorem {% for ipsum in dolor %}{{ ipsum }}{% endfor %} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -575,9 +617,12 @@ fn render_for_statement_err_loop_var_scope() { &err, "not found in this scope", " + --> :1:49 | 1 | lorem {% for _, ipsum in dolor %}{% endfor %}{{ ipsum }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -603,9 +648,12 @@ fn render_with_statement_err_var_scope() { &err, "not found in this scope", " + --> :1:59 | 1 | lorem {% with ipsum as dolor %}{{ dolor }}{% endwith %}{{ dolor }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -672,9 +720,12 @@ fn render_include_statement_err_parent_template_scope() { &err, "not found in this scope", r#" + --> :1:4 | 1 | {{ ipsum.dolor }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON "#, ); } @@ -690,9 +741,12 @@ fn render_include_statement_err_unknown_template() { &err, "unknown template", r#" + --> :1:18 | 1 | lorem {% include "nested" %} sit - | ^^^^^^^^ REASON + | ^^^^^^^^ + | + = reason: REASON "#, ); } @@ -710,7 +764,7 @@ fn render_include_statement_err_maximum_depth() { .unwrap_err(); assert_eq!( err.to_string(), - "failed to render: reached maximum include depth (64)" + "render error: reached maximum include depth (64)" ); } @@ -760,9 +814,12 @@ fn render_to_writer_err_not_io() { &err, "not found in this scope", " + --> :1:10 | 1 | lorem {{ ipsum }} - | ^^^^^ REASON + | ^^^^^ + | + = reason: REASON ", ); } @@ -814,8 +871,8 @@ impl io::Write for Writer { #[track_caller] fn assert_err(err: &Error, reason: &str, pretty: &str) { - let display = format!("failed to render: {}", reason); - let display_alt = format!("failed to render{}", pretty.replace("REASON", reason)); + let display = format!("render error: {}", reason); + let display_alt = format!("render error\n{}", pretty.replace("REASON", reason)); assert_eq!(err.to_string(), display); assert_eq!(format!("{:#}", err), display_alt); } diff --git a/tests/to_value.rs b/tests/to_value.rs index b307ded..c2ab4bc 100644 --- a/tests/to_value.rs +++ b/tests/to_value.rs @@ -27,7 +27,7 @@ fn to_value_out_of_range_integral() { let err = to_value(u64::MAX).unwrap_err().to_string(); assert_eq!( err, - "failed to serialize value: out of range integral type conversion attempted" + "serialize error: out of range integral type conversion attempted" ); } @@ -183,7 +183,7 @@ fn to_value_map_key_not_string() { to_value(BTreeMap::from([(Some("a"), "b"), (Some("c"), "d")])) .unwrap_err() .to_string(), - "failed to serialize value: map key must be a string" + "serialize error: map key must be a string" ); }