summaryrefslogtreecommitdiff
path: root/test/prism/errors_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/prism/errors_test.rb')
-rw-r--r--test/prism/errors_test.rb110
1 files changed, 63 insertions, 47 deletions
diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb
index 62bbd8458b..9dd7fbe3fe 100644
--- a/test/prism/errors_test.rb
+++ b/test/prism/errors_test.rb
@@ -1,41 +1,24 @@
# 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
+ filepaths = Dir[ENV.fetch("FOCUS", "**/*.txt"), base: base]
- 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
+ PARSE_Y_EXCLUDES = [
+ # https://bugs.ruby-lang.org/issues/20409
+ "#{base}/4.1/end_block_exit.txt"
+ ]
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
@@ -67,52 +50,85 @@ module Prism
def test_unterminated_string_closing
statement = Prism.parse_statement("'hello")
assert_equal statement.unescaped, "hello"
- assert_empty statement.closing
+ assert_nil statement.closing
end
def test_unterminated_interpolated_string_closing
statement = Prism.parse_statement('"hello')
assert_equal statement.unescaped, "hello"
- assert_empty statement.closing
+ assert_nil statement.closing
end
def test_unterminated_empty_string_closing
statement = Prism.parse_statement('"')
assert_empty statement.unescaped
- assert_empty statement.closing
+ assert_nil statement.closing
end
- def test_invalid_message_name
- assert_equal :"", Prism.parse_statement("+.@foo,+=foo").write_name
+ def test_regexp_encoding_option_mismatch_error
+ # UTF-8 char with ASCII-8BIT modifier
+ result = Prism.parse('/Ȃ/n')
+ assert_includes result.errors.map(&:type), :regexp_encoding_option_mismatch
+
+ # UTF-8 char with EUC-JP modifier
+ result = Prism.parse('/Ȃ/e')
+ assert_includes result.errors.map(&:type), :regexp_encoding_option_mismatch
+
+ # UTF-8 char with Windows-31J modifier
+ result = Prism.parse('/Ȃ/s')
+ assert_includes result.errors.map(&:type), :regexp_encoding_option_mismatch
+
+ # UTF-8 char with UTF-8 modifier
+ result = Prism.parse('/Ȃ/u')
+ assert_empty result.errors
end
- def test_circular_parameters
- source = <<~RUBY
- def foo(bar = bar) = 42
- def foo(bar: bar) = 42
- proc { |foo = foo| }
- proc { |foo: foo| }
- RUBY
+ def test_incomplete_def_closing_loc
+ statement = Prism.parse_statement("def f; 123")
+ assert_nil(statement.end_keyword)
+ end
- source.each_line do |line|
- assert_predicate Prism.parse(line, version: "3.3.0"), :failure?
- assert_predicate Prism.parse(line), :success?
- end
+ def test_unclosed_interpolation
+ statement = Prism.parse_statement("\"\#{")
+ assert_equal('"', statement.opening)
+ assert_nil(statement.closing)
+
+ assert_equal(1, statement.parts.count)
+ assert_equal('#{', statement.parts[0].opening)
+ assert_equal("", statement.parts[0].closing)
+ assert_nil(statement.parts[0].statements)
+ end
+
+ def test_unclosed_heredoc_and_interpolation
+ statement = Prism.parse_statement("<<D\n\#{")
+ assert_equal("<<D", statement.opening)
+ assert_nil(statement.closing)
+
+ assert_equal(1, statement.parts.count)
+ assert_equal('#{', statement.parts[0].opening)
+ assert_equal("", statement.parts[0].closing)
+ assert_nil(statement.parts[0].statements)
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)
+ if CURRENT_MAJOR_MINOR == version && !PARSE_Y_EXCLUDES.include?(filepath)
+ refute_valid_syntax(source)
+ end
- result = Prism.parse(source)
+ result = Prism.parse(source, version: version)
errors = result.errors
refute_empty errors, "Expected errors in #{filepath}"
actual = result.errors_format
+ if expected != actual && ENV["UPDATE_SNAPSHOTS"]
+ File.write(filepath, actual)
+ end
+
assert_equal expected, actual, "Expected errors to match for #{filepath}"
end
end