mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
Restore error messages for bare variable assignment
Since #6287, bare variable assignments do not parse, which broke the "Unsupported use of '='" error message. This commit catches parse errors that occur on bare variable assignments. When a statement node fails to parse, then we check if there is at least one prefixing variable assignment. If so, we emit the old error message. See also #6347
This commit is contained in:
parent
563bdf3cc7
commit
97969a9363
3 changed files with 60 additions and 5 deletions
|
@ -174,9 +174,10 @@ enum parse_error_code_t {
|
|||
parse_error_tokenizer_unterminated_escape,
|
||||
parse_error_tokenizer_other,
|
||||
|
||||
parse_error_unbalancing_end, // end outside of block
|
||||
parse_error_unbalancing_else, // else outside of if
|
||||
parse_error_unbalancing_case // case outside of switch
|
||||
parse_error_unbalancing_end, // end outside of block
|
||||
parse_error_unbalancing_else, // else outside of if
|
||||
parse_error_unbalancing_case, // case outside of switch
|
||||
parse_error_bare_variable_assignment, // a=b without command
|
||||
};
|
||||
|
||||
enum { PARSER_TEST_ERROR = 1, PARSER_TEST_INCOMPLETE = 2 };
|
||||
|
|
|
@ -53,6 +53,15 @@ wcstring parse_error_t::describe_with_prefix(const wcstring &src, const wcstring
|
|||
if (skip_caret && this->text.empty()) return L"";
|
||||
|
||||
wcstring result = prefix;
|
||||
if (code == parse_error_bare_variable_assignment) {
|
||||
wcstring assignment_src = src.substr(this->source_start, this->source_length);
|
||||
maybe_t<size_t> equals_pos = variable_assignment_equals_pos(assignment_src);
|
||||
assert(equals_pos);
|
||||
wcstring variable = assignment_src.substr(0, *equals_pos);
|
||||
wcstring value = assignment_src.substr(*equals_pos + 1);
|
||||
append_format(result, ERROR_BAD_COMMAND_ASSIGN_ERR_MSG, variable.c_str(), value.c_str());
|
||||
return result;
|
||||
}
|
||||
result.append(this->text);
|
||||
if (skip_caret || source_start >= src.size() || source_start + source_length > src.size()) {
|
||||
return result;
|
||||
|
@ -918,8 +927,45 @@ void parse_ll_t::accept_tokens(parse_token_t token1, parse_token_t token2) {
|
|||
production_for_token(stack_elem.type, token1, token2, &tag);
|
||||
node.tag = tag;
|
||||
if (production == nullptr) {
|
||||
parse_error_failed_production(stack_elem, token1);
|
||||
// The above sets fatal_errored, which ends the loop.
|
||||
tnode_t<grammar::variable_assignments> variable_assignments;
|
||||
if (const parse_node_t *parent = nodes.get_parent(node)) {
|
||||
switch (parent->type) {
|
||||
default:
|
||||
break;
|
||||
case symbol_job:
|
||||
variable_assignments =
|
||||
tnode_t<grammar::job>(&nodes, parent)
|
||||
.try_get_child<grammar::variable_assignments, 0>();
|
||||
break;
|
||||
case symbol_job_continuation:
|
||||
variable_assignments =
|
||||
tnode_t<grammar::job_continuation>(&nodes, parent)
|
||||
.try_get_child<grammar::variable_assignments, 2>();
|
||||
break;
|
||||
case symbol_not_statement:
|
||||
variable_assignments =
|
||||
tnode_t<grammar::not_statement>(&nodes, parent)
|
||||
.try_get_child<grammar::variable_assignments, 1>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
tnode_t<grammar::variable_assignment> variable_assignment;
|
||||
tnode_t<grammar::tok_string> assignment_tok;
|
||||
if (variable_assignments &&
|
||||
(variable_assignment =
|
||||
variable_assignments.try_get_child<grammar::variable_assignment, 0>()) &&
|
||||
(assignment_tok = variable_assignment.try_get_child<grammar::tok_string, 0>())) {
|
||||
parse_token_t token(parse_token_type_string);
|
||||
token.source_start = assignment_tok.source_range()->start;
|
||||
token.source_length = assignment_tok.source_range()->length;
|
||||
parse_error(token, parse_error_bare_variable_assignment,
|
||||
L" " /* won't be printed but must be non-empty, see
|
||||
describe_with_prefix */
|
||||
);
|
||||
} else {
|
||||
parse_error_failed_production(stack_elem, token1);
|
||||
}
|
||||
// The above set fatal_errored, which ends the loop.
|
||||
} else {
|
||||
bool is_terminate = (token1.type == parse_token_type_terminate);
|
||||
|
||||
|
|
|
@ -76,3 +76,11 @@ complete -C'a=b xalias '
|
|||
alias envxalias='a=b x'
|
||||
complete -C'a=b envxalias '
|
||||
# CHECK: arg
|
||||
|
||||
# Eval invalid grammar to allow fish to parse this file
|
||||
eval 'a=(echo b)'
|
||||
# CHECKERR: {{.*}}: Unsupported use of '='. In fish, please use 'set a (echo b)'.
|
||||
eval ': | a=b'
|
||||
# CHECKERR: {{.*}}: Unsupported use of '='. In fish, please use 'set a b'.
|
||||
eval 'not a=b'
|
||||
# CHECKERR: {{.*}}: Unsupported use of '='. In fish, please use 'set a b'.
|
||||
|
|
Loading…
Reference in a new issue