[ruby/prism] Fix parsing ...
in arguments
(https://github.com/ruby/prism/pull/1882) * Fix parsing `...` in arguments Fix https://github.com/ruby/prism/pull/1830 Fix https://github.com/ruby/prism/pull/1831 * Rename the constant name to PM_ERR_ARGUMENT_FORWARDING_UNBOUND https://github.com/ruby/prism/pull/1882#discussion_r1398461156 https://github.com/ruby/prism/commit/519653aec2
This commit is contained in:
parent
83da4a7e62
commit
caa9ae7804
@ -54,12 +54,14 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
|
|||||||
[PM_ERR_ALIAS_ARGUMENT] = "Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable",
|
[PM_ERR_ALIAS_ARGUMENT] = "Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable",
|
||||||
[PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = "Unexpected `&&=` in a multiple assignment",
|
[PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = "Unexpected `&&=` in a multiple assignment",
|
||||||
[PM_ERR_ARGUMENT_AFTER_BLOCK] = "Unexpected argument after a block argument",
|
[PM_ERR_ARGUMENT_AFTER_BLOCK] = "Unexpected argument after a block argument",
|
||||||
|
[PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = "Unexpected argument after `...`",
|
||||||
[PM_ERR_ARGUMENT_BARE_HASH] = "Unexpected bare hash argument",
|
[PM_ERR_ARGUMENT_BARE_HASH] = "Unexpected bare hash argument",
|
||||||
[PM_ERR_ARGUMENT_BLOCK_MULTI] = "Multiple block arguments; only one block is allowed",
|
[PM_ERR_ARGUMENT_BLOCK_MULTI] = "Multiple block arguments; only one block is allowed",
|
||||||
[PM_ERR_ARGUMENT_FORMAL_CLASS] = "Invalid formal argument; formal argument cannot be a class variable",
|
[PM_ERR_ARGUMENT_FORMAL_CLASS] = "Invalid formal argument; formal argument cannot be a class variable",
|
||||||
[PM_ERR_ARGUMENT_FORMAL_CONSTANT] = "Invalid formal argument; formal argument cannot be a constant",
|
[PM_ERR_ARGUMENT_FORMAL_CONSTANT] = "Invalid formal argument; formal argument cannot be a constant",
|
||||||
[PM_ERR_ARGUMENT_FORMAL_GLOBAL] = "Invalid formal argument; formal argument cannot be a global variable",
|
[PM_ERR_ARGUMENT_FORMAL_GLOBAL] = "Invalid formal argument; formal argument cannot be a global variable",
|
||||||
[PM_ERR_ARGUMENT_FORMAL_IVAR] = "Invalid formal argument; formal argument cannot be an instance variable",
|
[PM_ERR_ARGUMENT_FORMAL_IVAR] = "Invalid formal argument; formal argument cannot be an instance variable",
|
||||||
|
[PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = "Unexpected `...` in an non-parenthesized call",
|
||||||
[PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = "Unexpected `&` when the parent method is not forwarding",
|
[PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = "Unexpected `&` when the parent method is not forwarding",
|
||||||
[PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = "Unexpected `...` when the parent method is not forwarding",
|
[PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = "Unexpected `...` when the parent method is not forwarding",
|
||||||
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = "Unexpected `*` when the parent method is not forwarding",
|
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = "Unexpected `*` when the parent method is not forwarding",
|
||||||
|
@ -40,12 +40,14 @@ typedef enum {
|
|||||||
PM_ERR_ALIAS_ARGUMENT,
|
PM_ERR_ALIAS_ARGUMENT,
|
||||||
PM_ERR_AMPAMPEQ_MULTI_ASSIGN,
|
PM_ERR_AMPAMPEQ_MULTI_ASSIGN,
|
||||||
PM_ERR_ARGUMENT_AFTER_BLOCK,
|
PM_ERR_ARGUMENT_AFTER_BLOCK,
|
||||||
|
PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES,
|
||||||
PM_ERR_ARGUMENT_BARE_HASH,
|
PM_ERR_ARGUMENT_BARE_HASH,
|
||||||
PM_ERR_ARGUMENT_BLOCK_MULTI,
|
PM_ERR_ARGUMENT_BLOCK_MULTI,
|
||||||
PM_ERR_ARGUMENT_FORMAL_CLASS,
|
PM_ERR_ARGUMENT_FORMAL_CLASS,
|
||||||
PM_ERR_ARGUMENT_FORMAL_CONSTANT,
|
PM_ERR_ARGUMENT_FORMAL_CONSTANT,
|
||||||
PM_ERR_ARGUMENT_FORMAL_GLOBAL,
|
PM_ERR_ARGUMENT_FORMAL_GLOBAL,
|
||||||
PM_ERR_ARGUMENT_FORMAL_IVAR,
|
PM_ERR_ARGUMENT_FORMAL_IVAR,
|
||||||
|
PM_ERR_ARGUMENT_FORWARDING_UNBOUND,
|
||||||
PM_ERR_ARGUMENT_NO_FORWARDING_AMP,
|
PM_ERR_ARGUMENT_NO_FORWARDING_AMP,
|
||||||
PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
|
PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
|
||||||
PM_ERR_ARGUMENT_NO_FORWARDING_STAR,
|
PM_ERR_ARGUMENT_NO_FORWARDING_STAR,
|
||||||
|
@ -11039,13 +11039,18 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parsed_first_argument = false;
|
||||||
bool parsed_bare_hash = false;
|
bool parsed_bare_hash = false;
|
||||||
bool parsed_block_argument = false;
|
bool parsed_block_argument = false;
|
||||||
|
bool parsed_forwarding_arguments = false;
|
||||||
|
|
||||||
while (!match1(parser, PM_TOKEN_EOF)) {
|
while (!match1(parser, PM_TOKEN_EOF)) {
|
||||||
if (parsed_block_argument) {
|
if (parsed_block_argument) {
|
||||||
pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK);
|
pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK);
|
||||||
}
|
}
|
||||||
|
if (parsed_forwarding_arguments) {
|
||||||
|
pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES);
|
||||||
|
}
|
||||||
|
|
||||||
pm_node_t *argument = NULL;
|
pm_node_t *argument = NULL;
|
||||||
|
|
||||||
@ -11129,9 +11134,13 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|||||||
if (pm_parser_local_depth(parser, &parser->previous) == -1) {
|
if (pm_parser_local_depth(parser, &parser->previous) == -1) {
|
||||||
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
|
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
|
||||||
}
|
}
|
||||||
|
if (parsed_first_argument && terminator == PM_TOKEN_EOF) {
|
||||||
|
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
|
||||||
|
}
|
||||||
|
|
||||||
argument = (pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->previous);
|
argument = (pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->previous);
|
||||||
parse_arguments_append(parser, arguments, argument);
|
parse_arguments_append(parser, arguments, argument);
|
||||||
|
parsed_forwarding_arguments = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11183,6 +11192,8 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parsed_first_argument = true;
|
||||||
|
|
||||||
// If parsing the argument failed, we need to stop parsing arguments.
|
// If parsing the argument failed, we need to stop parsing arguments.
|
||||||
if (PM_NODE_TYPE_P(argument, PM_MISSING_NODE) || parser->recovering) break;
|
if (PM_NODE_TYPE_P(argument, PM_MISSING_NODE) || parser->recovering) break;
|
||||||
|
|
||||||
|
@ -1682,6 +1682,20 @@ module Prism
|
|||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_argument_after_ellipsis
|
||||||
|
source = 'def foo(...); foo(..., 1); end'
|
||||||
|
assert_errors expression(source), source, [
|
||||||
|
['Unexpected argument after `...`', 23..24]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_ellipsis_in_no_paren_call
|
||||||
|
source = 'def foo(...); foo 1, ...; end'
|
||||||
|
assert_errors expression(source), source, [
|
||||||
|
['Unexpected `...` in an non-parenthesized call', 21..24]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")
|
def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user