2020-10-23 14:11:46 -04:00
|
|
|
use crate::error;
|
|
|
|
|
use crate::error::Result;
|
2020-10-26 12:58:32 -04:00
|
|
|
use crate::test_highlight::parse_highlight_test;
|
2020-10-21 12:37:24 -04:00
|
|
|
use lazy_static::lazy_static;
|
|
|
|
|
use regex::Regex;
|
2020-10-21 14:54:47 -04:00
|
|
|
use std::collections::hash_map::HashMap;
|
2020-10-21 12:56:11 -04:00
|
|
|
use std::fs;
|
2020-10-26 12:58:32 -04:00
|
|
|
use tree_sitter::{Language, Parser, Point};
|
2020-10-21 12:37:24 -04:00
|
|
|
|
|
|
|
|
// TODO: It would be cooler to do this with a comments query rather than with a regex
|
|
|
|
|
// directly.
|
|
|
|
|
lazy_static! {
|
2020-10-21 13:32:04 -04:00
|
|
|
static ref METADATA_REGEX: Regex = Regex::new(r#"(\w+): ([^\s,]+), (\d+), (\d+)"#).unwrap();
|
2020-10-21 12:37:24 -04:00
|
|
|
}
|
|
|
|
|
|
2020-10-21 14:54:47 -04:00
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
2020-10-21 12:37:24 -04:00
|
|
|
pub struct CaptureInfo {
|
|
|
|
|
pub name: String,
|
2020-10-21 14:54:47 -04:00
|
|
|
pub position: Point,
|
2020-10-21 12:37:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
|
|
|
struct Assertion {
|
|
|
|
|
position: Point,
|
2020-10-21 13:32:04 -04:00
|
|
|
capture_class: String,
|
2020-10-21 12:37:24 -04:00
|
|
|
capture_type: String,
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-21 13:32:04 -04:00
|
|
|
impl From<regex::Captures<'_>> for Assertion {
|
|
|
|
|
fn from(re: regex::Captures) -> Assertion {
|
|
|
|
|
Assertion {
|
|
|
|
|
capture_class: re.get(1).unwrap().as_str().to_string(),
|
|
|
|
|
capture_type: re.get(2).unwrap().as_str().to_string(),
|
|
|
|
|
position: Point {
|
|
|
|
|
row: re
|
|
|
|
|
.get(3)
|
|
|
|
|
.iter()
|
|
|
|
|
.flat_map(|m| m.as_str().parse::<usize>())
|
|
|
|
|
.next()
|
|
|
|
|
.unwrap(),
|
|
|
|
|
column: re
|
|
|
|
|
.get(4)
|
|
|
|
|
.iter()
|
|
|
|
|
.flat_map(|m| m.as_str().parse::<usize>())
|
|
|
|
|
.next()
|
|
|
|
|
.unwrap(),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-26 12:58:32 -04:00
|
|
|
pub fn assert_expected_captures(
|
|
|
|
|
infos: Vec<CaptureInfo>,
|
|
|
|
|
path: String,
|
|
|
|
|
parser: &mut Parser,
|
|
|
|
|
language: Language,
|
|
|
|
|
) -> Result<()> {
|
2020-10-21 12:56:11 -04:00
|
|
|
let contents = fs::read_to_string(path)?;
|
2020-10-26 12:58:32 -04:00
|
|
|
let _pairs = parse_highlight_test(parser, language, contents.as_bytes());
|
2020-10-21 13:32:04 -04:00
|
|
|
|
|
|
|
|
let assertions: Vec<Assertion> = METADATA_REGEX
|
|
|
|
|
.captures_iter(&contents)
|
|
|
|
|
.map(|c| Assertion::from(c))
|
|
|
|
|
.collect();
|
|
|
|
|
|
2020-10-21 14:54:47 -04:00
|
|
|
let per_position_index: HashMap<Point, &Assertion> =
|
|
|
|
|
assertions.iter().map(|a| (a.position, a)).collect();
|
2020-10-21 13:32:04 -04:00
|
|
|
|
2020-10-23 14:11:46 -04:00
|
|
|
for info in &infos {
|
|
|
|
|
if !per_position_index.contains_key(&info.position) {
|
2020-10-21 14:54:47 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
2020-10-23 14:11:46 -04:00
|
|
|
let found = per_position_index.get(&info.position).unwrap();
|
2020-10-21 14:54:47 -04:00
|
|
|
let joined = format!("{}.{}", found.capture_class, found.capture_type);
|
2020-10-23 14:11:46 -04:00
|
|
|
if joined != info.name && info.name != "name" {
|
2020-10-21 14:54:47 -04:00
|
|
|
Err(error::Error::new(format!(
|
|
|
|
|
"Assertion failed: at {}, found {}, expected {}",
|
2020-10-23 14:11:46 -04:00
|
|
|
info.position, info.name, joined
|
2020-10-21 14:54:47 -04:00
|
|
|
)))?
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-21 12:49:41 -04:00
|
|
|
Ok(())
|
|
|
|
|
}
|