Skip to content

Commit 92e30ed

Browse files
committed
Add regular expression to extract error position from liquid
Signed-off-by: Ryan Bottriell <[email protected]>
1 parent 21da121 commit 92e30ed

File tree

6 files changed

+85
-6
lines changed

6 files changed

+85
-6
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/spk-schema/crates/liquid/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ version = "0.36.0"
88
migration-to-components = ["spk-schema-foundation/migration-to-components"]
99

1010
[dependencies]
11+
lazy_static = "1.4"
1112
liquid = "0.26.0"
1213
liquid-core = "0.26.0"
14+
format_serde_error = {version = "0.3", default_features = false, features = ["colored"]}
1315
regex = "1.6.0"
1416
serde = "1.0"
1517
serde_json = "1.0"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use std::error::Error;
2+
3+
use lazy_static::lazy_static;
4+
use regex::Regex;
5+
6+
#[cfg(test)]
7+
#[path = "./error_test.rs"]
8+
mod error_test;
9+
10+
#[derive(Debug)]
11+
struct ParsedError {
12+
message: String,
13+
}
14+
15+
impl std::fmt::Display for ParsedError {
16+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17+
f.write_str(&self.message)
18+
}
19+
}
20+
21+
impl Error for ParsedError {}
22+
23+
pub fn to_error_types(err: liquid::Error) -> format_serde_error::ErrorTypes {
24+
lazy_static! {
25+
static ref RE: Regex = Regex::new(r"(?ms)liquid: --> (\d+):(\d+)\n.*^\s+= (.*)")
26+
.expect("a valid regular expression");
27+
}
28+
let mut message = err.to_string();
29+
let mut line = Option::<usize>::None;
30+
let mut column = Option::<usize>::None;
31+
if let Some(m) = RE.captures(&message) {
32+
line = m.get(1).and_then(|line| line.as_str().parse().ok());
33+
column = m
34+
.get(2)
35+
.and_then(|column| column.as_str().parse().ok())
36+
// format_serde_error appears to use 0-based index for columns
37+
// whereas the liquid crates uses a 1-based index
38+
.map(|col: usize| col - 1);
39+
message = m
40+
.get(3)
41+
.map(|msg| msg.as_str())
42+
.unwrap_or("Invalid Template")
43+
.trim()
44+
.to_string();
45+
}
46+
let error = Box::new(ParsedError { message });
47+
format_serde_error::ErrorTypes::Custom {
48+
error,
49+
line,
50+
column,
51+
}
52+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use rstest::rstest;
2+
use serde_json::json;
3+
4+
#[rstest]
5+
fn test_error_position_extraction() {
6+
// ensure that the source position of an error can be
7+
// properly extracted and used for the returned serde_format_error
8+
9+
format_serde_error::never_color();
10+
static TPL: &str = r#"{% default = data | replace ''%}"#;
11+
let err =
12+
crate::render_template(TPL, &json!({})).expect_err("expected template render to fail");
13+
let expected = r#"
14+
1 | {% default = data | replace ''%}
15+
| ^ unexpected "="; expected Identifier
16+
"#;
17+
let message = err.to_string();
18+
assert_eq!(message, expected);
19+
}

crates/spk-schema/crates/liquid/src/lib.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
// https://github.com/imageworks/spk
44
//! Defines the default configuration for processing spec file templates in spk
55
6+
mod error;
67
mod filter_compare_version;
78
mod filter_parse_version;
89
mod filter_replace_regex;
910
mod tag_default;
1011

11-
pub use liquid::Error;
12+
pub use format_serde_error::SerdeError as Error;
1213

1314
/// Build the default template parser for spk
1415
///
@@ -27,13 +28,16 @@ pub fn default_parser() -> liquid::Parser {
2728
}
2829

2930
/// Render a template with the default configuration
30-
pub fn render_template<T, D>(tpl: T, data: &D) -> Result<String, liquid::Error>
31+
pub fn render_template<T, D>(tpl: T, data: &D) -> Result<String, Error>
3132
where
3233
T: AsRef<str>,
3334
D: serde::Serialize,
3435
{
36+
let tpl = tpl.as_ref();
37+
let map_err =
38+
|err| format_serde_error::SerdeError::new(tpl.to_string(), error::to_error_types(err));
3539
let parser = default_parser();
36-
let template = parser.parse(tpl.as_ref())?;
37-
let globals = liquid::to_object(data)?;
38-
template.render(&globals)
40+
let template = parser.parse(tpl).map_err(map_err)?;
41+
let globals = liquid::to_object(data).map_err(map_err)?;
42+
template.render(&globals).map_err(map_err)
3943
}

crates/spk-schema/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub enum Error {
4646
#[error(transparent)]
4747
InvalidYaml(#[from] format_serde_error::SerdeError),
4848
#[error(transparent)]
49-
InvalidTemplate(spk_schema_liquid::Error),
49+
InvalidTemplate(format_serde_error::SerdeError),
5050
}
5151

5252
impl Error {

0 commit comments

Comments
 (0)