# frozen_string_literal: true return if RUBY_VERSION < "3.3.0" require_relative "test_helper" module Ruby::Prism class ErrorsTest < TestCase base = File.expand_path("errors", __dir__) filepaths = Dir[ENV.fetch("FOCUS", "**/*.txt"), base: base] PARSE_Y_EXCLUDES = [ # https://bugs.ruby-lang.org/issues/20409 "#{base}/4.1/end_block_exit.txt" ] filepaths.each do |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 def test_newline_preceding_eof err = Ruby::Prism.parse("foo(").errors.first assert_equal 1, err.location.start_line err = Ruby::Prism.parse("foo(\n").errors.first assert_equal 1, err.location.start_line err = Ruby::Prism.parse("foo(\n\n\n\n\n").errors.first assert_equal 5, err.location.start_line end def test_embdoc_ending source = <<~RUBY =begin\n=end =begin\n=end\0 =begin\n=end\C-d =begin\n=end\C-z RUBY source.each_line do |line| assert_valid_syntax(source) assert_predicate Ruby::Prism.parse(source), :success? end end def test_unterminated_string_closing statement = Ruby::Prism.parse_statement("'hello") assert_equal statement.unescaped, "hello" assert_nil statement.closing end def test_unterminated_interpolated_string_closing statement = Ruby::Prism.parse_statement('"hello') assert_equal statement.unescaped, "hello" assert_nil statement.closing end def test_unterminated_empty_string_closing statement = Ruby::Prism.parse_statement('"') assert_empty statement.unescaped assert_nil statement.closing end def test_regexp_encoding_option_mismatch_error # UTF-8 char with ASCII-8BIT modifier result = Ruby::Prism.parse('/Ȃ/n') assert_includes result.errors.map(&:type), :regexp_encoding_option_mismatch # UTF-8 char with EUC-JP modifier result = Ruby::Prism.parse('/Ȃ/e') assert_includes result.errors.map(&:type), :regexp_encoding_option_mismatch # UTF-8 char with Windows-31J modifier result = Ruby::Prism.parse('/Ȃ/s') assert_includes result.errors.map(&:type), :regexp_encoding_option_mismatch # UTF-8 char with UTF-8 modifier result = Ruby::Prism.parse('/Ȃ/u') assert_empty result.errors end def test_long_formatted_messages # Messages are formatted into a fixed-size buffer first, so check lengths # on either side of its size to cover both the copy and the reformat. template = "unterminated heredoc; can't find string \"%s\" anywhere before EOF" (254..258).each do |length| identifier = "E" * (length - template.length + 2) expected = format(template, identifier) assert_equal length, expected.bytesize messages = Ruby::Prism.parse("<<#{identifier}\n").errors.map(&:message) assert_includes messages, expected end end def test_incomplete_def_closing_loc statement = Ruby::Prism.parse_statement("def f; 123") assert_nil(statement.end_keyword) end def test_unclosed_interpolation statement = Ruby::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 = Ruby::Prism.parse_statement("<