rust: Create readable messages for query syntax errors
This commit is contained in:
parent
a45dc67390
commit
324c259cbb
2 changed files with 65 additions and 11 deletions
|
|
@ -16,37 +16,73 @@ fn test_query_errors_on_invalid_syntax() {
|
|||
// Mismatched parens
|
||||
assert_eq!(
|
||||
Query::new(language, "(if_statement"),
|
||||
Err(QueryError::Syntax(13))
|
||||
Err(QueryError::Syntax("Unexpected EOF".to_string()))
|
||||
);
|
||||
assert_eq!(
|
||||
Query::new(language, "(if_statement))"),
|
||||
Err(QueryError::Syntax(14))
|
||||
Query::new(language, "; comment 1\n; comment 2\n (if_statement))"),
|
||||
Err(QueryError::Syntax(
|
||||
[
|
||||
" (if_statement))", //
|
||||
" ^",
|
||||
]
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
|
||||
// Return an error at the *beginning* of a bare identifier not followed a colon.
|
||||
// If there's a colon but no pattern, return an error at the end of the colon.
|
||||
assert_eq!(
|
||||
Query::new(language, "(if_statement identifier)"),
|
||||
Err(QueryError::Syntax(14))
|
||||
Err(QueryError::Syntax(
|
||||
[
|
||||
"(if_statement identifier)", //
|
||||
" ^",
|
||||
]
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
Query::new(language, "(if_statement condition:)"),
|
||||
Err(QueryError::Syntax(24))
|
||||
Err(QueryError::Syntax(
|
||||
[
|
||||
"(if_statement condition:)", //
|
||||
" ^",
|
||||
]
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
|
||||
// Return an error at the beginning of an unterminated string.
|
||||
assert_eq!(
|
||||
Query::new(language, r#"(identifier) "h "#),
|
||||
Err(QueryError::Syntax(13))
|
||||
Err(QueryError::Syntax(
|
||||
[
|
||||
r#"(identifier) "h "#, //
|
||||
r#" ^"#,
|
||||
]
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Query::new(language, r#"((identifier) ()"#),
|
||||
Err(QueryError::Syntax(16))
|
||||
Err(QueryError::Syntax(
|
||||
[
|
||||
"((identifier) ()", //
|
||||
" ^",
|
||||
]
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
Query::new(language, r#"((identifier) @x (eq? @x a"#),
|
||||
Err(QueryError::Syntax(26))
|
||||
Err(QueryError::Syntax(
|
||||
[
|
||||
r#"((identifier) @x (eq? @x a"#,
|
||||
r#" ^"#,
|
||||
]
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ pub struct QueryCapture<'a> {
|
|||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum QueryError {
|
||||
Syntax(usize),
|
||||
Syntax(String),
|
||||
NodeType(String),
|
||||
Field(String),
|
||||
Capture(String),
|
||||
|
|
@ -997,6 +997,24 @@ impl Query {
|
|||
// On failure, build an error based on the error code and offset.
|
||||
if ptr.is_null() {
|
||||
let offset = error_offset as usize;
|
||||
let mut line_start = 0;
|
||||
let line_containing_error = source.split("\n").find_map(|line| {
|
||||
let line_end = line_start + line.len() + 1;
|
||||
if line_end > offset {
|
||||
Some(line)
|
||||
} else {
|
||||
line_start = line_end;
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let message = if let Some(line) = line_containing_error {
|
||||
line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^"
|
||||
} else {
|
||||
"Unexpected EOF".to_string()
|
||||
};
|
||||
|
||||
// if line_containing_error
|
||||
return if error_type != ffi::TSQueryError_TSQueryErrorSyntax {
|
||||
let suffix = source.split_at(offset).1;
|
||||
let end_offset = suffix
|
||||
|
|
@ -1007,10 +1025,10 @@ impl Query {
|
|||
ffi::TSQueryError_TSQueryErrorNodeType => Err(QueryError::NodeType(name)),
|
||||
ffi::TSQueryError_TSQueryErrorField => Err(QueryError::Field(name)),
|
||||
ffi::TSQueryError_TSQueryErrorCapture => Err(QueryError::Capture(name)),
|
||||
_ => Err(QueryError::Syntax(offset)),
|
||||
_ => Err(QueryError::Syntax(message)),
|
||||
}
|
||||
} else {
|
||||
Err(QueryError::Syntax(offset))
|
||||
Err(QueryError::Syntax(message))
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue