Skip to content

Commit ec662f5

Browse files
Validate MultiTargetNode and MultiWriteNode
1 parent 7b23e44 commit ec662f5

3 files changed

Lines changed: 35 additions & 17 deletions

File tree

config.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3727,8 +3727,7 @@ nodes:
37273727
- IndexTargetNode
37283728
- MultiTargetNode
37293729
- RequiredParameterNode # def m((a,b)); end
3730-
- on error: BackReferenceReadNode # a, (b, $&) = z
3731-
- on error: NumberedReferenceReadNode # a, (b, $1) = z
3730+
- on error: ErrorRecoveryNode
37323731
comment: |
37333732
Represents the targets expressions before a splat node.
37343733
@@ -3772,8 +3771,7 @@ nodes:
37723771
- IndexTargetNode
37733772
- MultiTargetNode
37743773
- RequiredParameterNode # def m((*,b)); end
3775-
- on error: BackReferenceReadNode # a, (*, $&) = z
3776-
- on error: NumberedReferenceReadNode # a, (*, $1) = z
3774+
- on error: ErrorRecoveryNode
37773775
comment: |
37783776
Represents the targets expressions after a splat node.
37793777
@@ -3817,8 +3815,7 @@ nodes:
38173815
- CallTargetNode
38183816
- IndexTargetNode
38193817
- MultiTargetNode
3820-
- on error: BackReferenceReadNode # $&, = z
3821-
- on error: NumberedReferenceReadNode # $1, = z
3818+
- on error: ErrorRecoveryNode
38223819
comment: |
38233820
Represents the targets expressions before a splat node.
38243821
@@ -3861,8 +3858,7 @@ nodes:
38613858
- CallTargetNode
38623859
- IndexTargetNode
38633860
- MultiTargetNode
3864-
- on error: BackReferenceReadNode # *, $& = z
3865-
- on error: NumberedReferenceReadNode # *, $1 = z
3861+
- on error: ErrorRecoveryNode
38663862
comment: |
38673863
Represents the targets expressions after a splat node.
38683864

src/prism.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13125,7 +13125,13 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
1312513125
bool has_rest = PM_NODE_TYPE_P(first_target, PM_SPLAT_NODE);
1312613126

1312713127
pm_multi_target_node_t *result = pm_multi_target_node_create(parser);
13128-
pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target, true, false));
13128+
13129+
pm_node_t *first = parse_target(parser, first_target, true, false);
13130+
PM_VALIDATE_NODE_TYPE(parser, first,
13131+
PM_SPLAT_NODE, PM_IMPLICIT_REST_NODE, PM_LOCAL_VARIABLE_TARGET_NODE, PM_INSTANCE_VARIABLE_TARGET_NODE,
13132+
PM_CLASS_VARIABLE_TARGET_NODE, PM_GLOBAL_VARIABLE_TARGET_NODE, PM_CONSTANT_TARGET_NODE,
13133+
PM_CONSTANT_PATH_TARGET_NODE, PM_CALL_TARGET_NODE, PM_INDEX_TARGET_NODE, PM_MULTI_TARGET_NODE, PM_REQUIRED_PARAMETER_NODE);
13134+
pm_multi_target_node_targets_append(parser, result, first);
1312913135

