[ruby/prism] Fix and reuse pm_call_node_index_p

Fix https://github.com/ruby/prism/pull/1925
Fix https://github.com/ruby/prism/pull/1927

Previously pm_call_node_index_p does not check about a block argument
correctly and is not used in parse_write to check an index call node.

This commit fixes these problems.

https://github.com/ruby/prism/commit/92bab044ff
This commit is contained in:
TSUYUSATO Kitsune 2023-11-26 17:20:35 +09:00 committed by git
parent bd4a992f38
commit 8654859dbd
4 changed files with 604 additions and 433 deletions

View File

@ -1840,8 +1840,8 @@ pm_call_node_variable_call_p(pm_call_node_t *node) {
}
/**
* Returns whether or not this call is to the [] method in the index form (as
* opposed to `foo.[]`).
* Returns whether or not this call is to the [] method in the index form without a block (as
* opposed to `foo.[]` and `foo[] { }`).
*/
static inline bool
pm_call_node_index_p(pm_call_node_t *node) {
@ -1849,7 +1849,8 @@ pm_call_node_index_p(pm_call_node_t *node) {
(node->call_operator_loc.start == NULL) &&
(node->message_loc.start != NULL) &&
(node->message_loc.start[0] == '[') &&
(node->message_loc.end[-1] == ']')
(node->message_loc.end[-1] == ']') &&
(node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE))
);
}
@ -10827,13 +10828,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
// If there is no call operator and the message is "[]" then this is
// an aref expression, and we can transform it into an aset
// expression.
if (
(call->call_operator_loc.start == NULL) &&
(call->message_loc.start != NULL) &&
(call->message_loc.start[0] == '[') &&
(call->message_loc.end[-1] == ']') &&
(call->block == NULL)
) {
if (pm_call_node_index_p(call)) {
if (call->arguments == NULL) {
call->arguments = pm_arguments_node_create(parser);
}

View File

@ -1256,6 +1256,33 @@ module Prism
]
end
def test_index_call_with_block_and_write
source = "foo[1] {} &&= 1"
assert_errors expression(source), source, [
["Unexpected write target", 0..9],
["Unexpected operator after a call with arguments", 10..13],
["Unexpected operator after a call with a block", 10..13]
]
end
def test_index_call_with_block_or_write
source = "foo[1] {} ||= 1"
assert_errors expression(source), source, [
["Unexpected write target", 0..9],
["Unexpected operator after a call with arguments", 10..13],
["Unexpected operator after a call with a block", 10..13]
]
end
def test_index_call_with_block_operator_write
source = "foo[1] {} += 1"
assert_errors expression(source), source, [
["Unexpected write target", 0..9],
["Unexpected operator after a call with arguments", 10..12],
["Unexpected operator after a call with a block", 10..12]
]
end
def test_writing_numbered_parameter
assert_errors expression("-> { _1 = 0 }"), "-> { _1 = 0 }", [
["_1 is reserved for a numbered parameter", 5..7]

View File

@ -81,6 +81,14 @@ foo[bar] = baz
%w[\C:]
foo[&bar] = 1
foo.foo[&bar] = 1
def foo(&)
bar[&] = 1
end
foo[] += 1
foo[] ||= 1

File diff suppressed because it is too large Load Diff