diff --git a/cli/src/main.rs b/cli/src/main.rs index 2e55c2fb..7594ce27 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -95,7 +95,8 @@ fn run() -> error::Result<()> { .takes_value(true), ) .arg(Arg::with_name("scope").long("scope").takes_value(true)) - .arg(Arg::with_name("captures").long("captures").short("c")), + .arg(Arg::with_name("captures").long("captures").short("c")) + .arg(Arg::with_name("test").long("test")), ) .subcommand( SubCommand::with_name("tags") @@ -289,7 +290,15 @@ fn run() -> error::Result<()> { let r: Vec<&str> = br.split(":").collect(); (r[0].parse().unwrap(), r[1].parse().unwrap()) }); - query::query_files_at_paths(language, paths, query_path, ordered_captures, range)?; + let should_test = matches.is_present("test"); + query::query_files_at_paths( + language, + paths, + query_path, + ordered_captures, + range, + should_test, + )?; } else if let Some(matches) = matches.subcommand_matches("tags") { loader.find_all_languages(&config.parser_directories)?; let paths = collect_paths(matches.value_of("paths-file"), matches.values_of("paths"))?; diff --git a/cli/src/query.rs b/cli/src/query.rs index e71e6254..d2aefc7f 100644 --- a/cli/src/query.rs +++ b/cli/src/query.rs @@ -4,12 +4,17 @@ use std::io::{self, Write}; use std::path::Path; use tree_sitter::{Language, Node, Parser, Query, QueryCursor}; +mod assert; + +use assert::CaptureInfo; + pub fn query_files_at_paths( language: Language, paths: Vec, query_path: &Path, ordered_captures: bool, range: Option<(usize, usize)>, + should_test: bool, ) -> Result<()> { let stdout = io::stdout(); let mut stdout = stdout.lock(); @@ -29,6 +34,8 @@ pub fn query_files_at_paths( parser.set_language(language).map_err(|e| e.to_string())?; for path in paths { + let mut results = Vec::new(); + writeln!(&mut stdout, "{}", path)?; let source_code = fs::read(&path).map_err(Error::wrap(|| { @@ -42,14 +49,18 @@ pub fn query_files_at_paths( query_cursor.captures(&query, tree.root_node(), text_callback) { let capture = mat.captures[capture_index]; + let capture_name = &query.capture_names()[capture.index as usize]; writeln!( &mut stdout, " pattern: {}, capture: {}, row: {}, text: {:?}", mat.pattern_index, - &query.capture_names()[capture.index as usize], + capture_name, capture.node.start_position().row, capture.node.utf8_text(&source_code).unwrap_or("") )?; + results.push(CaptureInfo { + name: capture_name.to_string(), + }); } } else { for m in query_cursor.matches(&query, tree.root_node(), text_callback) { @@ -57,11 +68,12 @@ pub fn query_files_at_paths( for capture in m.captures { let start = capture.node.start_position(); let end = capture.node.end_position(); + let capture_name = &query.capture_names()[capture.index as usize]; if end.row == start.row { writeln!( &mut stdout, " capture: {}, start: {}, text: {:?}", - &query.capture_names()[capture.index as usize], + capture_name, start, capture.node.utf8_text(&source_code).unwrap_or("") )?; @@ -69,14 +81,18 @@ pub fn query_files_at_paths( writeln!( &mut stdout, " capture: {}, start: {}, end: {}", - &query.capture_names()[capture.index as usize], - start, - end, + capture_name, start, end, )?; } + results.push(CaptureInfo { + name: capture_name.to_string(), + }); } } } + if should_test { + assert::assert_expected_captures(results, path); + } } Ok(()) diff --git a/cli/src/query/assert.rs b/cli/src/query/assert.rs new file mode 100644 index 00000000..5fb7e1d6 --- /dev/null +++ b/cli/src/query/assert.rs @@ -0,0 +1,23 @@ +use lazy_static::lazy_static; +use regex::Regex; +use tree_sitter::Point; + +// TODO: It would be cooler to do this with a comments query rather than with a regex +// directly. +lazy_static! { + static ref METADATA_PAIR_REGEX: Regex = Regex::new(r#"(\w+): ([^\s,]+)"#).unwrap(); + static ref NUMBER_REGEX: Regex = Regex::new(r#"\d+"#).unwrap(); +} + +pub struct CaptureInfo { + pub name: String, +} + +#[derive(Debug, Eq, PartialEq)] +struct Assertion { + position: Point, + line_numbers: Vec, + capture_type: String, +} + +pub fn assert_expected_captures(_captures: Vec, _path: String) {}