Skip to content

Commit 096721a

Browse files
committed
feat: improving error display
1 parent 57564fc commit 096721a

File tree

3 files changed

+39
-13
lines changed

3 files changed

+39
-13
lines changed

src/error.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ pub type Result<T> = std::result::Result<T, RenderError>;
55

66
#[derive(Error, Debug, PartialEq)]
77
pub enum RenderError {
8-
#[error("Syntax error inside command")]
9-
SyntaxError,
8+
#[error("Template syntax error: {0}")]
9+
SyntaxError(String),
1010
#[error("Template function call error")]
1111
FunctionError,
12-
#[error("Missing command type at `{0}`")]
12+
#[error("Missing command type at {0}")]
1313
MissingCommandType(String),
14-
#[error("Missing closing command tag at `{0}`")]
14+
#[error("Missing closing command tag at {0}")]
1515
MissingClosingTag(String),
1616
}
1717

1818
impl Into<JsValue> for RenderError {
1919
fn into(self) -> JsValue {
20-
self.to_string().into()
20+
js_sys::Error::new(&self.to_string()).into()
2121
}
2222
}

src/lib.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub struct ParsingData {
4545
}
4646

4747
#[wasm_bindgen]
48-
#[derive(Serialize, Deserialize, Debug)]
48+
#[derive(Serialize, Deserialize, Debug, Clone)]
4949
pub struct ParserConfig {
5050
opening_tag: String,
5151
closing_tag: String,
@@ -126,10 +126,10 @@ impl<'a> Parser<'a> {
126126
.content
127127
.split('\n')
128128
.take(d.line as usize)
129-
.map(|l| l.len()+1)
129+
.map(|l| l.len() + 1)
130130
.sum();
131131
let ch = d.ch - line_ch;
132-
let mut spaces: String = (0..ch-1).map(|_| ' ').collect();
132+
let mut spaces: String = (0..ch - 1).map(|_| ' ').collect();
133133
spaces += "^";
134134
let s = format!("line {} col {}:\n\n{}\n{}", d.line + 1, ch, line, spaces);
135135
s
@@ -283,6 +283,11 @@ impl<'a> Parser<'a> {
283283
parsing_data.ch += text.len();
284284
parsing_data.line += count_newlines(text);
285285
}
286+
if i.is_empty() {
287+
return Err(RenderError::MissingClosingTag(
288+
self.generate_backtrace(&mut parsing_data),
289+
));
290+
}
286291

287292
let (opening_whitespace, i) = self.parse_whitespace(i, &mut parsing_data)?;
288293
let (cmd_type, i) = self.parse_command_tag(i, &mut parsing_data)?;
@@ -300,7 +305,6 @@ impl<'a> Parser<'a> {
300305

301306
parsing_data.ch += content.len();
302307
parsing_data.line += count_newlines(content);
303-
304308
let command = Command {
305309
r#type: cmd_type,
306310
opening_whitespace,
@@ -407,7 +411,11 @@ impl Renderer {
407411
&JsValue::from(&fn_body).into(),
408412
) {
409413
Ok(f) => f,
410-
Err(_) => return Err(RenderError::SyntaxError),
414+
Err(e) => {
415+
let err = js_sys::Error::from(e);
416+
let msg = err.message().as_string().unwrap();
417+
return Err(RenderError::SyntaxError(msg));
418+
}
411419
};
412420
let async_fn = js_sys::Function::from(async_fn);
413421
let res = match async_fn.call1(&JsValue::NULL, context) {

tests/error.rs

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![cfg(target_arch = "wasm32")]
22

33
extern crate wasm_bindgen_test;
4-
use wasm_bindgen_test::*;
54
use wasm_bindgen::prelude::*;
5+
use wasm_bindgen_test::*;
66

77
use rusty_engine::{error::RenderError, Parser, ParserConfig, Renderer};
88

@@ -18,6 +18,16 @@ testtest <% test2
1818
let parser = Parser::new(content, &config);
1919
let tokens = parser.parse_tokens();
2020
assert_eq!(tokens, Err(RenderError::MissingClosingTag(err.into())));
21+
22+
let content = "\ntest\n\n<%";
23+
let err = r#"line 4 col 2:
24+
25+
<%
26+
^"#;
27+
28+
let parser = Parser::new(content, &config);
29+
let tokens = parser.parse_tokens();
30+
assert_eq!(tokens, Err(RenderError::MissingClosingTag(err.into())));
2131
}
2232

2333
#[wasm_bindgen_test]
@@ -39,8 +49,16 @@ test <% test %> test
3949
pub fn test_syntax_error() {
4050
let config = ParserConfig::new("<%".into(), "%>".into(), '\0', '*', '-', '_', "tR".into());
4151
let content = r#"test <%* / %> test"#;
52+
let err = "Invalid regular expression: missing /";
53+
54+
let renderer = Renderer::new(config.clone());
55+
let res = renderer.render_content(content, &JsValue::NULL);
56+
assert_eq!(res, Err(RenderError::SyntaxError(err.into())));
57+
58+
let content = r#"test <% console.log('\'test\''); %> test"#;
59+
let err = "missing ) after argument list";
4260

43-
let renderer = Renderer::new(config);
61+
let renderer = Renderer::new(config.clone());
4462
let res = renderer.render_content(content, &JsValue::NULL);
45-
assert_eq!(res, Err(RenderError::SyntaxError));
63+
assert_eq!(res, Err(RenderError::SyntaxError(err.into())));
4664
}

0 commit comments

Comments
 (0)