Skip to content
Merged
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
1 change: 1 addition & 0 deletions .github/auto_request_review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ files:
'doc/zjit*': [team:jit]
'test/ruby/test_zjit*': [team:jit]
'defs/jit.mk': [team:jit]
'tool/zjit_bisect.rb': [team:jit]
# Skip github workflow files because the team don't necessarily need to review dependabot updates for GitHub Actions. It's noisy in notifications, and they're auto-merged anyway.
options:
ignore_draft: true
Expand Down
2 changes: 1 addition & 1 deletion prism/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -15764,7 +15764,7 @@ parse_return(pm_parser_t *parser, pm_node_t *node) {
break;
}
}
if (in_sclass) {
if (in_sclass && parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) {
pm_parser_err_node(parser, node, PM_ERR_RETURN_INVALID);
}
}
Expand Down
12 changes: 12 additions & 0 deletions test/prism/errors/3.3-3.3/circular_parameters.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def foo(bar = bar) = 42
^~~ circular argument reference - bar

def foo(bar: bar) = 42
^~~ circular argument reference - bar

proc { |foo = foo| }
^~~ circular argument reference - foo

proc { |foo: foo| }
^~~ circular argument reference - foo

34 changes: 34 additions & 0 deletions test/prism/errors/3.3-3.4/leading_logical.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
1
&& 2
^~ unexpected '&&', ignoring it
&& 3
^~ unexpected '&&', ignoring it

1
|| 2
^ unexpected '|', ignoring it
^ unexpected '|', ignoring it
|| 3
^ unexpected '|', ignoring it
^ unexpected '|', ignoring it

1
and 2
^~~ unexpected 'and', ignoring it
and 3
^~~ unexpected 'and', ignoring it

1
or 2
^~ unexpected 'or', ignoring it
or 3
^~ unexpected 'or', ignoring it

1
and foo
^~~ unexpected 'and', ignoring it

2
or foo
^~ unexpected 'or', ignoring it

3 changes: 3 additions & 0 deletions test/prism/errors/3.3-3.4/private_endless_method.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
private def foo = puts "Hello"
^ unexpected string literal, expecting end-of-input

65 changes: 10 additions & 55 deletions test/prism/errors_test.rb
Original file line number Diff line number Diff line change
@@ -1,41 +1,19 @@
# frozen_string_literal: true

return if RUBY_VERSION < "3.3.0"

require_relative "test_helper"

module Prism
class ErrorsTest < TestCase
base = File.expand_path("errors", __dir__)
filepaths = Dir["*.txt", base: base]

if RUBY_VERSION < "3.0"
filepaths -= [
"cannot_assign_to_a_reserved_numbered_parameter.txt",
"writing_numbered_parameter.txt",
"targeting_numbered_parameter.txt",
"defining_numbered_parameter.txt",
"defining_numbered_parameter_2.txt",
"numbered_parameters_in_block_arguments.txt",
"numbered_and_write.txt",
"numbered_or_write.txt",
"numbered_operator_write.txt"
]
end

if RUBY_VERSION < "3.4"
filepaths -= [
"it_with_ordinary_parameter.txt",
"block_args_in_array_assignment.txt",
"keyword_args_in_array_assignment.txt"
]
end

if RUBY_VERSION < "3.4" || RUBY_RELEASE_DATE < "2024-07-24"
filepaths -= ["dont_allow_return_inside_sclass_body.txt"]
end
filepaths = Dir["**/*.txt", base: base]

filepaths.each do |filepath|
define_method(:"test_#{File.basename(filepath, ".txt")}") do
assert_errors(File.join(base, filepath))
ruby_versions_for(filepath).each do |version|
define_method(:"test_#{version}_#{File.basename(filepath, ".txt")}") do
assert_errors(File.join(base, filepath), version)
end
end
end

Expand Down Expand Up @@ -86,38 +64,15 @@ def test_invalid_message_name
assert_equal :"", Prism.parse_statement("+.@foo,+=foo").write_name
end

def test_circular_parameters
source = <<~RUBY
def foo(bar = bar) = 42
def foo(bar: bar) = 42
proc { |foo = foo| }
proc { |foo: foo| }
RUBY

source.each_line do |line|
assert_predicate Prism.parse(line, version: "3.3.0"), :failure?
assert_predicate Prism.parse(line), :success?
end
end

