mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 21:33:09 +00:00
Port test_new_parser_ad_hoc
This commit is contained in:
parent
d5cfa0e346
commit
a7791aab4d
2 changed files with 61 additions and 58 deletions
|
@ -2,8 +2,9 @@ use crate::ast::{self, Ast, List, Node, Traversal};
|
||||||
use crate::builtins::shared::{STATUS_CMD_OK, STATUS_UNMATCHED_WILDCARD};
|
use crate::builtins::shared::{STATUS_CMD_OK, STATUS_UNMATCHED_WILDCARD};
|
||||||
use crate::expand::ExpandFlags;
|
use crate::expand::ExpandFlags;
|
||||||
use crate::io::{IoBufferfill, IoChain};
|
use crate::io::{IoBufferfill, IoChain};
|
||||||
use crate::parse_constants::StatementDecoration;
|
use crate::parse_constants::{
|
||||||
use crate::parse_constants::{ParseTreeFlags, ParserTestErrorBits};
|
ParseErrorCode, ParseTreeFlags, ParserTestErrorBits, StatementDecoration,
|
||||||
|
};
|
||||||
use crate::parse_util::{parse_util_detect_errors, parse_util_detect_errors_in_argument};
|
use crate::parse_util::{parse_util_detect_errors, parse_util_detect_errors_in_argument};
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
use crate::reader::reader_reset_interrupted;
|
use crate::reader::reader_reset_interrupted;
|
||||||
|
@ -499,6 +500,64 @@ add_test!("test_new_parser_ll2", || {
|
||||||
check_function_help!("function foo; end", ast::Type::function_header);
|
check_function_help!("function foo; end", ast::Type::function_header);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add_test!("test_new_parser_ad_hoc", || {
|
||||||
|
// Very ad-hoc tests for issues encountered.
|
||||||
|
|
||||||
|
// Ensure that 'case' terminates a job list.
|
||||||
|
let src = L!("switch foo ; case bar; case baz; end");
|
||||||
|
let ast = Ast::parse(src, ParseTreeFlags::default(), None);
|
||||||
|
assert!(!ast.errored());
|
||||||
|
// Expect two case_item_lists. The bug was that we'd
|
||||||
|
// try to run a command 'case'.
|
||||||
|
assert_eq!(
|
||||||
|
Traversal::new(ast.top())
|
||||||
|
.filter(|n| n.typ() == ast::Type::case_item)
|
||||||
|
.count(),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ensure that naked variable assignments don't hang.
|
||||||
|
// The bug was that "a=" would produce an error but not be consumed,
|
||||||
|
// leading to an infinite loop.
|
||||||
|
|
||||||
|
// By itself it should produce an error.
|
||||||
|
let ast = Ast::parse(L!("a="), ParseTreeFlags::default(), None);
|
||||||
|
assert!(ast.errored());
|
||||||
|
|
||||||
|
// If we are leaving things unterminated, this should not produce an error.
|
||||||
|
// i.e. when typing "a=" at the command line, it should be treated as valid
|
||||||
|
// because we don't want to color it as an error.
|
||||||
|
let ast = Ast::parse(L!("a="), ParseTreeFlags::LEAVE_UNTERMINATED, None);
|
||||||
|
assert!(!ast.errored());
|
||||||
|
|
||||||
|
let mut errors = vec![];
|
||||||
|
Ast::parse(
|
||||||
|
L!("begin; echo ("),
|
||||||
|
ParseTreeFlags::LEAVE_UNTERMINATED,
|
||||||
|
Some(&mut errors),
|
||||||
|
);
|
||||||
|
assert!(errors.len() == 1);
|
||||||
|
assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_subshell);
|
||||||
|
|
||||||
|
errors.clear();
|
||||||
|
Ast::parse(
|
||||||
|
L!("for x in ("),
|
||||||
|
ParseTreeFlags::LEAVE_UNTERMINATED,
|
||||||
|
Some(&mut errors),
|
||||||
|
);
|
||||||
|
assert!(errors.len() == 1);
|
||||||
|
assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_subshell);
|
||||||
|
|
||||||
|
errors.clear();
|
||||||
|
Ast::parse(
|
||||||
|
L!("begin; echo '"),
|
||||||
|
ParseTreeFlags::LEAVE_UNTERMINATED,
|
||||||
|
Some(&mut errors),
|
||||||
|
);
|
||||||
|
assert!(errors.len() == 1);
|
||||||
|
assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_quote);
|
||||||
|
});
|
||||||
|
|
||||||
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,61 +1077,6 @@ static void test_input() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo!("port this")
|
|
||||||
static void test_new_parser_ad_hoc() {
|
|
||||||
using namespace ast;
|
|
||||||
// Very ad-hoc tests for issues encountered.
|
|
||||||
say(L"Testing new parser ad hoc tests");
|
|
||||||
|
|
||||||
// Ensure that 'case' terminates a job list.
|
|
||||||
const wcstring src = L"switch foo ; case bar; case baz; end";
|
|
||||||
auto ast = ast_parse(src);
|
|
||||||
if (ast->errored()) {
|
|
||||||
err(L"Parsing failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expect two case_item_lists. The bug was that we'd
|
|
||||||
// try to run a command 'case'.
|
|
||||||
int count = 0;
|
|
||||||
for (auto ast_traversal = new_ast_traversal(*ast->top());;) {
|
|
||||||
auto n = ast_traversal->next();
|
|
||||||
if (!n->has_value()) break;
|
|
||||||
count += (n->typ() == type_t::case_item);
|
|
||||||
}
|
|
||||||
if (count != 2) {
|
|
||||||
err(L"Expected 2 case item nodes, found %d", count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that naked variable assignments don't hang.
|
|
||||||
// The bug was that "a=" would produce an error but not be consumed,
|
|
||||||
// leading to an infinite loop.
|
|
||||||
|
|
||||||
// By itself it should produce an error.
|
|
||||||
ast = ast_parse(L"a=");
|
|
||||||
do_test(ast->errored());
|
|
||||||
|
|
||||||
// If we are leaving things unterminated, this should not produce an error.
|
|
||||||
// i.e. when typing "a=" at the command line, it should be treated as valid
|
|
||||||
// because we don't want to color it as an error.
|
|
||||||
ast = ast_parse(L"a=", parse_flag_leave_unterminated);
|
|
||||||
do_test(!ast->errored());
|
|
||||||
|
|
||||||
auto errors = new_parse_error_list();
|
|
||||||
ast = ast_parse(L"begin; echo (", parse_flag_leave_unterminated, &*errors);
|
|
||||||
do_test(errors->size() == 1 &&
|
|
||||||
errors->at(0)->code() == parse_error_code_t::tokenizer_unterminated_subshell);
|
|
||||||
|
|
||||||
errors->clear();
|
|
||||||
ast = ast_parse(L"for x in (", parse_flag_leave_unterminated, &*errors);
|
|
||||||
do_test(errors->size() == 1 &&
|
|
||||||
errors->at(0)->code() == parse_error_code_t::tokenizer_unterminated_subshell);
|
|
||||||
|
|
||||||
errors->clear();
|
|
||||||
ast = ast_parse(L"begin; echo '", parse_flag_leave_unterminated, &*errors);
|
|
||||||
do_test(errors->size() == 1 &&
|
|
||||||
errors->at(0)->code() == parse_error_code_t::tokenizer_unterminated_quote);
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo!("port this")
|
// todo!("port this")
|
||||||
static void test_new_parser_errors() {
|
static void test_new_parser_errors() {
|
||||||
say(L"Testing new parser error reporting");
|
say(L"Testing new parser error reporting");
|
||||||
|
@ -1594,7 +1539,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_ad_hoc"), test_new_parser_ad_hoc},
|
|
||||||
{TEST_GROUP("new_parser_errors"), test_new_parser_errors},
|
{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},
|
||||||
|
|
Loading…
Reference in a new issue