[ruby/prism] Allow command calls in endless method bodies within assignments

Previously, endless method definitions in assignment contexts like
`x = def f = p 1` would fail to parse because command calls (method
calls without parentheses) were only accepted when the surrounding
binding power was less than `PM_BINDING_POWER_COMPOSITION`.

This fix specifically checks for assignment context and allows command
calls in those cases while maintaining the existing behavior for other
contexts. This ensures that:

- `x = def f = p 1` parses correctly (previously failed)
- `private def f = puts "Hello"` still produces the expected error

722af59ba3
This commit is contained in:
Stan Lo 2025-07-17 12:29:40 +01:00 committed by git
parent 026079925c
commit 2eab962c53
3 changed files with 14 additions and 1 deletions

View file

@ -19524,7 +19524,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_do_loop_stack_push(parser, false);
statements = (pm_node_t *) pm_statements_node_create(parser);
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1));
// In endless method bodies, we need to handle command calls carefully.
// We want to allow command calls in assignment context but maintain
// the same binding power to avoid changing how operators are parsed.
// Note that we're intentionally NOT allowing code like `private def foo = puts "Hello"`
// because the original parser, parse.y, can't handle it and we want to maintain the same behavior
bool allow_command_call = (binding_power == PM_BINDING_POWER_ASSIGNMENT) ||
(binding_power < PM_BINDING_POWER_COMPOSITION);
pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1));
if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
context_push(parser, PM_CONTEXT_RESCUE_MODIFIER);

View file

@ -0,0 +1,3 @@
private def foo = puts "Hello"
^ unexpected string literal, expecting end-of-input

View file

@ -3,3 +3,5 @@ def foo = 1
def bar = A ""
def method = 1 + 2 + 3
x = def f = p 1