def test_private_endless_method
source = <<~RUBY
private def foo = puts "Hello"
RUBY

assert_predicate Prism.parse(source, version: "3.4"), :failure?
assert_predicate Prism.parse(source), :success?
end

private

def assert_errors(filepath)
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)
refute_valid_syntax(source) if current_major_minor == version

result = Prism.parse(source)
result = Prism.parse(source, version: version)
errors = result.errors
refute_empty errors, "Expected errors in #{filepath}"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
matrix[5, &block] = 8
File renamed without changes.
1 change: 1 addition & 0 deletions test/prism/fixtures/3.3-3.3/it_with_ordinary_parameter.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
proc { || it }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
matrix[5, axis: :y] = 8
1 change: 1 addition & 0 deletions test/prism/fixtures/3.3-3.3/return_in_sclass.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class << A; return; end
4 changes: 4 additions & 0 deletions test/prism/fixtures/3.4/circular_parameters.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def foo(bar = bar) = 42
def foo(bar: bar) = 42
proc { |foo = foo| }
proc { |foo: foo| }
5 changes: 5 additions & 0 deletions test/prism/fixtures/3.4/it.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
x do
it
end

-> { it }
23 changes: 23 additions & 0 deletions test/prism/fixtures/3.4/it_indirect_writes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
tap { it += 1 }

tap { it ||= 1 }

tap { it &&= 1 }

tap { it; it += 1 }

tap { it; it ||= 1 }

tap { it; it &&= 1 }

tap { it += 1; it }

tap { it ||= 1; it }

tap { it &&= 1; it }

tap { it; it += 1; it }

tap { it; it ||= 1; it }

tap { it; it &&= 1; it }
1 change: 1 addition & 0 deletions test/prism/fixtures/3.4/it_read_and_assignment.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
42.tap { p it; it = it; p it }
14 changes: 12 additions & 2 deletions test/prism/fixtures_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ class FixturesTest < TestCase
except << "whitequark/ruby_bug_19281.txt"
end

if RUBY_VERSION < "3.4.0"
except << "3.4/circular_parameters.txt"
end

# Valid only on Ruby 3.3
except << "3.3-3.3/block_args_in_array_assignment.txt"
except << "3.3-3.3/it_with_ordinary_parameter.txt"
except << "3.3-3.3/keyword_args_in_array_assignment.txt"
except << "3.3-3.3/return_in_sclass.txt"

# Leaving these out until they are supported by parse.y.
except << "leading_logical.txt"
except << "endless_methods_command_call.txt"
except << "3.5/leading_logical.txt"
except << "3.5/endless_methods_command_call.txt"
# https://bugs.ruby-lang.org/issues/21168#note-5
except << "command_method_call_2.txt"

Expand Down
14 changes: 8 additions & 6 deletions test/prism/lex_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ class LexTest < TestCase
end

# https://bugs.ruby-lang.org/issues/20925
except << "leading_logical.txt"
except << "3.5/leading_logical.txt"

# https://bugs.ruby-lang.org/issues/17398#note-12
except << "endless_methods_command_call.txt"
except << "3.5/endless_methods_command_call.txt"

# https://bugs.ruby-lang.org/issues/21168#note-5
except << "command_method_call_2.txt"

Fixture.each(except: except) do |fixture|
define_method(fixture.test_name) { assert_lex(fixture) }
Fixture.each_with_version(except: except) do |fixture, version|
define_method(fixture.test_name(version)) { assert_lex(fixture, version) }
end

def test_lex_file
Expand Down Expand Up @@ -97,10 +97,12 @@ def test_parse_lex_file

private

def assert_lex(fixture)
def assert_lex(fixture, version)
return unless current_major_minor == version

source = fixture.read

result = Prism.lex_compat(source)
result = Prism.lex_compat(source, version: version)
assert_equal [], result.errors

Prism.lex_ripper(source).zip(result.value).each do |(ripper, prism)|
Expand Down
10 changes: 8 additions & 2 deletions test/prism/locals_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ class LocalsTest < TestCase
# CRuby is eliminating dead code.
"whitequark/ruby_bug_10653.txt",

