From 9122cb4fff0b1a6069a75218935098fcb5707d8e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 Jul 2026 13:57:19 -0400 Subject: [PATCH] Rescue associativity from the left --- snapshots/endless_method_rescue_modifier.txt | 417 ++++++++++++++++++ src/prism.c | 15 +- .../endless_method_rescue_modifier.txt | 11 + test/prism/ruby/ruby_parser_test.rb | 1 + 4 files changed, 441 insertions(+), 3 deletions(-) create mode 100644 snapshots/endless_method_rescue_modifier.txt create mode 100644 test/prism/fixtures/endless_method_rescue_modifier.txt diff --git a/snapshots/endless_method_rescue_modifier.txt b/snapshots/endless_method_rescue_modifier.txt new file mode 100644 index 0000000000..38db7b803e --- /dev/null +++ b/snapshots/endless_method_rescue_modifier.txt @@ -0,0 +1,417 @@ +@ ProgramNode (location: (1,0)-(11,35)) +├── flags: ∅ +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(11,35)) + ├── flags: ∅ + └── body: (length: 6) + ├── @ DefNode (location: (1,0)-(1,18)) + │ ├── flags: newline + │ ├── name: :f + │ ├── name_loc: (1,4)-(1,5) = "f" + │ ├── receiver: ∅ + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (1,8)-(1,18)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ RescueModifierNode (location: (1,8)-(1,18)) + │ │ ├── flags: ∅ + │ │ ├── expression: + │ │ │ @ CallNode (location: (1,8)-(1,9)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :a + │ │ │ ├── message_loc: (1,8)-(1,9) = "a" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── keyword_loc: (1,10)-(1,16) = "rescue" + │ │ └── rescue_expression: + │ │ @ CallNode (location: (1,17)-(1,18)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :b + │ │ ├── message_loc: (1,17)-(1,18) = "b" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── locals: [] + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (1,6)-(1,7) = "=" + │ └── end_keyword_loc: ∅ + ├── @ DefNode (location: (3,0)-(3,27)) + │ ├── flags: newline + │ ├── name: :f + │ ├── name_loc: (3,4)-(3,5) = "f" + │ ├── receiver: ∅ + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (3,8)-(3,27)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ RescueModifierNode (location: (3,8)-(3,27)) + │ │ ├── flags: ∅ + │ │ ├── expression: + │ │ │ @ RescueModifierNode (location: (3,8)-(3,18)) + │ │ │ ├── flags: ∅ + │ │ │ ├── expression: + │ │ │ │ @ CallNode (location: (3,8)-(3,9)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :a + │ │ │ │ ├── message_loc: (3,8)-(3,9) = "a" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── keyword_loc: (3,10)-(3,16) = "rescue" + │ │ │ └── rescue_expression: + │ │ │ @ CallNode (location: (3,17)-(3,18)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :b + │ │ │ ├── message_loc: (3,17)-(3,18) = "b" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── keyword_loc: (3,19)-(3,25) = "rescue" + │ │ └── rescue_expression: + │ │ @ CallNode (location: (3,26)-(3,27)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :c + │ │ ├── message_loc: (3,26)-(3,27) = "c" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── locals: [] + │ ├── def_keyword_loc: (3,0)-(3,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (3,6)-(3,7) = "=" + │ └── end_keyword_loc: ∅ + ├── @ CallNode (location: (5,0)-(5,29)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :baz + │ ├── message_loc: (5,0)-(5,3) = "baz" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (5,4)-(5,29)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ DefNode (location: (5,4)-(5,29)) + │ │ ├── flags: ∅ + │ │ ├── name: :f + │ │ ├── name_loc: (5,8)-(5,9) = "f" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (5,12)-(5,29)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ RescueModifierNode (location: (5,12)-(5,29)) + │ │ │ ├── flags: ∅ + │ │ │ ├── expression: + │ │ │ │ @ CallNode (location: (5,12)-(5,13)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :a + │ │ │ │ ├── message_loc: (5,12)-(5,13) = "a" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── keyword_loc: (5,14)-(5,20) = "rescue" + │ │ │ └── rescue_expression: + │ │ │ @ CallNode (location: (5,21)-(5,29)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :z + │ │ │ ├── message_loc: (5,21)-(5,22) = "z" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: + │ │ │ @ BlockNode (location: (5,23)-(5,29)) + │ │ │ ├── flags: ∅ + │ │ │ ├── locals: [] + │ │ │ ├── parameters: ∅ + │ │ │ ├── body: ∅ + │ │ │ ├── opening_loc: (5,23)-(5,25) = "do" + │ │ │ └── closing_loc: (5,26)-(5,29) = "end" + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (5,4)-(5,7) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (5,10)-(5,11) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── closing_loc: ∅ + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (7,0)-(7,34)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :bar + │ ├── message_loc: (7,0)-(7,3) = "bar" + │ ├── opening_loc: (7,3)-(7,4) = "(" + │ ├── arguments: + │ │ @ ArgumentsNode (location: (7,4)-(7,33)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ CallNode (location: (7,4)-(7,33)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :baz + │ │ ├── message_loc: (7,4)-(7,7) = "baz" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (7,8)-(7,33)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ DefNode (location: (7,8)-(7,33)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: :f + │ │ │ ├── name_loc: (7,12)-(7,13) = "f" + │ │ │ ├── receiver: ∅ + │ │ │ ├── parameters: ∅ + │ │ │ ├── body: + │ │ │ │ @ StatementsNode (location: (7,16)-(7,33)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ RescueModifierNode (location: (7,16)-(7,33)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── expression: + │ │ │ │ │ @ CallNode (location: (7,16)-(7,17)) + │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :a + │ │ │ │ │ ├── message_loc: (7,16)-(7,17) = "a" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ ├── keyword_loc: (7,18)-(7,24) = "rescue" + │ │ │ │ └── rescue_expression: + │ │ │ │ @ CallNode (location: (7,25)-(7,33)) + │ │ │ │ ├── flags: ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :z + │ │ │ │ ├── message_loc: (7,25)-(7,26) = "z" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: + │ │ │ │ @ BlockNode (location: (7,27)-(7,33)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── locals: [] + │ │ │ │ ├── parameters: ∅ + │ │ │ │ ├── body: ∅ + │ │ │ │ ├── opening_loc: (7,27)-(7,29) = "do" + │ │ │ │ └── closing_loc: (7,30)-(7,33) = "end" + │ │ │ ├── locals: [] + │ │ │ ├── def_keyword_loc: (7,8)-(7,11) = "def" + │ │ │ ├── operator_loc: ∅ + │ │ │ ├── lparen_loc: ∅ + │ │ │ ├── rparen_loc: ∅ + │ │ │ ├── equal_loc: (7,14)-(7,15) = "=" + │ │ │ └── end_keyword_loc: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: ∅ + │ ├── closing_loc: (7,33)-(7,34) = ")" + │ ├── equal_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (9,0)-(9,39)) + │ ├── flags: newline, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (9,0)-(9,3) = "foo" + │ ├── opening_loc: (9,3)-(9,4) = "(" + │ ├── arguments: + │ │ @ ArgumentsNode (location: (9,4)-(9,38)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ DefNode (location: (9,4)-(9,38)) + │ │ ├── flags: ∅ + │ │ ├── name: :f + │ │ ├── name_loc: (9,8)-(9,9) = "f" + │ │ ├── receiver: ∅ + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (9,12)-(9,38)) + │ │ │ ├── flags: ∅ + │ │ │ └── body: (length: 1) + │ │ │ └── @ RescueModifierNode (location: (9,12)-(9,38)) + │ │ │ ├── flags: ∅ + │ │ │ ├── expression: + │ │ │ │ @ RescueModifierNode (location: (9,12)-(9,22)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── expression: + │ │ │ │ │ @ CallNode (location: (9,12)-(9,13)) + │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :x + │ │ │ │ │ ├── message_loc: (9,12)-(9,13) = "x" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ ├── keyword_loc: (9,14)-(9,20) = "rescue" + │ │ │ │ └── rescue_expression: + │ │ │ │ @ CallNode (location: (9,21)-(9,22)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :y + │ │ │ │ ├── message_loc: (9,21)-(9,22) = "y" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── keyword_loc: (9,23)-(9,29) = "rescue" + │ │ │ └── rescue_expression: + │ │ │ @ CallNode (location: (9,30)-(9,38)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :y + │ │ │ ├── message_loc: (9,30)-(9,31) = "y" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: + │ │ │ @ BlockNode (location: (9,32)-(9,38)) + │ │ │ ├── flags: ∅ + │ │ │ ├── locals: [] + │ │ │ ├── parameters: ∅ + │ │ │ ├── body: ∅ + │ │ │ ├── opening_loc: (9,32)-(9,34) = "do" + │ │ │ └── closing_loc: (9,35)-(9,38) = "end" + │ │ ├── locals: [] + │ │ ├── def_keyword_loc: (9,4)-(9,7) = "def" + │ │ ├── operator_loc: ∅ + │ │ ├── lparen_loc: ∅ + │ │ ├── rparen_loc: ∅ + │ │ ├── equal_loc: (9,10)-(9,11) = "=" + │ │ └── end_keyword_loc: ∅ + │ ├── closing_loc: (9,38)-(9,39) = ")" + │ ├── equal_loc: ∅ + │ └── block: ∅ + └── @ CallNode (location: (11,0)-(11,35)) + ├── flags: newline, ignore_visibility + ├── receiver: ∅ + ├── call_operator_loc: ∅ + ├── name: :baz + ├── message_loc: (11,0)-(11,3) = "baz" + ├── opening_loc: ∅ + ├── arguments: + │ @ ArgumentsNode (location: (11,4)-(11,35)) + │ ├── flags: ∅ + │ └── arguments: (length: 1) + │ └── @ DefNode (location: (11,4)-(11,35)) + │ ├── flags: ∅ + │ ├── name: :f + │ ├── name_loc: (11,8)-(11,9) = "f" + │ ├── receiver: ∅ + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (11,12)-(11,35)) + │ │ ├── flags: ∅ + │ │ └── body: (length: 1) + │ │ └── @ RescueModifierNode (location: (11,12)-(11,35)) + │ │ ├── flags: ∅ + │ │ ├── expression: + │ │ │ @ RescueModifierNode (location: (11,12)-(11,22)) + │ │ │ ├── flags: ∅ + │ │ │ ├── expression: + │ │ │ │ @ CallNode (location: (11,12)-(11,13)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :a + │ │ │ │ ├── message_loc: (11,12)-(11,13) = "a" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ ├── equal_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ ├── keyword_loc: (11,14)-(11,20) = "rescue" + │ │ │ └── rescue_expression: + │ │ │ @ CallNode (location: (11,21)-(11,22)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :b + │ │ │ ├── message_loc: (11,21)-(11,22) = "b" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ ├── equal_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── keyword_loc: (11,23)-(11,29) = "rescue" + │ │ └── rescue_expression: + │ │ @ CallNode (location: (11,30)-(11,35)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :c + │ │ ├── message_loc: (11,30)-(11,31) = "c" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ ├── equal_loc: ∅ + │ │ └── block: + │ │ @ BlockNode (location: (11,32)-(11,35)) + │ │ ├── flags: ∅ + │ │ ├── locals: [] + │ │ ├── parameters: ∅ + │ │ ├── body: ∅ + │ │ ├── opening_loc: (11,32)-(11,33) = "{" + │ │ └── closing_loc: (11,34)-(11,35) = "}" + │ ├── locals: [] + │ ├── def_keyword_loc: (11,4)-(11,7) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: (11,10)-(11,11) = "=" + │ └── end_keyword_loc: ∅ + ├── closing_loc: ∅ + ├── equal_loc: ∅ + └── block: ∅ diff --git a/src/prism.c b/src/prism.c index 4436676f25..19af4f4a25 100644 --- a/src/prism.c +++ b/src/prism.c @@ -18606,10 +18606,13 @@ parse_def(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, * for primary-level constructs, not commands). During command argument * parsing, the stack is pushed to false, causing `do` to be lexed as * PM_TOKEN_KEYWORD_DO_BLOCK, which is not consumed inside the endless - * def body and instead left for the outer context. */ + * def body and instead left for the outer context. A method definition + * opens a fresh context all the way through its rescue modifier, so + * this frame spans the rescue modifier value as well: the `do` in + * `baz def f = a rescue z do end` lexes as a plain keyword that + * attaches to `z` rather than to `baz`. */ pm_accepts_block_stack_push(parser, true); pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_flags | PM_PARSE_IN_ENDLESS_DEF, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1)); - pm_accepts_block_stack_pop(parser); /* If an unconsumed PM_TOKEN_KEYWORD_DO follows the body, it is an error * (e.g., `def f = 1 do end`). PM_TOKEN_KEYWORD_DO_BLOCK is @@ -18621,7 +18624,11 @@ parse_def(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, pm_parser_err_node(parser, UP(block), PM_ERR_DEF_ENDLESS_DO_BLOCK); } - if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { + /* Any number of rescue modifiers chain onto the body within the method + * definition itself, associating to the left: `def f = a rescue b + * rescue c` defines a method whose body is `(a rescue b) rescue c`, + * rather than a rescue modifier guarding the definition. */ + while (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { context_push(parser, PM_CONTEXT_RESCUE_MODIFIER); pm_token_t rescue_keyword = parser->previous; @@ -18634,6 +18641,8 @@ parse_def(pm_parser_t *parser, pm_binding_power_t binding_power, uint8_t flags, statement = UP(pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value)); } + pm_accepts_block_stack_pop(parser); + /* A nested endless def whose body is a command call (e.g., * `def f = def g = foo bar`) is a command assignment and cannot appear * as a def body. */ diff --git a/test/prism/fixtures/endless_method_rescue_modifier.txt b/test/prism/fixtures/endless_method_rescue_modifier.txt new file mode 100644 index 0000000000..f9229fd42f --- /dev/null +++ b/test/prism/fixtures/endless_method_rescue_modifier.txt @@ -0,0 +1,11 @@ +def f = a rescue b + +def f = a rescue b rescue c + +baz def f = a rescue z do end + +bar(baz def f = a rescue z do end) + +foo(def f = x rescue y rescue y do end) + +baz def f = a rescue b rescue c { } diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb index 0a89e784f6..600f97c80b 100644 --- a/test/prism/ruby/ruby_parser_test.rb +++ b/test/prism/ruby/ruby_parser_test.rb @@ -37,6 +37,7 @@ class RubyParserTest < TestCase "alias.txt", "dsym_str.txt", "dos_endings.txt", + "endless_method_rescue_modifier.txt", "heredoc_dedent_line_continuation.txt", "heredoc_percent_q_newline_delimiter.txt", "heredocs_with_fake_newlines.txt",