mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
Port test_new_parser_errors
This commit is contained in:
parent
a7791aab4d
commit
f3d1e0d63a
2 changed files with 31 additions and 53 deletions
|
@ -558,6 +558,37 @@ add_test!("test_new_parser_ad_hoc", || {
|
||||||
assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_quote);
|
assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_quote);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_test!("test_new_parser_errors", || {
|
||||||
|
macro_rules! validate {
|
||||||
|
($src:expr, $expected_code:expr) => {
|
||||||
|
let mut errors = vec![];
|
||||||
|
let ast = Ast::parse(L!($src), ParseTreeFlags::default(), Some(&mut errors));
|
||||||
|
assert!(ast.errored());
|
||||||
|
assert_eq!(
|
||||||
|
errors.into_iter().map(|e| e.code).collect::<Vec<_>>(),
|
||||||
|
vec![$expected_code],
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
validate!("echo 'abc", ParseErrorCode::tokenizer_unterminated_quote);
|
||||||
|
validate!("'", ParseErrorCode::tokenizer_unterminated_quote);
|
||||||
|
validate!("echo (abc", ParseErrorCode::tokenizer_unterminated_subshell);
|
||||||
|
|
||||||
|
validate!("end", ParseErrorCode::unbalancing_end);
|
||||||
|
validate!("echo hi ; end", ParseErrorCode::unbalancing_end);
|
||||||
|
|
||||||
|
validate!("else", ParseErrorCode::unbalancing_else);
|
||||||
|
validate!("if true ; end ; else", ParseErrorCode::unbalancing_else);
|
||||||
|
|
||||||
|
validate!("case", ParseErrorCode::unbalancing_case);
|
||||||
|
validate!("if true ; case ; end", ParseErrorCode::generic);
|
||||||
|
|
||||||
|
validate!("true | and", ParseErrorCode::andor_in_pipeline);
|
||||||
|
|
||||||
|
validate!("a=", ParseErrorCode::bare_variable_assignment);
|
||||||
|
});
|
||||||
|
|
||||||
add_test!("test_eval_recursion_detection", || {
|
add_test!("test_eval_recursion_detection", || {
|
||||||
// Ensure that we don't crash on infinite self recursion and mutual recursion. These must use
|
// Ensure that we don't crash on infinite self recursion and mutual recursion. These must use
|
||||||
// the principal parser because we cannot yet execute jobs on other parsers.
|
// the principal parser because we cannot yet execute jobs on other parsers.
|
||||||
|
|
|
@ -1077,58 +1077,6 @@ static void test_input() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo!("port this")
|
|
||||||
static void test_new_parser_errors() {
|
|
||||||
say(L"Testing new parser error reporting");
|
|
||||||
const struct {
|
|
||||||
const wchar_t *src;
|
|
||||||
parse_error_code_t code;
|
|
||||||
} tests[] = {
|
|
||||||
{L"echo 'abc", parse_error_code_t::tokenizer_unterminated_quote},
|
|
||||||
{L"'", parse_error_code_t::tokenizer_unterminated_quote},
|
|
||||||
{L"echo (abc", parse_error_code_t::tokenizer_unterminated_subshell},
|
|
||||||
|
|
||||||
{L"end", parse_error_code_t::unbalancing_end},
|
|
||||||
{L"echo hi ; end", parse_error_code_t::unbalancing_end},
|
|
||||||
|
|
||||||
{L"else", parse_error_code_t::unbalancing_else},
|
|
||||||
{L"if true ; end ; else", parse_error_code_t::unbalancing_else},
|
|
||||||
|
|
||||||
{L"case", parse_error_code_t::unbalancing_case},
|
|
||||||
{L"if true ; case ; end", parse_error_code_t::generic},
|
|
||||||
|
|
||||||
{L"true | and", parse_error_code_t::andor_in_pipeline},
|
|
||||||
|
|
||||||
{L"a=", parse_error_code_t::bare_variable_assignment},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &test : tests) {
|
|
||||||
const wcstring src = test.src;
|
|
||||||
parse_error_code_t expected_code = test.code;
|
|
||||||
|
|
||||||
auto errors = new_parse_error_list();
|
|
||||||
auto ast = ast_parse(src, parse_flag_none, &*errors);
|
|
||||||
if (!ast->errored()) {
|
|
||||||
err(L"Source '%ls' was expected to fail to parse, but succeeded", src.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errors->size() != 1) {
|
|
||||||
err(L"Source '%ls' was expected to produce 1 error, but instead produced %lu errors",
|
|
||||||
src.c_str(), errors->size());
|
|
||||||
for (size_t i = 0; i < errors->size(); i++) {
|
|
||||||
fprintf(stderr, "%ls\n", errors->at(i)->describe(src, false)->c_str());
|
|
||||||
}
|
|
||||||
} else if (errors->at(0)->code() != expected_code) {
|
|
||||||
err(L"Source '%ls' was expected to produce error code %lu, but instead produced error "
|
|
||||||
L"code %lu",
|
|
||||||
src.c_str(), expected_code, (unsigned long)errors->at(0)->code());
|
|
||||||
for (size_t i = 0; i < errors->size(); i++) {
|
|
||||||
err(L"\t\t%ls", errors->at(i)->describe(src, true)->c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Given a format string, returns a list of non-empty strings separated by format specifiers. The
|
// Given a format string, returns a list of non-empty strings separated by format specifiers. The
|
||||||
// format specifiers themselves are omitted.
|
// format specifiers themselves are omitted.
|
||||||
static std::vector<wcstring> separate_by_format_specifiers(const wchar_t *format) {
|
static std::vector<wcstring> separate_by_format_specifiers(const wchar_t *format) {
|
||||||
|
@ -1539,7 +1487,6 @@ static const test_t s_tests[]{
|
||||||
{TEST_GROUP("enum"), test_enum_array},
|
{TEST_GROUP("enum"), test_enum_array},
|
||||||
{TEST_GROUP("autosuggestion"), test_autosuggestion_combining},
|
{TEST_GROUP("autosuggestion"), test_autosuggestion_combining},
|
||||||
{TEST_GROUP("test_abbreviations"), test_abbreviations},
|
{TEST_GROUP("test_abbreviations"), test_abbreviations},
|
||||||
{TEST_GROUP("new_parser_errors"), test_new_parser_errors},
|
|
||||||
{TEST_GROUP("error_messages"), test_error_messages},
|
{TEST_GROUP("error_messages"), test_error_messages},
|
||||||
{TEST_GROUP("convert"), test_convert},
|
{TEST_GROUP("convert"), test_convert},
|
||||||
{TEST_GROUP("convert"), test_convert_private_use},
|
{TEST_GROUP("convert"), test_convert_private_use},
|
||||||
|
|
Loading…
Reference in a new issue