1313013136
while (accept1(parser, PM_TOKEN_COMMA)) {
1313113137
if (accept1(parser, PM_TOKEN_USTAR)) {
@@ -13152,12 +13158,20 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
1315213158
pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
1315313159
target = parse_target(parser, target, true, false);
1315413160

13161+
PM_VALIDATE_NODE_TYPE(parser, target,
13162+
PM_SPLAT_NODE, PM_IMPLICIT_REST_NODE, PM_LOCAL_VARIABLE_TARGET_NODE, PM_INSTANCE_VARIABLE_TARGET_NODE,
13163+
PM_CLASS_VARIABLE_TARGET_NODE, PM_GLOBAL_VARIABLE_TARGET_NODE, PM_CONSTANT_TARGET_NODE,
13164+
PM_CONSTANT_PATH_TARGET_NODE, PM_CALL_TARGET_NODE, PM_INDEX_TARGET_NODE, PM_MULTI_TARGET_NODE, PM_REQUIRED_PARAMETER_NODE);
1315513165
pm_multi_target_node_targets_append(parser, result, target);
1315613166
context_pop(parser);
1315713167
} else if (token_begins_expression_p(parser->current.type)) {
1315813168
pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
1315913169
target = parse_target(parser, target, true, false);
1316013170

13171+
PM_VALIDATE_NODE_TYPE(parser, target,
13172+
PM_SPLAT_NODE, PM_IMPLICIT_REST_NODE, PM_LOCAL_VARIABLE_TARGET_NODE, PM_INSTANCE_VARIABLE_TARGET_NODE,
13173+
PM_CLASS_VARIABLE_TARGET_NODE, PM_GLOBAL_VARIABLE_TARGET_NODE, PM_CONSTANT_TARGET_NODE,
13174+
PM_CONSTANT_PATH_TARGET_NODE, PM_CALL_TARGET_NODE, PM_INDEX_TARGET_NODE, PM_MULTI_TARGET_NODE, PM_REQUIRED_PARAMETER_NODE);
1316113175
pm_multi_target_node_targets_append(parser, result, target);
1316213176
} else if (!match1(parser, PM_TOKEN_EOF)) {
1316313177
// If we get here, then we have a trailing , in a multi target node.
@@ -17647,6 +17661,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1764717661
multi_target = (pm_multi_target_node_t *) statement;
1764817662
} else {
1764917663
multi_target = pm_multi_target_node_create(parser);
17664+
PM_VALIDATE_NODE_TYPE(parser, statement,
17665+
PM_SPLAT_NODE, PM_IMPLICIT_REST_NODE, PM_LOCAL_VARIABLE_TARGET_NODE, PM_INSTANCE_VARIABLE_TARGET_NODE,
17666+
PM_CLASS_VARIABLE_TARGET_NODE, PM_GLOBAL_VARIABLE_TARGET_NODE, PM_CONSTANT_TARGET_NODE,
17667+
PM_CONSTANT_PATH_TARGET_NODE, PM_CALL_TARGET_NODE, PM_INDEX_TARGET_NODE, PM_MULTI_TARGET_NODE, PM_REQUIRED_PARAMETER_NODE);
1765017668
pm_multi_target_node_targets_append(parser, multi_target, statement);
1765117669
}
1765217670

@@ -17755,6 +17773,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1775517773

1775617774
if (PM_NODE_TYPE_P(statement, PM_SPLAT_NODE)) {
1775717775
pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser);
17776+
PM_VALIDATE_NODE_TYPE(parser, statement,
17777+
PM_SPLAT_NODE, PM_IMPLICIT_REST_NODE, PM_LOCAL_VARIABLE_TARGET_NODE, PM_INSTANCE_VARIABLE_TARGET_NODE,
17778+
PM_CLASS_VARIABLE_TARGET_NODE, PM_GLOBAL_VARIABLE_TARGET_NODE, PM_CONSTANT_TARGET_NODE,
17779+
PM_CONSTANT_PATH_TARGET_NODE, PM_CALL_TARGET_NODE, PM_INDEX_TARGET_NODE, PM_MULTI_TARGET_NODE, PM_REQUIRED_PARAMETER_NODE);
1775817780
pm_multi_target_node_targets_append(parser, multi_target, statement);
1775917781

1776017782
statement = UP(multi_target);

test/prism/result/error_recovery_test.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,63 +106,63 @@ def test_multi_target_node_lefts_back_reference
106106
refute result.success?
107107

108108
node = result.value.statements.body.first.lefts.last
109-
assert node.lefts.any? { |left| left.is_a?(BackReferenceReadNode) }
109+
assert node.lefts.any? { |left| left.is_a?(ErrorRecoveryNode) && left.child.is_a?(BackReferenceReadNode) }
110110
end
111111

112112
def test_multi_target_node_lefts_numbered_reference
113113
result = Prism.parse("a, (b, $1) = z")
114114
refute result.success?
115115

116116
node = result.value.statements.body.first.lefts.last
117-
assert node.lefts.any? { |left| left.is_a?(NumberedReferenceReadNode) }
117+
assert node.lefts.any? { |left| left.is_a?(ErrorRecoveryNode) && left.child.is_a?(NumberedReferenceReadNode) }
118118
end
119119

120120
def test_multi_target_node_rights_back_reference
121121
result = Prism.parse("a, (*, $&) = z")
122122
refute result.success?
123123

124124
node = result.value.statements.body.first.lefts.last
125-
assert node.rights.any? { |right| right.is_a?(BackReferenceReadNode) }
125+
assert node.rights.any? { |right| right.is_a?(ErrorRecoveryNode) && right.child.is_a?(BackReferenceReadNode) }
126126
end
127127

128128
def test_multi_target_node_rights_numbered_reference
129129
result = Prism.parse("a, (*, $1) = z")
130130
refute result.success?
131131

132132
node = result.value.statements.body.first.lefts.last
133-
assert node.rights.any? { |right| right.is_a?(NumberedReferenceReadNode) }
133+
assert node.rights.any? { |right| right.is_a?(ErrorRecoveryNode) && right.child.is_a?(NumberedReferenceReadNode) }
134134
end
135135

136136
def test_multi_write_node_lefts_back_reference
137137
result = Prism.parse("$&, = z")
138138
refute result.success?
139139

140140
node = result.value.statements.body.first
141-
assert node.lefts.any? { |left| left.is_a?(BackReferenceReadNode) }
141+
assert node.lefts.any? { |left| left.is_a?(ErrorRecoveryNode) && left.child.is_a?(BackReferenceReadNode) }
142142
end
143143

144144
def test_multi_write_node_lefts_numbered_reference
145145
result = Prism.parse("$1, = z")
146146
refute result.success?
147147

148148
node = result.value.statements.body.first
149-
assert node.lefts.any? { |left| left.is_a?(NumberedReferenceReadNode) }
149+
assert node.lefts.any? { |left| left.is_a?(ErrorRecoveryNode) && left.child.is_a?(NumberedReferenceReadNode) }
150150
end
151151

152152
def test_multi_write_node_rights_back_reference
153153
result = Prism.parse("*, $& = z")
154154
refute result.success?
155155

156156
node = result.value.statements.body.first
157-
assert node.rights.any? { |right| right.is_a?(BackReferenceReadNode) }
157+
assert node.rights.any? { |right| right.is_a?(ErrorRecoveryNode) && right.child.is_a?(BackReferenceReadNode) }
158158
end
159159

160160
def test_multi_write_node_rights_numbered_reference
161161
result = Prism.parse("*, $1 = z")
162162
refute result.success?
163163

164164
node = result.value.statements.body.first
165-
assert node.rights.any? { |right| right.is_a?(NumberedReferenceReadNode) }
165+
assert node.rights.any? { |right| right.is_a?(ErrorRecoveryNode) && right.child.is_a?(NumberedReferenceReadNode) }
166166
end
167167

168168
def test_parameters_node_posts_keyword_rest

0 commit comments

Comments
 (0)