Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions snapshots/3.3-3.4/end_block_exit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@ ProgramNode (location: (1,0)-(7,1))
├── flags: ∅
├── locals: []
└── statements:
@ StatementsNode (location: (1,0)-(7,1))
├── flags: ∅
└── body: (length: 2)
├── @ PostExecutionNode (location: (1,0)-(3,1))
│ ├── flags: newline
│ ├── statements:
│ │ @ StatementsNode (location: (2,2)-(2,8))
│ │ ├── flags: ∅
│ │ └── body: (length: 1)
│ │ └── @ ReturnNode (location: (2,2)-(2,8))
│ │ ├── flags: newline
│ │ ├── keyword_loc: (2,2)-(2,8) = "return"
│ │ └── arguments: ∅
│ ├── keyword_loc: (1,0)-(1,3) = "END"
│ ├── opening_loc: (1,4)-(1,5) = "{"
│ └── closing_loc: (3,0)-(3,1) = "}"
└── @ PostExecutionNode (location: (5,0)-(7,1))
├── flags: newline
├── statements:
│ @ StatementsNode (location: (6,2)-(6,7))
│ ├── flags: ∅
│ └── body: (length: 1)
│ └── @ BreakNode (location: (6,2)-(6,7))
│ ├── flags: newline
│ ├── arguments: ∅
│ └── keyword_loc: (6,2)-(6,7) = "break"
├── keyword_loc: (5,0)-(5,3) = "END"
├── opening_loc: (5,4)-(5,5) = "{"
└── closing_loc: (7,0)-(7,1) = "}"
20 changes: 20 additions & 0 deletions snapshots/end_block_exit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@ ProgramNode (location: (1,0)-(3,1))
├── flags: ∅
├── locals: []
└── statements:
@ StatementsNode (location: (1,0)-(3,1))
├── flags: ∅
└── body: (length: 1)
└── @ PostExecutionNode (location: (1,0)-(3,1))
├── flags: newline
├── statements:
│ @ StatementsNode (location: (2,2)-(2,6))
│ ├── flags: ∅
│ └── body: (length: 1)
│ └── @ NextNode (location: (2,2)-(2,6))
│ ├── flags: newline
│ ├── arguments: ∅
│ └── keyword_loc: (2,2)-(2,6) = "next"
├── keyword_loc: (1,0)-(1,3) = "END"
├── opening_loc: (1,4)-(1,5) = "{"
└── closing_loc: (3,0)-(3,1) = "}"
12 changes: 11 additions & 1 deletion src/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -15777,7 +15777,6 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node) {
case PM_CONTEXT_LAMBDA_ENSURE:
case PM_CONTEXT_LAMBDA_RESCUE:
case PM_CONTEXT_LOOP_PREDICATE:
case PM_CONTEXT_POSTEXE:
case PM_CONTEXT_UNTIL:
case PM_CONTEXT_WHILE:
// These are the good cases. We're allowed to have a block exit
Expand All @@ -15790,10 +15789,21 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node) {
case PM_CONTEXT_DEF_RESCUE:
case PM_CONTEXT_MAIN:
case PM_CONTEXT_PREEXE:
case PM_CONTEXT_POSTEXE:
case PM_CONTEXT_SCLASS:
case PM_CONTEXT_SCLASS_ELSE:
case PM_CONTEXT_SCLASS_ENSURE:
case PM_CONTEXT_SCLASS_RESCUE:
// https://bugs.ruby-lang.org/issues/20409
if (context_node->context == PM_CONTEXT_POSTEXE) {
if (parser->version < PM_OPTIONS_VERSION_CRUBY_4_0) {
return;
}
if (PM_NODE_TYPE_P(node, PM_NEXT_NODE)) {
return;
}
}

// These are the bad cases. We're not allowed to have a block
// exit in these contexts.
//
Expand Down
5 changes: 5 additions & 0 deletions test/prism/errors/4.0/end_block_exit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
END {
break
^~~~~ Invalid break
}

9 changes: 8 additions & 1 deletion test/prism/errors_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class ErrorsTest < TestCase
base = File.expand_path("errors", __dir__)
filepaths = Dir["**/*.txt", base: base]

PARSE_Y_EXCLUDES = [
# https://bugs.ruby-lang.org/issues/20409
"#{base}/3.5/end_block_exit.txt"
]

filepaths.each do |filepath|
ruby_versions_for(filepath).each do |version|
define_method(:"test_#{version}_#{File.basename(filepath, ".txt")}") do
Expand Down Expand Up @@ -70,7 +75,9 @@ def assert_errors(filepath, version)
expected = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8)

source = expected.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "")
refute_valid_syntax(source) if current_major_minor == version
if current_major_minor == version && !PARSE_Y_EXCLUDES.include?(filepath)
refute_valid_syntax(source)
end

result = Prism.parse(source, version: version)
errors = result.errors
Expand Down
7 changes: 7 additions & 0 deletions test/prism/fixtures/3.3-3.4/end_block_exit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
END {
return
}

END {
break
}
3 changes: 3 additions & 0 deletions test/prism/fixtures/end_block_exit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
END {
next
}
Loading