diff --git a/prism/prism.c b/prism/prism.c index 864dd49f51..fecc25336d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17051,10 +17051,10 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_ static inline pm_node_t * parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) { pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id); + bool single_value = true; - bool is_single_value = true; if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) { - is_single_value = false; + single_value = false; pm_token_t opening = not_provided(parser); pm_array_node_t *array = pm_array_node_create(parser, &opening); @@ -17068,16 +17068,18 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding } } - // Contradicting binding powers, the right-hand-side value of the assignment allows the `rescue` modifier. - if (is_single_value && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { + // Contradicting binding powers, the right-hand-side value of the assignment + // allows the `rescue` modifier. + if ((single_value || (binding_power == (PM_BINDING_POWER_MULTI_ASSIGNMENT + 1))) && match1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) { pm_token_t rescue = parser->current; parser_lex(parser); bool accepts_command_call_inner = false; - // RHS can accept command call iff the value is a call with arguments but without paranthesis. + // RHS can accept command call iff the value is a call with arguments + // but without paranthesis. if (PM_NODE_TYPE_P(value, PM_CALL_NODE)) { - pm_call_node_t *call_node = (pm_call_node_t *)value; + pm_call_node_t *call_node = (pm_call_node_t *) value; if ((call_node->arguments != NULL) && (call_node->opening_loc.start == NULL)) { accepts_command_call_inner = true; } diff --git a/test/prism/fixtures/multi_write.txt b/test/prism/fixtures/multi_write.txt new file mode 100644 index 0000000000..edbcafb969 --- /dev/null +++ b/test/prism/fixtures/multi_write.txt @@ -0,0 +1,4 @@ +foo = 1 rescue nil +foo, bar = 1 rescue nil +foo = 1, 2 rescue nil +foo, bar = 1, 2 rescue nil diff --git a/test/prism/ruby_parser_test.rb b/test/prism/ruby_parser_test.rb index a71d05e78c..89150b2faa 100644 --- a/test/prism/ruby_parser_test.rb +++ b/test/prism/ruby_parser_test.rb @@ -73,6 +73,7 @@ module Prism alias.txt method_calls.txt methods.txt + multi_write.txt not.txt patterns.txt regex.txt diff --git a/test/prism/snapshots/multi_write.txt b/test/prism/snapshots/multi_write.txt new file mode 100644 index 0000000000..d313801fdb --- /dev/null +++ b/test/prism/snapshots/multi_write.txt @@ -0,0 +1,93 @@ +@ ProgramNode (location: (1,0)-(4,26)) +├── locals: [:foo, :bar] +└── statements: + @ StatementsNode (location: (1,0)-(4,26)) + └── body: (length: 4) + ├── @ LocalVariableWriteNode (location: (1,0)-(1,18)) + │ ├── name: :foo + │ ├── depth: 0 + │ ├── name_loc: (1,0)-(1,3) = "foo" + │ ├── value: + │ │ @ RescueModifierNode (location: (1,6)-(1,18)) + │ │ ├── expression: + │ │ │ @ IntegerNode (location: (1,6)-(1,7)) + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 + │ │ ├── keyword_loc: (1,8)-(1,14) = "rescue" + │ │ └── rescue_expression: + │ │ @ NilNode (location: (1,15)-(1,18)) + │ └── operator_loc: (1,4)-(1,5) = "=" + ├── @ MultiWriteNode (location: (2,0)-(2,23)) + │ ├── lefts: (length: 2) + │ │ ├── @ LocalVariableTargetNode (location: (2,0)-(2,3)) + │ │ │ ├── name: :foo + │ │ │ └── depth: 0 + │ │ └── @ LocalVariableTargetNode (location: (2,5)-(2,8)) + │ │ ├── name: :bar + │ │ └── depth: 0 + │ ├── rest: ∅ + │ ├── rights: (length: 0) + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── operator_loc: (2,9)-(2,10) = "=" + │ └── value: + │ @ RescueModifierNode (location: (2,11)-(2,23)) + │ ├── expression: + │ │ @ IntegerNode (location: (2,11)-(2,12)) + │ │ ├── flags: decimal + │ │ └── value: 1 + │ ├── keyword_loc: (2,13)-(2,19) = "rescue" + │ └── rescue_expression: + │ @ NilNode (location: (2,20)-(2,23)) + ├── @ RescueModifierNode (location: (3,0)-(3,21)) + │ ├── expression: + │ │ @ LocalVariableWriteNode (location: (3,0)-(3,10)) + │ │ ├── name: :foo + │ │ ├── depth: 0 + │ │ ├── name_loc: (3,0)-(3,3) = "foo" + │ │ ├── value: + │ │ │ @ ArrayNode (location: (3,6)-(3,10)) + │ │ │ ├── flags: ∅ + │ │ │ ├── elements: (length: 2) + │ │ │ │ ├── @ IntegerNode (location: (3,6)-(3,7)) + │ │ │ │ │ ├── flags: decimal + │ │ │ │ │ └── value: 1 + │ │ │ │ └── @ IntegerNode (location: (3,9)-(3,10)) + │ │ │ │ ├── flags: decimal + │ │ │ │ └── value: 2 + │ │ │ ├── opening_loc: ∅ + │ │ │ └── closing_loc: ∅ + │ │ └── operator_loc: (3,4)-(3,5) = "=" + │ ├── keyword_loc: (3,11)-(3,17) = "rescue" + │ └── rescue_expression: + │ @ NilNode (location: (3,18)-(3,21)) + └── @ MultiWriteNode (location: (4,0)-(4,26)) + ├── lefts: (length: 2) + │ ├── @ LocalVariableTargetNode (location: (4,0)-(4,3)) + │ │ ├── name: :foo + │ │ └── depth: 0 + │ └── @ LocalVariableTargetNode (location: (4,5)-(4,8)) + │ ├── name: :bar + │ └── depth: 0 + ├── rest: ∅ + ├── rights: (length: 0) + ├── lparen_loc: ∅ + ├── rparen_loc: ∅ + ├── operator_loc: (4,9)-(4,10) = "=" + └── value: + @ RescueModifierNode (location: (4,11)-(4,26)) + ├── expression: + │ @ ArrayNode (location: (4,11)-(4,15)) + │ ├── flags: ∅ + │ ├── elements: (length: 2) + │ │ ├── @ IntegerNode (location: (4,11)-(4,12)) + │ │ │ ├── flags: decimal + │ │ │ └── value: 1 + │ │ └── @ IntegerNode (location: (4,14)-(4,15)) + │ │ ├── flags: decimal + │ │ └── value: 2 + │ ├── opening_loc: ∅ + │ └── closing_loc: ∅ + ├── keyword_loc: (4,16)-(4,22) = "rescue" + └── rescue_expression: + @ NilNode (location: (4,23)-(4,26))