Skip to content

Commit

Permalink
Raise void value expression in begin clauses
Browse files Browse the repository at this point in the history
In some cases Prism was either not raising an appropriate `void value
expression` error, or raising that error when the syntax is considered
valid.

To fix this Prism needs to check whether we have other clauses on the
`begin` rather than just returning `cast->statements`.

* If the `cast->statements` are null and the `cast->ensure_clause` is
not null, set the code to `cast->ensure_clause`
* else
  * If there is a `cast->rescue_clause`
    * Check if `cast->statements` are null and `cast->rescue_clause->statements`
    are null, and return `NULL`
    * Check if there is an `else_clause`, and set the node to
      `cast->else_clause`.
    * Otherwise return `cast->statements` as the node
  * return `cast->statements` as the node

See tests for test cases. Note I took these directly from CRuby so if
desired I can delete them since the test will now pass. This only fixes
one test in the `test_parse` file, taking failures from 14 to 13.

This fixes `TestParse#test_void_value_in_rhs` and is related to
issue #2791.
  • Loading branch information
eileencodes committed May 23, 2024
1 parent a05813d commit 398152b
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,31 @@ pm_check_value_expression(pm_node_t *node) {
return NULL;
case PM_BEGIN_NODE: {
pm_begin_node_t *cast = (pm_begin_node_t *) node;

if (cast->statements == NULL && cast->ensure_clause != NULL) {
node = (pm_node_t *) cast->ensure_clause;
}
else {
if (cast->rescue_clause != NULL) {
if (cast->rescue_clause->statements == NULL) {
return NULL;
}
else if (cast->else_clause != NULL) {
node = (pm_node_t *) cast->else_clause;
}
else {
node = (pm_node_t *) cast->statements;
}
}
else {
node = (pm_node_t *) cast->statements;
}
}

break;
}
case PM_ENSURE_NODE: {
pm_ensure_node_t *cast = (pm_ensure_node_t *) node;
node = (pm_node_t *) cast->statements;
break;
}
Expand Down
35 changes: 35 additions & 0 deletions test/prism/errors_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1630,6 +1630,41 @@ class << (return)
]
end

def test_void_value_expression_in_begin_statement
source = <<~RUBY
x = return 1
x = return, 1
x = 1, return
x, y = return
x = begin return ensure end
x = begin ensure return end
x = begin return ensure return end
x = begin return; rescue; return end
x = begin return; rescue; return; else return end
x = begin; return; rescue; retry; end
RUBY

message = 'unexpected void value expression'
assert_errors expression(source), source, [
[message, 4..12],
[message, 17..23],
[message, 34..40],
[message, 48..54],
[message, 65..71],
[message, 100..106],
[message, 121..127],
[message, 156..162],
[message, 222..228],
[message, 244..250],
]

refute_error_messages("x = begin return; rescue; end")
refute_error_messages("x = begin return; rescue; return; else end")
refute_error_messages("x = begin; rescue; retry; end")
refute_error_messages("x = begin 1; rescue; retry; ensure; end")
refute_error_messages("x = begin 1; rescue; return; end")
end

def test_void_value_expression_in_def
source = <<~RUBY
def (return).x
Expand Down

0 comments on commit 398152b

Please sign in to comment.