use crate::{ast::Module, parse_module, Parse, ParserError};
use expect_test::expect_file;
use rslint_errors::{file::SimpleFiles, Emitter};
use std::fs;
use std::panic::catch_unwind;
use std::path::{Path, PathBuf};
#[test]
fn parser_smoke_test() {
let src = r#"
console.log("hello world");
"#;
assert!(parse_module(src, 0).ok().is_ok());
}
fn test_data_dir() -> PathBuf {
project_dir().join("rslint_parser/test_data")
}
fn try_parse(path: &str, text: &str) -> Parse<Module> {
let res = catch_unwind(|| parse_module(text, 0));
if res.is_err() {
panic!("Trying to parse `{}` caused infinite recursion", path);
};
res.unwrap()
}
#[test]
fn parser_tests() {
dir_tests(&test_data_dir(), &["inline/ok"], "rast", |text, path| {
let parse = try_parse(path.to_str().unwrap(), text);
let errors = parse.errors();
assert_errors_are_absent(errors, path);
format!("{:#?}", parse.syntax())
});
dir_tests(&test_data_dir(), &["inline/err"], "rast", |text, path| {
let parse = try_parse(path.to_str().unwrap(), text);
let errors = parse.errors();
assert_errors_are_present(errors, path);
let mut files = SimpleFiles::new();
files.add(
path.file_name().unwrap().to_string_lossy().to_string(),
text.to_string(),
);
let mut ret = format!("{:#?}", parse.syntax());
for diag in parse.errors() {
let mut write = rslint_errors::termcolor::Buffer::no_color();
let mut emitter = Emitter::new(&files);
emitter
.emit_with_writer(diag, &mut write)
.expect("failed to emit diagnostic");
ret.push_str(&format!(
"--\n{}",
std::str::from_utf8(write.as_slice()).expect("non utf8 in error buffer")
));
}
ret.push_str(&format!("--\n{}", text));
ret
});
}
fn dir_tests<F>(test_data_dir: &Path, paths: &[&str], outfile_extension: &str, f: F)
where
F: Fn(&str, &Path) -> String,
{
for (path, input_code) in collect_js_files(test_data_dir, paths) {
let actual = f(&input_code, &path);
let path = path.with_extension(outfile_extension);
expect_file![path].assert_eq(&actual)
}
}
pub fn project_dir() -> PathBuf {
let dir = env!("CARGO_MANIFEST_DIR");
PathBuf::from(dir).parent().unwrap().to_path_buf()
}
fn collect_js_files(root_dir: &Path, paths: &[&str]) -> Vec<(PathBuf, String)> {
paths
.iter()
.flat_map(|path| {
let path = root_dir.to_owned().join(path);
js_files_in_dir(&path).into_iter()
})
.map(|path| {
let text = fs::read_to_string(&path).expect("Could not read js file");
(path, text)
})
.collect()
}
fn js_files_in_dir(dir: &Path) -> Vec<PathBuf> {
let mut acc = Vec::new();
println!("{:?}", dir);
for file in fs::read_dir(&dir).unwrap() {
let file = file.unwrap();
let path = file.path();
if path.extension().unwrap_or_default() == "js" {
acc.push(path);
}
}
acc.sort();
acc
}
fn assert_errors_are_present(errors: &[ParserError], path: &Path) {
assert!(
!errors.is_empty(),
"There should be errors in the file {:?}",
path.display()
);
}
fn assert_errors_are_absent(errors: &[ParserError], path: &Path) {
assert!(
errors.is_empty(),
"There should be no errors in the file {:?}",
path.display(),
);
}