2018-07-30 12:25:52 +00:00
|
|
|
use std::{
|
2018-10-15 21:44:23 +00:00
|
|
|
fmt::Write,
|
2020-02-01 20:25:01 +00:00
|
|
|
path::{Component, Path, PathBuf},
|
2018-07-30 12:25:52 +00:00
|
|
|
};
|
2018-01-07 11:56:08 +00:00
|
|
|
|
2019-07-04 20:05:17 +00:00
|
|
|
use test_utils::{collect_tests, dir_tests, project_dir, read_text};
|
2018-08-25 09:10:35 +00:00
|
|
|
|
2020-03-13 02:29:44 +00:00
|
|
|
use crate::{fuzz, tokenize, SourceFile, SyntaxError, TextRange, TextUnit, Token};
|
2019-07-24 09:38:21 +00:00
|
|
|
|
2018-08-11 07:03:03 +00:00
|
|
|
#[test]
|
|
|
|
fn lexer_tests() {
|
2020-02-01 20:25:01 +00:00
|
|
|
// FIXME:
|
|
|
|
// * Add tests for unicode escapes in byte-character and [raw]-byte-string literals
|
|
|
|
// * Add tests for unescape errors
|
|
|
|
|
|
|
|
dir_tests(&test_data_dir(), &["lexer/ok"], |text, path| {
|
|
|
|
let (tokens, errors) = tokenize(text);
|
|
|
|
assert_errors_are_absent(&errors, path);
|
|
|
|
dump_tokens_and_errors(&tokens, &errors, text)
|
|
|
|
});
|
|
|
|
dir_tests(&test_data_dir(), &["lexer/err"], |text, path| {
|
|
|
|
let (tokens, errors) = tokenize(text);
|
|
|
|
assert_errors_are_present(&errors, path);
|
|
|
|
dump_tokens_and_errors(&tokens, &errors, text)
|
|
|
|
});
|
2018-08-11 07:03:03 +00:00
|
|
|
}
|
|
|
|
|
2019-09-09 11:52:31 +00:00
|
|
|
#[test]
|
|
|
|
fn parse_smoke_test() {
|
|
|
|
let code = r##"
|
|
|
|
fn main() {
|
|
|
|
println!("Hello, world!")
|
|
|
|
}
|
|
|
|
"##;
|
|
|
|
|
|
|
|
let parse = SourceFile::parse(code);
|
2020-03-13 11:09:14 +00:00
|
|
|
// eprintln!("{:#?}", parse.syntax_node());
|
2019-09-09 11:52:31 +00:00
|
|
|
assert!(parse.ok().is_ok());
|
|
|
|
}
|
|
|
|
|
2018-09-10 18:14:09 +00:00
|
|
|
#[test]
|
|
|
|
fn parser_tests() {
|
2019-02-08 11:49:43 +00:00
|
|
|
dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| {
|
2019-05-28 14:34:28 +00:00
|
|
|
let parse = SourceFile::parse(text);
|
2019-07-12 16:41:13 +00:00
|
|
|
let errors = parse.errors();
|
2020-02-01 20:25:01 +00:00
|
|
|
assert_errors_are_absent(&errors, path);
|
2019-05-28 13:59:22 +00:00
|
|
|
parse.debug_dump()
|
2019-02-08 11:49:43 +00:00
|
|
|
});
|
|
|
|
dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], |text, path| {
|
2019-05-28 14:34:28 +00:00
|
|
|
let parse = SourceFile::parse(text);
|
2019-07-12 16:41:13 +00:00
|
|
|
let errors = parse.errors();
|
2020-02-01 20:25:01 +00:00
|
|
|
assert_errors_are_present(&errors, path);
|
2019-05-28 13:59:22 +00:00
|
|
|
parse.debug_dump()
|
2019-02-08 11:49:43 +00:00
|
|
|
});
|
2018-09-10 18:14:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parser_fuzz_tests() {
|
2018-12-23 11:05:54 +00:00
|
|
|
for (_, text) in collect_tests(&test_data_dir(), &["parser/fuzz-failures"]) {
|
2019-03-21 17:05:12 +00:00
|
|
|
fuzz::check_parser(&text)
|
2018-09-10 18:14:09 +00:00
|
|
|
}
|
2018-08-25 11:45:17 +00:00
|
|
|
}
|
|
|
|
|
2019-03-21 17:06:48 +00:00
|
|
|
#[test]
|
|
|
|
fn reparse_fuzz_tests() {
|
|
|
|
for (_, text) in collect_tests(&test_data_dir(), &["reparse/fuzz-failures"]) {
|
|
|
|
let check = fuzz::CheckReparse::from_data(text.as_bytes()).unwrap();
|
|
|
|
println!("{:?}", check);
|
|
|
|
check.run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-11 14:15:20 +00:00
|
|
|
/// Test that Rust-analyzer can parse and validate the rust-analyzer
|
2019-03-23 07:53:48 +00:00
|
|
|
/// FIXME: Use this as a benchmark
|
2018-12-09 19:19:23 +00:00
|
|
|
#[test]
|
|
|
|
fn self_hosting_parsing() {
|
2018-12-19 21:19:32 +00:00
|
|
|
use std::ffi::OsStr;
|
|
|
|
let dir = project_dir().join("crates");
|
|
|
|
let mut count = 0;
|
2018-12-09 19:19:23 +00:00
|
|
|
for entry in walkdir::WalkDir::new(dir)
|
|
|
|
.into_iter()
|
|
|
|
.filter_entry(|entry| {
|
2018-12-21 22:44:31 +00:00
|
|
|
!entry.path().components().any(|component| {
|
2020-02-01 20:25:01 +00:00
|
|
|
// Get all files which are not in the crates/ra_syntax/test_data folder
|
2019-07-24 09:38:21 +00:00
|
|
|
component == Component::Normal(OsStr::new("test_data"))
|
2018-12-21 22:44:31 +00:00
|
|
|
})
|
2018-12-09 19:19:23 +00:00
|
|
|
})
|
|
|
|
.map(|e| e.unwrap())
|
|
|
|
.filter(|entry| {
|
|
|
|
// Get all `.rs ` files
|
2018-12-19 21:19:32 +00:00
|
|
|
!entry.path().is_dir() && (entry.path().extension() == Some(OsStr::new("rs")))
|
2018-12-09 19:19:23 +00:00
|
|
|
})
|
|
|
|
{
|
2018-12-19 21:19:32 +00:00
|
|
|
count += 1;
|
2018-12-09 19:19:23 +00:00
|
|
|
let text = read_text(entry.path());
|
2019-09-09 11:52:31 +00:00
|
|
|
if let Err(errors) = SourceFile::parse(&text).ok() {
|
|
|
|
panic!("Parsing errors:\n{:?}\n{}\n", errors, entry.path().display());
|
|
|
|
}
|
2018-12-09 19:19:23 +00:00
|
|
|
}
|
2018-12-19 21:19:32 +00:00
|
|
|
assert!(
|
|
|
|
count > 30,
|
|
|
|
"self_hosting_parsing found too few files - is it running in the right directory?"
|
|
|
|
)
|
2018-12-09 19:19:23 +00:00
|
|
|
}
|
2018-01-07 11:56:08 +00:00
|
|
|
|
|
|
|
fn test_data_dir() -> PathBuf {
|
2019-07-24 09:38:21 +00:00
|
|
|
project_dir().join("crates/ra_syntax/test_data")
|
2018-08-11 07:03:03 +00:00
|
|
|
}
|
|
|
|
|
2020-02-01 20:25:01 +00:00
|
|
|
fn assert_errors_are_present(errors: &[SyntaxError], path: &Path) {
|
|
|
|
assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display());
|
|
|
|
}
|
|
|
|
fn assert_errors_are_absent(errors: &[SyntaxError], path: &Path) {
|
|
|
|
assert_eq!(
|
|
|
|
errors,
|
|
|
|
&[] as &[SyntaxError],
|
|
|
|
"There should be no errors in the file {:?}",
|
|
|
|
path.display(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str) -> String {
|
2018-08-11 07:03:03 +00:00
|
|
|
let mut acc = String::new();
|
2020-03-13 02:29:44 +00:00
|
|
|
let mut offset = TextUnit::from_usize(0);
|
2018-08-11 07:03:03 +00:00
|
|
|
for token in tokens {
|
2020-03-13 02:29:44 +00:00
|
|
|
let token_len = token.len;
|
|
|
|
let token_text = &text[TextRange::offset_len(offset, token.len)];
|
|
|
|
offset += token.len;
|
2020-02-01 20:25:01 +00:00
|
|
|
writeln!(acc, "{:?} {} {:?}", token.kind, token_len, token_text).unwrap();
|
|
|
|
}
|
|
|
|
for err in errors {
|
2020-02-10 00:08:49 +00:00
|
|
|
writeln!(acc, "> error{:?} token({:?}) msg({})", err.range(), &text[err.range()], err)
|
|
|
|
.unwrap();
|
2020-02-01 20:25:01 +00:00
|
|
|
}
|
2020-02-06 00:33:18 +00:00
|
|
|
acc
|
2018-02-03 09:51:06 +00:00
|
|
|
}
|