Skip to content

Commit

Permalink
feat(template-compiler): better error message
Browse files Browse the repository at this point in the history
  • Loading branch information
Tidyzq committed Oct 24, 2023
1 parent 754ae3d commit 4bffcfe
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 28 deletions.
6 changes: 3 additions & 3 deletions glass-easel-template-compiler/src/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ impl TmplGroup {

/// Add a template into the group.
pub fn add_tmpl(&mut self, path: &str, tmpl_str: &str) -> Result<(), TmplParseError> {
let mut tmpl = parse_tmpl(tmpl_str)?;
let mut tmpl = parse_tmpl(tmpl_str, path)?;
tmpl.path = path.to_string();
if tmpl.get_inline_script_module_names().len() > 0 {
self.has_scripts = true;
Expand All @@ -260,7 +260,7 @@ impl TmplGroup {
}

/// Add a script segment into the group.
///
///
/// The `content` must be valid JavaScript file content.
/// `require` and `exports` can be visited in this JavaScript segment, similar to Node.js.
pub fn add_script(&mut self, path: &str, content: &str) -> Result<(), TmplParseError> {
Expand All @@ -270,7 +270,7 @@ impl TmplGroup {
}

/// Set extra runtime JavaScript code as a string.
///
///
/// The `content` must be valid JavaScript statements, ended by semicolon.
pub fn set_extra_runtime_script(&mut self, content: &str) {
self.extra_runtime_string = content.to_string();
Expand Down
19 changes: 15 additions & 4 deletions glass-easel-template-compiler/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct TmplParser;
/// Template parsing error object.
pub struct TmplParseError {
pub message: String,
pub filename: String,
pub start_pos: (usize, usize),
pub end_pos: (usize, usize),
}
Expand All @@ -24,8 +25,8 @@ impl fmt::Debug for TmplParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Template parsing error (from line {} column {} to line {} column {}) : {}",
self.start_pos.0, self.start_pos.1, self.end_pos.0, self.end_pos.1, self.message
"Template parsing error (at {}:{}:{}): {}",
self.filename, self.start_pos.0, self.start_pos.1, self.message
)
}
}
Expand All @@ -39,21 +40,30 @@ impl fmt::Display for TmplParseError {
impl std::error::Error for TmplParseError {}

/// Parse a template string, returning a `TmplTree` if success.
pub fn parse_tmpl(tmpl_str: &str) -> Result<TmplTree, TmplParseError> {
pub fn parse_tmpl(tmpl_str: &str, path: &str) -> Result<TmplTree, TmplParseError> {
let mut pairs = TmplParser::parse(Rule::main, tmpl_str).map_err(|e| {
use pest::error::*;
let (start_pos, end_pos) = match e.line_col {
LineColLocation::Pos(p) => (p, p),
LineColLocation::Span(start, end) => (start, end),
};
let (start_location, end_location) = match e.location {
InputLocation::Pos(p) => (p, p),
InputLocation::Span(p) => p,
};
let message = match e.variant {
ErrorVariant::ParsingError {
positives: _,
negatives: _,
} => String::from("Unexpected character"),
} => {
let mut message = String::from("Unexpected character ");
message.push_str(&tmpl_str[start_location..end_location+1]);
message
},
ErrorVariant::CustomError { message: msg } => msg,
};
TmplParseError {
filename: String::from(path),
message,
start_pos,
end_pos,
Expand Down Expand Up @@ -1008,6 +1018,7 @@ pub fn parse_tmpl(tmpl_str: &str) -> Result<TmplTree, TmplParseError> {
if let Some(pair) = segment.peek() {
let span = pair.as_span();
return Err(TmplParseError {
filename: String::from(tree.path),
message: String::from("Unexpected segment"),
start_pos: span.start_pos().line_col(),
end_pos: span.end_pos().line_col(),
Expand Down
12 changes: 6 additions & 6 deletions glass-easel-template-compiler/tests/directive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,46 @@ fn lonely_if() {
const SRC: &str = r#"<b wx:if="{{a}}">{{a}}<b wx:if="{{!a}}">{{a}}</b></b>"#;
const GEN: &str =
r#"<block wx:if="{{a}}"><b>{{a}}<block wx:if="{{!a}}"><b>{{a}}</b></block></b></block>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn if_else() {
const SRC: &str = r#"<b wx:if="{{a}}">1</b><b wx:else>2</b>"#;
const GEN: &str = r#"<block wx:if="{{a}}"><b>1</b></block><block wx:else><b>2</b></block>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn if_elif_else() {
const SRC: &str = r#"<b wx:if="{{a}}">1</b><b wx:elif="{{a + 1}}">2</b><b wx:else>3</b>"#;
const GEN: &str = r#"<block wx:if="{{a}}"><b>1</b></block><block wx:elif="{{a+1}}"><b>2</b></block><block wx:else><b>3</b></block>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn for_array() {
const SRC: &str = r#"<b wx:for="{{list}}" wx:key="v" a="{{index}}">{{item.v}}</b>"#;
const GEN: &str = r#"<block wx:for="{{list}}" wx:for-item="$0" wx:for-index="$1" wx:key="v"><b a="{{$1}}">{{X($0).v}}</b></block>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn for_object() {
const SRC: &str = r#"<b wx:for="{{list}}" wx:key="*this" a="{{index}}">{{item}}</b>"#;
const GEN: &str = r#"<block wx:for="{{list}}" wx:for-item="$0" wx:for-index="$1" wx:key="*this"><b a="{{$1}}">{{$0}}</b></block>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn for_string() {
const SRC: &str = r#"<b wx:for="abc" a="{{index}}">{{item}}</b>"#;
const GEN: &str = r#"<block wx:for="abc" wx:for-item="$0" wx:for-index="$1"><b a="{{$1}}">{{$0}}</b></block>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}
20 changes: 10 additions & 10 deletions glass-easel-template-compiler/tests/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,47 @@ use glass_easel_template_compiler::*;
fn basic_eval() {
const SRC: &str = r#"<b a="{{ "" }}" />"#;
const GEN: &str = r#"<b a="{{""}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn member() {
const SRC: &str = r#"<b a="{{ a.a2 + b[4 + 1 - 5] + {c1: true}['c1'] + [null, '2'][1] }}" />"#;
const GEN: &str = r#"<b a="{{X(a).a2+X(b)[4+1-5]+X({c1:true})["c1"]+X([null,"2"])[1]}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn unary() {
const SRC: &str = r#"<b a="{{ - a + - 2 + + 3 + !!b }}" />"#;
const GEN: &str = r#"<b a="{{-a+-2++3+!!b}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn number_plus() {
const SRC: &str = r#"<b a="{{ a - 2 * b + 3 }}" />"#;
const GEN: &str = r#"<b a="{{a-2*b+3}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn string_plus() {
const SRC: &str = r#"<b a="{{ a + (b + 2.1) }}" />"#;
const GEN: &str = r#"<b a="{{a+(b+2.1)}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn multiply() {
const SRC: &str = r#"<b a="{{ a % '2' * (b / 4) }}" />"#;
const GEN: &str = r#"<b a="{{a%"2"*(b/4)}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

Expand All @@ -53,30 +53,30 @@ fn comparison() {
const SRC: &str = r#"<b a="{{ a > b ? true : false }} {{ a >= b ? true : false }} {{ c < d }} {{ c <= d }}" />"#;
const GEN: &str =
r#"<b a="{{Y(a>b?true:false)+" "+Y(a>=b?true:false)+" "+Y(c<d)+" "+Y(c<=d)}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn equality() {
const SRC: &str = r#"<b a="{{ a == b }} {{ a === b }} {{ a != b }} {{ a !== b }}" />"#;
const GEN: &str = r#"<b a="{{Y(a==b)+" "+Y(a===b)+" "+Y(a!=b)+" "+Y(a!==b)}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn logic() {
const SRC: &str = r#"<b a="{{a || b && c || d}}" />"#;
const GEN: &str = r#"<b a="{{a||b&&c||d}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}

#[test]
fn condition() {
const SRC: &str = r#"<b a="{{a ? b : c ? d : e}}" />"#;
const GEN: &str = r#"<b a="{{a?b:c?d:e}}"></b>"#;
let tree = parse_tmpl(SRC).unwrap();
let tree = parse_tmpl(SRC, r#""#).unwrap();
assert_eq!(tree.to_string(), GEN);
}
12 changes: 7 additions & 5 deletions glass-easel-template-compiler/tests/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use glass_easel_template_compiler::*;
fn basic_parsing() {
let tree = parse_tmpl(
r#" <!-- comment --> <div attr1='value 1' attr2=value&nbsp;2 > &lt;abc&gt; </div> def "#,
r#""#,
)
.unwrap();
assert_eq!(
Expand All @@ -16,6 +17,7 @@ fn basic_parsing() {
fn basic_entities_parsing() {
let tree = parse_tmpl(
r#"<div> &lt; &#xA9; &#169; </div>"#,
r#""#,
)
.unwrap();
assert_eq!(
Expand All @@ -27,7 +29,7 @@ fn basic_entities_parsing() {
#[test]
fn basic_expr_parsing() {
let tree =
parse_tmpl(r#"<div attr=" {{ (a + 1).b }} "> {{ c - ( d + e ) * 3 }} </div>"#).unwrap();
parse_tmpl(r#"<div attr=" {{ (a + 1).b }} "> {{ c - ( d + e ) * 3 }} </div>"#, r#""#).unwrap();
assert_eq!(
tree.to_string(),
r#"<div attr="{{" "+Y(X(a+1).b)+" "}}">{{" "+Y(c-(d+e)*3)+" "}}</div>"#
Expand All @@ -37,7 +39,7 @@ fn basic_expr_parsing() {
#[test]
fn basic_keywords_parsing() {
let tree =
parse_tmpl(r#"<div attr="{{ true }}">{{ truetrue }}</div>"#).unwrap();
parse_tmpl(r#"<div attr="{{ true }}">{{ truetrue }}</div>"#, r#""#).unwrap();
assert_eq!(
tree.to_string(),
r#"<div attr="{{true}}">{{truetrue}}</div>"#
Expand All @@ -46,7 +48,7 @@ fn basic_keywords_parsing() {

#[test]
fn basic_block_parsing() {
let tree = parse_tmpl(r#"<div wx:if="{{v}}" wx:for="{{list}}" wx:for-item="v" wx:for-index="i" wx:key="k">{{i}}</div>"#).unwrap();
let tree = parse_tmpl(r#"<div wx:if="{{v}}" wx:for="{{list}}" wx:for-item="v" wx:for-index="i" wx:key="k">{{i}}</div>"#, r#""#).unwrap();
assert_eq!(
tree.to_string(),
r#"<block wx:for="{{list}}" wx:for-item="$0" wx:for-index="$1" wx:key="k"><block wx:if="{{$0}}"><div>{{$1}}</div></block></block>"#
Expand All @@ -56,7 +58,7 @@ fn basic_block_parsing() {
#[test]
fn basic_sub_template_parsing() {
let tree =
parse_tmpl(r#"<div><template is="sub" /></div> <template name="sub"><view wx:for="{{a}}">{{item}}</view></template>"#)
parse_tmpl(r#"<div><template is="sub" /></div> <template name="sub"><view wx:for="{{a}}">{{item}}</view></template>"#, r#""#)
.unwrap();
assert_eq!(
tree.to_string(),
Expand All @@ -66,7 +68,7 @@ fn basic_sub_template_parsing() {

#[test]
fn generic() {
let tree = parse_tmpl(r#"<element wx:if="{{true}}" generic:g="g"></element>"#).unwrap();
let tree = parse_tmpl(r#"<element wx:if="{{true}}" generic:g="g"></element>"#, r#""#).unwrap();
assert_eq!(
tree.to_string(),
r#"<block wx:if="{{true}}"><element generic:g=g></element></block>"#
Expand Down

0 comments on commit 4bffcfe

Please sign in to comment.