mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-29 06:13:20 +00:00
Migrate parse_util_detect_errors to a free function
This commit is contained in:
parent
2c3bc1e857
commit
29dede8139
5 changed files with 39 additions and 43 deletions
|
@ -303,11 +303,10 @@ int builtin_complete(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
|
|||
prefix.append(cmd);
|
||||
prefix.append(L": ");
|
||||
|
||||
wcstring err_text;
|
||||
if (parser.detect_errors_in_argument_list(comp, &err_text, prefix.c_str())) {
|
||||
if (maybe_t<wcstring> err_text = parse_util_detect_errors_in_argument_list(comp, prefix)) {
|
||||
streams.err.append_format(L"%ls: Completion '%ls' contained a syntax error\n", cmd,
|
||||
comp);
|
||||
streams.err.append(err_text);
|
||||
streams.err.append(*err_text);
|
||||
streams.err.push_back(L'\n');
|
||||
return STATUS_CMD_ERROR;
|
||||
}
|
||||
|
|
|
@ -1333,3 +1333,35 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
maybe_t<wcstring> parse_util_detect_errors_in_argument_list(const wcstring &arg_list_src,
|
||||
const wcstring &prefix) {
|
||||
// Helper to return a description of the first error.
|
||||
auto get_error_text = [&](const parse_error_list_t &errors) {
|
||||
assert(!errors.empty() && "Expected an error");
|
||||
return errors.at(0).describe_with_prefix(arg_list_src, prefix, false /* not interactive */,
|
||||
false /* don't skip caret */);
|
||||
};
|
||||
|
||||
// Parse the string as an argument list.
|
||||
parse_error_list_t errors;
|
||||
parse_node_tree_t tree;
|
||||
if (!parse_tree_from_string(arg_list_src, parse_flag_none, &tree, &errors,
|
||||
symbol_freestanding_argument_list)) {
|
||||
// Failed to parse.
|
||||
return get_error_text(errors);
|
||||
}
|
||||
|
||||
// Get the root argument list and extract arguments from it.
|
||||
// Test each of these.
|
||||
assert(!tree.empty() && "Should have parsed a tree");
|
||||
tnode_t<grammar::freestanding_argument_list> arg_list(&tree, &tree.at(0));
|
||||
while (auto arg = arg_list.next_in_list<grammar::argument>()) {
|
||||
const wcstring arg_src = arg.get_source(arg_list_src);
|
||||
if (parse_util_detect_errors_in_argument(arg, arg_src, &errors)) {
|
||||
return get_error_text(errors);
|
||||
}
|
||||
}
|
||||
|
||||
return none();
|
||||
}
|
||||
|
|
|
@ -132,6 +132,11 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
|
|||
bool allow_incomplete = true,
|
||||
parsed_source_ref_t *out_pstree = NULL);
|
||||
|
||||
/// Detect errors in the specified string when parsed as an argument list. Returns the text of an
|
||||
/// error, or none if no error occurred.
|
||||
maybe_t<wcstring> parse_util_detect_errors_in_argument_list(const wcstring &arg_list_src,
|
||||
const wcstring &prefix = {});
|
||||
|
||||
/// Test if this argument contains any errors. Detected errors include syntax errors in command
|
||||
/// substitutions, improperly escaped characters and improper use of the variable expansion
|
||||
/// operator. This does NOT currently detect unterminated quotes.
|
||||
|
|
|
@ -680,41 +680,6 @@ template int parser_t::eval_node(parsed_source_ref_t, tnode_t<grammar::job_list>
|
|||
const io_chain_t &, enum block_type_t,
|
||||
std::shared_ptr<job_t> parent_job);
|
||||
|
||||
bool parser_t::detect_errors_in_argument_list(const wcstring &arg_list_src, wcstring *out,
|
||||
const wchar_t *prefix) const {
|
||||
bool errored = false;
|
||||
parse_error_list_t errors;
|
||||
|
||||
// Use empty string for the prefix if it's NULL.
|
||||
if (!prefix) prefix = L""; //!OCLINT(parameter reassignment)
|
||||
|
||||
// Parse the string as an argument list.
|
||||
parse_node_tree_t tree;
|
||||
if (!parse_tree_from_string(arg_list_src, parse_flag_none, &tree, &errors,
|
||||
symbol_freestanding_argument_list)) {
|
||||
// Failed to parse.
|
||||
errored = true;
|
||||
}
|
||||
|
||||
if (!errored) {
|
||||
// Get the root argument list and extract arguments from it.
|
||||
assert(!tree.empty()); //!OCLINT(multiple unary operator)
|
||||
tnode_t<grammar::freestanding_argument_list> arg_list(&tree, &tree.at(0));
|
||||
while (auto arg = arg_list.next_in_list<grammar::argument>()) {
|
||||
const wcstring arg_src = arg.get_source(arg_list_src);
|
||||
if (parse_util_detect_errors_in_argument(arg, arg_src, &errors)) {
|
||||
errored = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.empty() && out != NULL) {
|
||||
out->assign(errors.at(0).describe_with_prefix(
|
||||
arg_list_src, prefix, false /* not interactive */, false /* don't skip caret */));
|
||||
}
|
||||
return errored;
|
||||
}
|
||||
|
||||
void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &errors,
|
||||
wcstring &output) const {
|
||||
if (!errors.empty()) {
|
||||
|
|
|
@ -335,11 +335,6 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
|
|||
void get_backtrace(const wcstring &src, const parse_error_list_t &errors,
|
||||
wcstring &output) const;
|
||||
|
||||
/// Detect errors in the specified string when parsed as an argument list. Returns true if an
|
||||
/// error occurred.
|
||||
bool detect_errors_in_argument_list(const wcstring &arg_list_src, wcstring *out_err,
|
||||
const wchar_t *prefix) const;
|
||||
|
||||
/// Tell the parser that the specified function may not be run if not inside of a conditional
|
||||
/// block. This is to remove some possibilities of infinite recursion.
|
||||
void forbid_function(const wcstring &function);
|
||||
|
|
Loading…
Reference in a new issue