# Valid only on Ruby 3.3
"3.3-3.3/block_args_in_array_assignment.txt",
"3.3-3.3/it_with_ordinary_parameter.txt",
"3.3-3.3/keyword_args_in_array_assignment.txt",
"3.3-3.3/return_in_sclass.txt",

# Leaving these out until they are supported by parse.y.
"leading_logical.txt",
"endless_methods_command_call.txt",
"3.5/leading_logical.txt",
"3.5/endless_methods_command_call.txt",
"command_method_call_2.txt"
]

Expand Down
13 changes: 8 additions & 5 deletions test/prism/ruby/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,14 @@ class ParserTest < TestCase
# 1.. && 2
"ranges.txt",

# https://bugs.ruby-lang.org/issues/20478
"3.4/circular_parameters.txt",

# Cannot yet handling leading logical operators.
"leading_logical.txt",
"3.5/leading_logical.txt",

# Ruby >= 3.5 specific syntax
"endless_methods_command_call.txt",
"3.5/endless_methods_command_call.txt",

# https://bugs.ruby-lang.org/issues/21168#note-5
"command_method_call_2.txt",
Expand Down Expand Up @@ -165,9 +168,9 @@ def test_non_prism_builder_class_deprecated

if RUBY_VERSION >= "3.3"
def test_current_parser_for_current_ruby
major, minor, _patch = Gem::Version.new(RUBY_VERSION).segments
major, minor = current_major_minor.split(".")
# Let's just hope there never is a Ruby 3.10 or similar
expected = major * 10 + minor
expected = major.to_i * 10 + minor.to_i
assert_equal(expected, Translation::ParserCurrent.new.version)
end
end
Expand All @@ -189,7 +192,7 @@ def test_invalid_syntax
end

def test_it_block_parameter_syntax
it_fixture_path = Pathname(__dir__).join("../../../test/prism/fixtures/it.txt")
it_fixture_path = Pathname(__dir__).join("../../../test/prism/fixtures/3.4/it.txt")

buffer = Parser::Source::Buffer.new(it_fixture_path)
buffer.source = it_fixture_path.read
Expand Down
12 changes: 10 additions & 2 deletions test/prism/ruby/ripper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class RipperTest < TestCase
# Skip these tests that Ripper is reporting the wrong results for.
incorrect = [
# Not yet supported.
"leading_logical.txt",
"3.5/leading_logical.txt",

# Ripper incorrectly attributes the block to the keyword.
"seattlerb/block_break.txt",
Expand All @@ -31,8 +31,16 @@ class RipperTest < TestCase
# Ripper fails to understand some structures that span across heredocs.
"spanning_heredoc.txt",

"3.3-3.3/block_args_in_array_assignment.txt",
"3.3-3.3/it_with_ordinary_parameter.txt",
"3.3-3.3/keyword_args_in_array_assignment.txt",
"3.3-3.3/return_in_sclass.txt",

# https://bugs.ruby-lang.org/issues/20478
"3.4/circular_parameters.txt",

# https://bugs.ruby-lang.org/issues/17398#note-12
"endless_methods_command_call.txt",
"3.5/endless_methods_command_call.txt",

# https://bugs.ruby-lang.org/issues/21168#note-5
"command_method_call_2.txt",
Expand Down
12 changes: 9 additions & 3 deletions test/prism/ruby/ruby_parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class RubyParserTest < TestCase
"dos_endings.txt",
"heredocs_with_fake_newlines.txt",
"heredocs_with_ignored_newlines.txt",
"leading_logical.txt",
"method_calls.txt",
"methods.txt",
"multi_write.txt",
Expand Down Expand Up @@ -77,8 +76,15 @@ class RubyParserTest < TestCase
"whitequark/ruby_bug_19281.txt",
"whitequark/slash_newline_in_heredocs.txt",

# Ruby >= 3.5 specific syntax
"endless_methods_command_call.txt",
"3.3-3.3/block_args_in_array_assignment.txt",
"3.3-3.3/it_with_ordinary_parameter.txt",
"3.3-3.3/keyword_args_in_array_assignment.txt",
"3.3-3.3/return_in_sclass.txt",

"3.4/circular_parameters.txt",

"3.5/endless_methods_command_call.txt",
"3.5/leading_logical.txt",

# https://bugs.ruby-lang.org/issues/21168#note-5
"command_method_call_2.txt",
Expand Down
Loading