cli: Check queries when running tree-sitter test

This commit is contained in:
Max Brunsfeld 2019-10-18 14:42:52 -07:00
parent b73b31356d
commit e14e285a10
6 changed files with 69 additions and 20 deletions

View file

@ -52,7 +52,25 @@ impl Error {
impl<'a> From<QueryError> for Error {
fn from(error: QueryError) -> Self {
Error::new(format!("{:?}", error))
match error {
QueryError::Capture(row, c) => Error::new(format!(
"Query error on line {}: Invalid capture name {}",
row, c
)),
QueryError::Field(row, f) => Error::new(format!(
"Query error on line {}: Invalid field name {}",
row, f
)),
QueryError::NodeType(row, t) => Error::new(format!(
"Query error on line {}. Invalid node type {}",
row, t
)),
QueryError::Syntax(row, l) => Error::new(format!(
"Query error on line {}. Invalid syntax:\n{}",
row, l
)),
QueryError::Predicate(p) => Error::new(format!("Query error: {}", p)),
}
}
}

View file

@ -162,9 +162,15 @@ fn run() -> error::Result<()> {
let debug = matches.is_present("debug");
let debug_graph = matches.is_present("debug-graph");
let filter = matches.value_of("filter");
let corpus_path = current_dir.join("corpus");
if let Some(language) = loader.languages_at_path(&current_dir)?.first() {
test::run_tests_at_path(*language, &corpus_path, debug, debug_graph, filter)?;
test::run_tests_at_path(
*language,
&current_dir.join("corpus"),
debug,
debug_graph,
filter,
)?;
test::check_queries_at_path(*language, &current_dir.join("queries"))?;
} else {
eprintln!("No language found");
}

View file

@ -10,7 +10,7 @@ use std::fs;
use std::io::{self, Write};
use std::path::Path;
use std::str;
use tree_sitter::{Language, LogType, Parser};
use tree_sitter::{Language, LogType, Parser, Query};
lazy_static! {
static ref HEADER_REGEX: ByteRegex = ByteRegexBuilder::new(r"^===+\r?\n([^=]*)\r?\n===+\r?\n")
@ -98,6 +98,22 @@ pub fn run_tests_at_path(
}
}
pub fn check_queries_at_path(language: Language, path: &Path) -> Result<()> {
for entry in fs::read_dir(path)? {
let entry = entry?;
let hidden = entry.file_name().to_str().unwrap_or("").starts_with(".");
if !hidden {
let content = fs::read_to_string(entry.path()).map_err(Error::wrap(|| {
format!("Error reading query file {:?}", entry.file_name())
}))?;
Query::new(language, &content).map_err(Error::wrap(|| {
format!("Error in query file {:?}", entry.file_name())
}))?;
}
}
Ok(())
}
pub fn print_diff_key() {
println!(
"\n{} / {}",

View file

@ -17,6 +17,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, "(if_statement"),
Err(QueryError::Syntax(
1,
[
"(if_statement", //
" ^",
@ -27,6 +28,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, "; comment 1\n; comment 2\n (if_statement))"),
Err(QueryError::Syntax(
3,
[
" (if_statement))", //
" ^",
@ -40,6 +42,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, "(if_statement identifier)"),
Err(QueryError::Syntax(
1,
[
"(if_statement identifier)", //
" ^",
@ -50,6 +53,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, "(if_statement condition:)"),
Err(QueryError::Syntax(
1,
[
"(if_statement condition:)", //
" ^",
@ -62,6 +66,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, r#"(identifier) "h "#),
Err(QueryError::Syntax(
1,
[
r#"(identifier) "h "#, //
r#" ^"#,
@ -73,6 +78,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, r#"((identifier) ()"#),
Err(QueryError::Syntax(
1,
[
"((identifier) ()", //
" ^",
@ -83,6 +89,7 @@ fn test_query_errors_on_invalid_syntax() {
assert_eq!(
Query::new(language, r#"((identifier) @x (eq? @x a"#),
Err(QueryError::Syntax(
1,
[
r#"((identifier) @x (eq? @x a"#,
r#" ^"#,
@ -100,23 +107,23 @@ fn test_query_errors_on_invalid_symbols() {
assert_eq!(
Query::new(language, "(clas)"),
Err(QueryError::NodeType("clas".to_string()))
Err(QueryError::NodeType(1, "clas".to_string()))
);
assert_eq!(
Query::new(language, "(if_statement (arrayyyyy))"),
Err(QueryError::NodeType("arrayyyyy".to_string()))
Err(QueryError::NodeType(1, "arrayyyyy".to_string()))
);
assert_eq!(
Query::new(language, "(if_statement condition: (non_existent3))"),
Err(QueryError::NodeType("non_existent3".to_string()))
Err(QueryError::NodeType(1, "non_existent3".to_string()))
);
assert_eq!(
Query::new(language, "(if_statement condit: (identifier))"),
Err(QueryError::Field("condit".to_string()))
Err(QueryError::Field(1, "condit".to_string()))
);
assert_eq!(
Query::new(language, "(if_statement conditioning: (identifier))"),
Err(QueryError::Field("conditioning".to_string()))
Err(QueryError::Field(1, "conditioning".to_string()))
);
});
}
@ -140,7 +147,7 @@ fn test_query_errors_on_invalid_conditions() {
);
assert_eq!(
Query::new(language, "((identifier) @id (eq? @id @ok))"),
Err(QueryError::Capture("ok".to_string()))
Err(QueryError::Capture(1, "ok".to_string()))
);
});
}

View file

@ -118,10 +118,10 @@ pub struct QueryCapture<'a> {
#[derive(Debug, PartialEq, Eq)]
pub enum QueryError {
Syntax(String),
NodeType(String),
Field(String),
Capture(String),
Syntax(usize, String),
NodeType(usize, String),
Field(usize, String),
Capture(usize, String),
Predicate(String),
}
@ -812,7 +812,9 @@ impl Query {
if ptr.is_null() {
let offset = error_offset as usize;
let mut line_start = 0;
let mut row = 0;
let line_containing_error = source.split("\n").find_map(|line| {
row += 1;
let line_end = line_start + line.len() + 1;
if line_end > offset {
Some(line)
@ -836,13 +838,13 @@ impl Query {
.unwrap_or(source.len());
let name = suffix.split_at(end_offset).0.to_string();
match error_type {
ffi::TSQueryError_TSQueryErrorNodeType => Err(QueryError::NodeType(name)),
ffi::TSQueryError_TSQueryErrorField => Err(QueryError::Field(name)),
ffi::TSQueryError_TSQueryErrorCapture => Err(QueryError::Capture(name)),
_ => Err(QueryError::Syntax(message)),
ffi::TSQueryError_TSQueryErrorNodeType => Err(QueryError::NodeType(row, name)),
ffi::TSQueryError_TSQueryErrorField => Err(QueryError::Field(row, name)),
ffi::TSQueryError_TSQueryErrorCapture => Err(QueryError::Capture(row, name)),
_ => Err(QueryError::Syntax(row, message)),
}
} else {
Err(QueryError::Syntax(message))
Err(QueryError::Syntax(row, message))
};
}

View file

@ -485,7 +485,7 @@ static TSQueryError ts_query_parse_predicate(
// Parse the string content
const char *string_content = stream->input;
while (stream->next != '"') {
if (!stream_advance(stream)) {
if (stream->next == '\n' || !stream_advance(stream)) {
stream_reset(stream, string_content - 1);
return TSQueryErrorSyntax;
}