mirror of
https://github.com/ruby/ruby.git
synced 2025-08-25 14:05:02 +02:00
[ruby/prism] Fix to check multiple block arguments for forwarding arg
Fix https://github.com/ruby/prism/pull/2111
21ca243d0a
This commit is contained in:
parent
165deec5fe
commit
0ee625ceae
4 changed files with 31 additions and 5 deletions
|
@ -56,6 +56,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
|
||||||
[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_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_FORWARDING] = "both a block argument and a forwarding argument; only one block is allowed",
|
||||||
[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",
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef enum {
|
||||||
PM_ERR_ARGUMENT_AFTER_BLOCK,
|
PM_ERR_ARGUMENT_AFTER_BLOCK,
|
||||||
PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES,
|
PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES,
|
||||||
PM_ERR_ARGUMENT_BARE_HASH,
|
PM_ERR_ARGUMENT_BARE_HASH,
|
||||||
|
PM_ERR_ARGUMENT_BLOCK_FORWARDING,
|
||||||
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,
|
||||||
|
|
|
@ -813,6 +813,9 @@ typedef struct {
|
||||||
|
|
||||||
/** The optional block attached to the call. */
|
/** The optional block attached to the call. */
|
||||||
pm_node_t *block;
|
pm_node_t *block;
|
||||||
|
|
||||||
|
/** The flag indicating whether this arguments list has forwarding argument. */
|
||||||
|
bool has_forwarding;
|
||||||
} pm_arguments_t;
|
} pm_arguments_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11306,6 +11309,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
|
||||||
|
|
||||||
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);
|
||||||
|
arguments->has_forwarding = true;
|
||||||
parsed_forwarding_arguments = true;
|
parsed_forwarding_arguments = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -12170,14 +12174,20 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block != NULL) {
|
if (block != NULL) {
|
||||||
if (arguments->block == NULL) {
|
if (arguments->block == NULL && !arguments->has_forwarding) {
|
||||||
arguments->block = (pm_node_t *) block;
|
arguments->block = (pm_node_t *) block;
|
||||||
} else {
|
} else {
|
||||||
pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI);
|
if (arguments->has_forwarding) {
|
||||||
if (arguments->arguments == NULL) {
|
pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_FORWARDING);
|
||||||
arguments->arguments = pm_arguments_node_create(parser);
|
} else {
|
||||||
|
pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI);
|
||||||
|
}
|
||||||
|
if (arguments->block != NULL) {
|
||||||
|
if (arguments->arguments == NULL) {
|
||||||
|
arguments->arguments = pm_arguments_node_create(parser);
|
||||||
|
}
|
||||||
|
pm_arguments_node_arguments_append(arguments->arguments, arguments->block);
|
||||||
}
|
}
|
||||||
pm_arguments_node_arguments_append(arguments->arguments, arguments->block);
|
|
||||||
arguments->block = (pm_node_t *) block;
|
arguments->block = (pm_node_t *) block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2046,6 +2046,20 @@ module Prism
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_block_arg_and_block
|
||||||
|
source = 'foo(&1) { }'
|
||||||
|
assert_errors expression(source), source, [
|
||||||
|
['multiple block arguments; only one block is allowed', 8..11]
|
||||||
|
], compare_ripper: false # Ripper does not check 'both block arg and actual block given'.
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_forwarding_arg_and_block
|
||||||
|
source = 'def foo(...) = foo(...) { }'
|
||||||
|
assert_errors expression(source), source, [
|
||||||
|
['both a block argument and a forwarding argument; only one block is allowed', 24..27]
|
||||||
|
], compare_ripper: false # Ripper does not check 'both block arg and actual block given'.
|
||||||
|
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…
Add table
Add a link
Reference in a new issue