2020-10-26 14:27:33 -04:00
|
|
|
use crate::query_testing;
|
2021-06-09 12:32:22 -04:00
|
|
|
use anyhow::{Context, Result};
|
2021-05-28 14:15:05 -07:00
|
|
|
use std::{
|
|
|
|
|
fs,
|
|
|
|
|
io::{self, Write},
|
|
|
|
|
ops::Range,
|
|
|
|
|
path::Path,
|
2023-02-14 14:41:25 -08:00
|
|
|
time::Instant,
|
2021-05-28 14:15:05 -07:00
|
|
|
};
|
2023-02-14 14:41:25 -08:00
|
|
|
use tree_sitter::{Language, Parser, Point, Query, QueryCursor};
|
2019-09-11 14:44:49 -07:00
|
|
|
|
|
|
|
|
pub fn query_files_at_paths(
|
|
|
|
|
language: Language,
|
2020-07-14 15:04:39 -07:00
|
|
|
paths: Vec<String>,
|
2019-09-11 14:44:49 -07:00
|
|
|
query_path: &Path,
|
2019-09-18 14:22:55 -07:00
|
|
|
ordered_captures: bool,
|
2023-02-14 14:41:25 -08:00
|
|
|
byte_range: Option<Range<usize>>,
|
|
|
|
|
point_range: Option<Range<Point>>,
|
2020-10-21 12:37:24 -04:00
|
|
|
should_test: bool,
|
2023-02-14 14:41:25 -08:00
|
|
|
quiet: bool,
|
|
|
|
|
print_time: bool,
|
2019-09-11 14:44:49 -07:00
|
|
|
) -> Result<()> {
|
|
|
|
|
let stdout = io::stdout();
|
|
|
|
|
let mut stdout = stdout.lock();
|
|
|
|
|
|
2021-06-09 12:32:22 -04:00
|
|
|
let query_source = fs::read_to_string(query_path)
|
|
|
|
|
.with_context(|| format!("Error reading query file {:?}", query_path))?;
|
|
|
|
|
let query = Query::new(language, &query_source).with_context(|| "Query compilation failed")?;
|
2019-09-11 14:44:49 -07:00
|
|
|
|
2019-09-11 14:44:49 -07:00
|
|
|
let mut query_cursor = QueryCursor::new();
|
2023-02-14 14:41:25 -08:00
|
|
|
if let Some(range) = byte_range {
|
2021-05-28 14:15:05 -07:00
|
|
|
query_cursor.set_byte_range(range);
|
2020-07-12 20:45:17 +07:00
|
|
|
}
|
2023-02-14 14:41:25 -08:00
|
|
|
if let Some(range) = point_range {
|
|
|
|
|
query_cursor.set_point_range(range);
|
|
|
|
|
}
|
2019-09-11 14:44:49 -07:00
|
|
|
|
|
|
|
|
let mut parser = Parser::new();
|
2021-06-09 12:32:22 -04:00
|
|
|
parser.set_language(language)?;
|
2019-09-11 14:44:49 -07:00
|
|
|
|
|
|
|
|
for path in paths {
|
2020-10-21 12:37:24 -04:00
|
|
|
let mut results = Vec::new();
|
|
|
|
|
|
2020-07-14 15:04:39 -07:00
|
|
|
writeln!(&mut stdout, "{}", path)?;
|
2019-09-11 14:44:49 -07:00
|
|
|
|
2021-06-09 12:32:22 -04:00
|
|
|
let source_code =
|
|
|
|
|
fs::read(&path).with_context(|| format!("Error reading source file {:?}", path))?;
|
2019-09-11 14:44:49 -07:00
|
|
|
let tree = parser.parse(&source_code, None).unwrap();
|
|
|
|
|
|
2023-02-14 14:41:25 -08:00
|
|
|
let start = Instant::now();
|
2019-09-18 14:22:55 -07:00
|
|
|
if ordered_captures {
|
2019-10-03 12:45:58 -07:00
|
|
|
for (mat, capture_index) in
|
2021-05-23 15:12:24 -07:00
|
|
|
query_cursor.captures(&query, tree.root_node(), source_code.as_slice())
|
2019-10-03 12:45:58 -07:00
|
|
|
{
|
|
|
|
|
let capture = mat.captures[capture_index];
|
2020-10-21 12:37:24 -04:00
|
|
|
let capture_name = &query.capture_names()[capture.index as usize];
|
2023-02-14 14:41:25 -08:00
|
|
|
if !quiet {
|
|
|
|
|
writeln!(
|
|
|
|
|
&mut stdout,
|
|
|
|
|
" pattern: {:>2}, capture: {} - {}, start: {}, end: {}, text: `{}`",
|
|
|
|
|
mat.pattern_index,
|
|
|
|
|
capture.index,
|
|
|
|
|
capture_name,
|
|
|
|
|
capture.node.start_position(),
|
|
|
|
|
capture.node.end_position(),
|
|
|
|
|
capture.node.utf8_text(&source_code).unwrap_or("")
|
|
|
|
|
)?;
|
|
|
|
|
}
|
2020-10-26 14:27:33 -04:00
|
|
|
results.push(query_testing::CaptureInfo {
|
2020-10-21 12:37:24 -04:00
|
|
|
name: capture_name.to_string(),
|
2020-11-23 12:01:08 -05:00
|
|
|
start: capture.node.start_position(),
|
|
|
|
|
end: capture.node.end_position(),
|
2020-10-21 12:37:24 -04:00
|
|
|
});
|
2019-09-11 14:44:49 -07:00
|
|
|
}
|
2019-09-18 14:22:55 -07:00
|
|
|
} else {
|
2021-05-23 15:12:24 -07:00
|
|
|
for m in query_cursor.matches(&query, tree.root_node(), source_code.as_slice()) {
|
2023-02-14 14:41:25 -08:00
|
|
|
if !quiet {
|
|
|
|
|
writeln!(&mut stdout, " pattern: {}", m.pattern_index)?;
|
|
|
|
|
}
|
2019-10-03 12:45:58 -07:00
|
|
|
for capture in m.captures {
|
2020-01-15 17:08:31 -08:00
|
|
|
let start = capture.node.start_position();
|
|
|
|
|
let end = capture.node.end_position();
|
2020-10-21 12:37:24 -04:00
|
|
|
let capture_name = &query.capture_names()[capture.index as usize];
|
2023-02-14 14:41:25 -08:00
|
|
|
if !quiet {
|
|
|
|
|
if end.row == start.row {
|
|
|
|
|
writeln!(
|
|
|
|
|
&mut stdout,
|
|
|
|
|
" capture: {} - {}, start: {}, end: {}, text: `{}`",
|
|
|
|
|
capture.index,
|
|
|
|
|
capture_name,
|
|
|
|
|
start,
|
|
|
|
|
end,
|
|
|
|
|
capture.node.utf8_text(&source_code).unwrap_or("")
|
|
|
|
|
)?;
|
|
|
|
|
} else {
|
|
|
|
|
writeln!(
|
|
|
|
|
&mut stdout,
|
|
|
|
|
" capture: {}, start: {}, end: {}",
|
|
|
|
|
capture_name, start, end,
|
|
|
|
|
)?;
|
|
|
|
|
}
|
2020-01-15 17:08:31 -08:00
|
|
|
}
|
2020-10-26 14:27:33 -04:00
|
|
|
results.push(query_testing::CaptureInfo {
|
2020-10-21 12:37:24 -04:00
|
|
|
name: capture_name.to_string(),
|
2020-11-23 12:01:08 -05:00
|
|
|
start: capture.node.start_position(),
|
|
|
|
|
end: capture.node.end_position(),
|
2020-10-21 12:37:24 -04:00
|
|
|
});
|
2019-09-18 14:22:55 -07:00
|
|
|
}
|
|
|
|
|
}
|
2019-09-11 14:44:49 -07:00
|
|
|
}
|
2021-04-27 09:38:43 -04:00
|
|
|
if query_cursor.did_exceed_match_limit() {
|
|
|
|
|
writeln!(
|
|
|
|
|
&mut stdout,
|
|
|
|
|
" WARNING: Query exceeded maximum number of in-progress captures!"
|
|
|
|
|
)?;
|
|
|
|
|
}
|
2020-10-21 12:37:24 -04:00
|
|
|
if should_test {
|
2020-10-26 14:27:33 -04:00
|
|
|
query_testing::assert_expected_captures(results, path, &mut parser, language)?
|
2020-10-21 12:37:24 -04:00
|
|
|
}
|
2023-02-14 14:41:25 -08:00
|
|
|
if print_time {
|
|
|
|
|
writeln!(&mut stdout, "{:?}", start.elapsed())?;
|
|
|
|
|
}
|
2019-09-11 14:44:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|