ruby/test/yarp/errors_test.rb
Kevin Newton 439f069b4b [ruby/yarp] Move tests from test/* to test/yarp/* to match CRuby
This should make it easier on the sync to determine what changed
and hopefully result in fewer merge conflicts that have to be
manually resolved.

17d82afbfc
2023-08-25 21:15:49 +00:00

1131 lines
28 KiB
Ruby

# frozen_string_literal: true
require_relative "test_helper"
class ErrorsTest < Test::Unit::TestCase
include ::YARP::DSL
def test_constant_path_with_invalid_token_after
assert_error_messages "A::$b", [
"Expected identifier or constant after '::'",
"Expected a newline or semicolon after statement."
]
end
def test_module_name_recoverable
expected = ModuleNode(
[],
Location(),
ConstantReadNode(),
StatementsNode(
[ModuleNode([], Location(), MissingNode(), nil, Location(), "")]
),
Location(),
"Parent"
)
assert_errors expected, "module Parent module end", [
["Expected to find a module name after `module`.", 20..20]
]
end
def test_for_loops_index_missing
expected = ForNode(
MissingNode(),
expression("1..10"),
StatementsNode([expression("i")]),
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "for in 1..10\ni\nend", [
["Expected index after for.", 0..0]
]
end
def test_for_loops_only_end
expected = ForNode(
MissingNode(),
MissingNode(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "for end", [
["Expected index after for.", 0..0],
["Expected keyword in.", 3..3],
["Expected collection.", 3..3]
]
end
def test_pre_execution_missing_brace
expected = PreExecutionNode(
StatementsNode([expression("1")]),
Location(),
Location(),
Location()
)
assert_errors expected, "BEGIN 1 }", [
["Expected '{' after 'BEGIN'.", 5..5]
]
end
def test_pre_execution_context
expected = PreExecutionNode(
StatementsNode([
CallNode(
expression("1"),
nil,
Location(),
nil,
ArgumentsNode([MissingNode()]),
nil,
nil,
0,
"+"
)
]),
Location(),
Location(),
Location()
)
assert_errors expected, "BEGIN { 1 + }", [
["Expected a value after the operator.", 11..11]
]
end
def test_unterminated_embdoc
assert_errors expression("1"), "1\n=begin\n", [
["Unterminated embdoc", 2..9]
]
end
def test_unterminated_i_list
assert_errors expression("%i["), "%i[", [
["Expected a closing delimiter for a `%i` list.", 3..3]
]
end
def test_unterminated_w_list
assert_errors expression("%w["), "%w[", [
["Expected a closing delimiter for a `%w` list.", 3..3]
]
end
def test_unterminated_W_list
assert_errors expression("%W["), "%W[", [
["Expected a closing delimiter for a `%W` list.", 3..3]
]
end
def test_unterminated_regular_expression
assert_errors expression("/hello"), "/hello", [
["Expected a closing delimiter for a regular expression.", 1..1]
]
end
def test_unterminated_regular_expression_with_heredoc
source = "<<-END + /b\nEND\n"
assert_errors expression(source), source, [
["Expected a closing delimiter for a regular expression.", 10..10]
]
end
def test_unterminated_xstring
assert_errors expression("`hello"), "`hello", [
["Expected a closing delimiter for an xstring.", 1..1]
]
end
def test_unterminated_string
assert_errors expression('"hello'), '"hello', [
["Expected a closing delimiter for an interpolated string.", 1..1]
]
end
def test_unterminated_s_symbol
assert_errors expression("%s[abc"), "%s[abc", [
["Expected a closing delimiter for a dynamic symbol.", 3..3]
]
end
def test_unterminated_parenthesized_expression
assert_errors expression('(1 + 2'), '(1 + 2', [
["Expected to be able to parse an expression.", 6..6],
["Expected a closing parenthesis.", 6..6]
]
end
def test_unterminated_argument_expression
assert_errors expression('a %'), 'a %', [
["Unexpected end of input", 2..3],
["Expected a value after the operator.", 3..3],
]
end
def test_cr_without_lf_in_percent_expression
assert_errors expression("%\r"), "%\r", [
["Invalid %% token", 0..2],
]
end
def test_1_2_3
assert_errors expression("(1, 2, 3)"), "(1, 2, 3)", [
["Expected to be able to parse an expression.", 2..2],
["Expected a closing parenthesis.", 2..2],
["Expected a newline or semicolon after statement.", 2..2],
["Expected to be able to parse an expression.", 2..2],
["Expected a newline or semicolon after statement.", 5..5],
["Expected to be able to parse an expression.", 5..5],
["Expected a newline or semicolon after statement.", 8..8],
["Expected to be able to parse an expression.", 8..8],
]
end
def test_return_1_2_3
assert_error_messages "return(1, 2, 3)", [
"Expected to be able to parse an expression.",
"Expected a closing parenthesis.",
"Expected a newline or semicolon after statement.",
"Expected to be able to parse an expression."
]
end
def test_return_1
assert_errors expression("return 1,;"), "return 1,;", [
["Expected to be able to parse an argument.", 9..9]
]
end
def test_next_1_2_3
assert_errors expression("next(1, 2, 3)"), "next(1, 2, 3)", [
["Expected to be able to parse an expression.", 6..6],
["Expected a closing parenthesis.", 6..6],
["Expected a newline or semicolon after statement.", 12..12],
["Expected to be able to parse an expression.", 12..12]
]
end
def test_next_1
assert_errors expression("next 1,;"), "next 1,;", [
["Expected to be able to parse an argument.", 7..7]
]
end
def test_break_1_2_3
assert_errors expression("break(1, 2, 3)"), "break(1, 2, 3)", [
["Expected to be able to parse an expression.", 7..7],
["Expected a closing parenthesis.", 7..7],
["Expected a newline or semicolon after statement.", 13..13],
["Expected to be able to parse an expression.", 13..13],
]
end
def test_break_1
assert_errors expression("break 1,;"), "break 1,;", [
["Expected to be able to parse an argument.", 8..8]
]
end
def test_argument_forwarding_when_parent_is_not_forwarding
assert_errors expression('def a(x, y, z); b(...); end'), 'def a(x, y, z); b(...); end', [
["unexpected ... when parent method is not forwarding.", 18..21]
]
end
def test_argument_forwarding_only_effects_its_own_internals
assert_errors expression('def a(...); b(...); end; def c(x, y, z); b(...); end'),
'def a(...); b(...); end; def c(x, y, z); b(...); end', [
["unexpected ... when parent method is not forwarding.", 43..46]
]
end
def test_top_level_constant_with_downcased_identifier
assert_error_messages "::foo", [
"Expected a constant after ::.",
"Expected a newline or semicolon after statement."
]
end
def test_top_level_constant_starting_with_downcased_identifier
assert_error_messages "::foo::A", [
"Expected a constant after ::.",
"Expected a newline or semicolon after statement."
]
end
def test_aliasing_global_variable_with_non_global_variable
assert_errors expression("alias $a b"), "alias $a b", [
["Expected a global variable.", 9..10]
]
end
def test_aliasing_non_global_variable_with_global_variable
assert_errors expression("alias a $b"), "alias a $b", [
["Expected a bare word or symbol argument.", 8..10]
]
end
def test_aliasing_global_variable_with_global_number_variable
assert_errors expression("alias $a $1"), "alias $a $1", [
["Can't make alias for number variables.", 9..11]
]
end
def test_def_with_expression_receiver_and_no_identifier
assert_errors expression("def (a); end"), "def (a); end", [
["Expected '.' or '::' after receiver", 7..7]
]
end
def test_def_with_multiple_statements_receiver
assert_errors expression("def (\na\nb\n).c; end"), "def (\na\nb\n).c; end", [
["Expected closing ')' for receiver.", 7..7],
["Expected '.' or '::' after receiver", 7..7],
["Expected to be able to parse an expression.", 10..10],
["Expected to be able to parse an expression.", 11..11]
]
end
def test_def_with_empty_expression_receiver
assert_errors expression("def ().a; end"), "def ().a; end", [
["Expected to be able to parse receiver.", 5..5]
]
end
def test_block_beginning_with_brace_and_ending_with_end
assert_error_messages "x.each { x end", [
"Expected a newline or semicolon after statement.",
"Expected to be able to parse an expression.",
"Expected to be able to parse an expression.",
"Expected block beginning with '{' to end with '}'."
]
end
def test_double_splat_followed_by_splat_argument
expected = CallNode(
nil,
nil,
Location(),
Location(),
ArgumentsNode([
KeywordHashNode([AssocSplatNode(expression("kwargs"), Location())]),
SplatNode(Location(), expression("args"))
]),
Location(),
nil,
0,
"a"
)
assert_errors expected, "a(**kwargs, *args)", [
["Unexpected splat argument after double splat.", 12..17]
]
end
def test_arguments_after_block
expected = CallNode(
nil,
nil,
Location(),
Location(),
ArgumentsNode([
BlockArgumentNode(expression("block"), Location()),
expression("foo")
]),
Location(),
nil,
0,
"a"
)
assert_errors expected, "a(&block, foo)", [
["Unexpected argument after block argument.", 10..13]
]
end
def test_arguments_binding_power_for_and
assert_error_messages "foo(*bar and baz)", [
"Expected a ')' to close the argument list.",
"Expected a newline or semicolon after statement.",
"Expected to be able to parse an expression."
]
end
def test_splat_argument_after_keyword_argument
expected = CallNode(
nil,
nil,
Location(),
Location(),
ArgumentsNode([
KeywordHashNode(
[AssocNode(
SymbolNode(nil, Location(), Location(), "foo"),
expression("bar"),
nil
)]
),
SplatNode(Location(), expression("args"))
]),
Location(),
nil,
0,
"a"
)
assert_errors expected, "a(foo: bar, *args)", [
["Unexpected splat argument after double splat.", 12..17]
]
end
def test_module_definition_in_method_body
expected = DefNode(
Location(),
nil,
nil,
StatementsNode([ModuleNode([], Location(), ConstantReadNode(), nil, Location(), "A")]),
[],
Location(),
nil,
nil,
nil,
nil,
Location()
)
assert_errors expected, "def foo;module A;end;end", [
["Module definition in method body", 8..14]
]
end
def test_module_definition_in_method_body_within_block
expected = DefNode(
Location(),
nil,
nil,
StatementsNode(
[CallNode(
nil,
nil,
Location(),
nil,
nil,
nil,
BlockNode(
[],
nil,
StatementsNode([ModuleNode([], Location(), ConstantReadNode(), nil, Location(), "Foo")]),
Location(),
Location()
),
0,
"bar"
)]
),
[],
Location(),
nil,
nil,
nil,
nil,
Location()
)
assert_errors expected, "
def foo
bar do
module Foo;end
end
end
", [
["Module definition in method body", 40..46]
]
end
def test_class_definition_in_method_body
expected = DefNode(
Location(),
nil,
nil,
StatementsNode(
[ClassNode(
[],
Location(),
ConstantReadNode(),
nil,
nil,
nil,
Location(),
"A"
)]
),
[],
Location(),
nil,
nil,
nil,
nil,
Location()
)
assert_errors expected, "def foo;class A;end;end", [
["Class definition in method body", 8..13]
]
end
def test_bad_arguments
expected = DefNode(
Location(),
nil,
ParametersNode([
RequiredParameterNode(:A),
RequiredParameterNode(:@a),
RequiredParameterNode(:$A),
RequiredParameterNode(:@@a),
], [], [], nil, [], nil, nil),
nil,
[:A, :@a, :$A, :@@a],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(A, @a, $A, @@a);end", [
["Formal argument cannot be a constant", 8..9],
["Formal argument cannot be an instance variable", 11..13],
["Formal argument cannot be a global variable", 15..17],
["Formal argument cannot be a class variable", 19..22],
]
end
def test_cannot_assign_to_a_reserved_numbered_parameter
expected = BeginNode(
Location(),
StatementsNode([
LocalVariableWriteNode(:_1, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_2, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_3, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_4, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_5, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_6, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_7, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_8, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_9, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location()),
LocalVariableWriteNode(:_10, 0, SymbolNode(Location(), Location(), nil, "a"), Location(), Location())
]),
nil,
nil,
nil,
Location()
)
source = <<~RUBY
begin
_1=:a;_2=:a;_3=:a;_4=:a;_5=:a
_6=:a;_7=:a;_8=:a;_9=:a;_10=:a
end
RUBY
assert_errors expected, source, [
["reserved for numbered parameter", 8..10],
["reserved for numbered parameter", 14..16],
["reserved for numbered parameter", 20..22],
["reserved for numbered parameter", 26..28],
["reserved for numbered parameter", 32..34],
["reserved for numbered parameter", 40..42],
["reserved for numbered parameter", 46..48],
["reserved for numbered parameter", 52..54],
["reserved for numbered parameter", 58..60],
]
end
def test_do_not_allow_trailing_commas_in_method_parameters
expected = DefNode(
Location(),
nil,
ParametersNode(
[RequiredParameterNode(:a), RequiredParameterNode(:b), RequiredParameterNode(:c)],
[],
[],
nil,
[],
nil,
nil
),
nil,
[:a, :b, :c],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(a,b,c,);end", [
["Unexpected ','.", 13..14]
]
end
def test_do_not_allow_trailing_commas_in_lambda_parameters
expected = LambdaNode(
[:a, :b],
Location(),
Location(),
Location(),
BlockParametersNode(
ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], [], nil, [], nil, nil),
[],
Location(),
Location()
),
nil
)
assert_errors expected, "-> (a, b, ) {}", [
["Unexpected ','.", 8..9]
]
end
def test_do_not_allow_multiple_codepoints_in_a_single_character_literal
expected = StringNode(Location(), Location(), nil, "\u0001\u0002")
assert_errors expected, '?\u{0001 0002}', [
["Multiple codepoints at single character literal", 9..12]
]
end
def test_do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation
expected = StringNode(Location(), Location(), Location(), "\u0001")
assert_errors expected, '"\u{0000001}"', [
["invalid Unicode escape.", 4..11],
["invalid Unicode escape.", 4..11]
]
end
def test_do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation
expected = StringNode(Location(), Location(), Location(), "\u0000z}")
assert_errors expected, '"\u{000z}"', [
["unterminated Unicode escape", 7..7],
["unterminated Unicode escape", 7..7]
]
end
def test_method_parameters_after_block
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[RequiredParameterNode(:a)],
nil,
[],
nil,
BlockParameterNode(Location(), Location())
),
nil,
[:block, :a],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(&block, a)\nend", [
["Unexpected parameter order", 16..17]
]
end
def test_method_with_arguments_after_anonymous_block
expected = DefNode(
Location(),
nil,
ParametersNode([], [], [RequiredParameterNode(:a)], nil, [], nil, BlockParameterNode(nil, Location())),
nil,
[:&, :a],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(&, a)\nend", [
["Unexpected parameter order", 11..12]
]
end
def test_method_parameters_after_arguments_forwarding
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[RequiredParameterNode(:a)],
nil,
[],
ForwardingParameterNode(),
nil
),
nil,
[:"...", :a],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(..., a)\nend", [
["Unexpected parameter order", 13..14]
]
end
def test_keywords_parameters_before_required_parameters
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[RequiredParameterNode(:a)],
nil,
[KeywordParameterNode(Location(), nil)],
nil,
nil
),
nil,
[:b, :a],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(b:, a)\nend", [
["Unexpected parameter order", 12..13]
]
end
def test_rest_keywords_parameters_before_required_parameters
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[],
nil,
[KeywordParameterNode(Location(), nil)],
KeywordRestParameterNode(Location(), Location()),
nil
),
nil,
[:rest, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(**rest, b:)\nend", [
["Unexpected parameter order", 16..18]
]
end
def test_double_arguments_forwarding
expected = DefNode(
Location(),
nil,
ParametersNode([], [], [], nil, [], ForwardingParameterNode(), nil),
nil,
[:"..."],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(..., ...)\nend", [
["Unexpected parameter order", 13..16]
]
end
def test_multiple_error_in_parameters_order
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[RequiredParameterNode(:a)],
nil,
[KeywordParameterNode(Location(), nil)],
KeywordRestParameterNode(Location(), Location()),
nil
),
nil,
[:args, :a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(**args, a, b:)\nend", [
["Unexpected parameter order", 16..17],
["Unexpected parameter order", 19..21]
]
end
def test_switching_to_optional_arguments_twice
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[RequiredParameterNode(:a)],
nil,
[KeywordParameterNode(Location(), nil)],
KeywordRestParameterNode(Location(), Location()),
nil
),
nil,
[:args, :a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location(),
)
assert_errors expected, "def foo(**args, a, b:)\nend", [
["Unexpected parameter order", 16..17],
["Unexpected parameter order", 19..21]
]
end
def test_switching_to_named_arguments_twice
expected = DefNode(
Location(),
nil,
ParametersNode(
[],
[],
[RequiredParameterNode(:a)],
nil,
[KeywordParameterNode(Location(), nil)],
KeywordRestParameterNode(Location(), Location()),
nil
),
nil,
[:args, :a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location(),
)
assert_errors expected, "def foo(**args, a, b:)\nend", [
["Unexpected parameter order", 16..17],
["Unexpected parameter order", 19..21]
]
end
def test_returning_to_optional_parameters_multiple_times
expected = DefNode(
Location(),
nil,
ParametersNode(
[RequiredParameterNode(:a)],
[
OptionalParameterNode(:b, Location(), Location(), IntegerNode()),
OptionalParameterNode(:d, Location(), Location(), IntegerNode())
],
[RequiredParameterNode(:c), RequiredParameterNode(:e)],
nil,
[],
nil,
nil
),
nil,
[:a, :b, :c, :d, :e],
Location(),
nil,
Location(),
Location(),
nil,
Location(),
)
assert_errors expected, "def foo(a, b = 1, c, d = 2, e)\nend", [
["Unexpected parameter order", 23..24]
]
end
def test_case_without_when_clauses_errors_on_else_clause
expected = CaseNode(
SymbolNode(Location(), Location(), nil, "a"),
[],
ElseNode(Location(), nil, Location()),
Location(),
Location()
)
assert_errors expected, "case :a\nelse\nend", [
["Unexpected else without no when clauses in case statement.", 8..12]
]
end
def test_setter_method_cannot_be_defined_in_an_endless_method_definition
expected = DefNode(
Location(),
nil,
nil,
StatementsNode([IntegerNode()]),
[],
Location(),
nil,
Location(),
Location(),
Location(),
nil
)
assert_errors expected, "def a=() = 42", [
["Setter method cannot be defined in an endless method definition", 4..6]
]
end
def test_do_not_allow_forward_arguments_in_lambda_literals
expected = LambdaNode(
[:"..."],
Location(),
Location(),
Location(),
BlockParametersNode(ParametersNode([], [], [], nil, [], ForwardingParameterNode(), nil), [], Location(), Location()),
nil
)
assert_errors expected, "->(...) {}", [
["Unexpected ...", 3..6]
]
end
def test_do_not_allow_forward_arguments_in_blocks
expected = CallNode(
nil,
nil,
Location(),
nil,
nil,
nil,
BlockNode(
[:"..."],
BlockParametersNode(ParametersNode([], [], [], nil, [], ForwardingParameterNode(), nil), [], Location(), Location()),
nil,
Location(),
Location()
),
0,
"a"
)
assert_errors expected, "a {|...|}", [
["Unexpected ...", 4..7]
]
end
def test_dont_allow_return_inside_class_body
expected = ClassNode(
[],
Location(),
ConstantReadNode(),
nil,
nil,
StatementsNode([ReturnNode(Location(), nil)]),
Location(),
"A"
)
assert_errors expected, "class A; return; end", [
["Invalid return in class/module body", 15..16]
]
end
def test_dont_allow_return_inside_module_body
expected = ModuleNode(
[],
Location(),
ConstantReadNode(),
StatementsNode([ReturnNode(Location(), nil)]),
Location(),
"A"
)
assert_errors expected, "module A; return; end", [
["Invalid return in class/module body", 16..17]
]
end
def test_dont_allow_setting_to_back_and_nth_reference
expected = BeginNode(
Location(),
StatementsNode([
GlobalVariableWriteNode(Location(), Location(), NilNode()),
GlobalVariableWriteNode(Location(), Location(), NilNode())
]),
nil,
nil,
nil,
Location()
)
assert_errors expected, "begin\n$+ = nil\n$1466 = nil\nend", [
["Can't set variable", 6..8],
["Can't set variable", 15..20]
]
end
def test_duplicated_parameter_names
# For some reason, Ripper reports no error for Ruby 3.0 when you have
# duplicated parameter names for positional parameters.
unless RUBY_VERSION < "3.1.0"
expected = DefNode(
Location(),
nil,
ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b), RequiredParameterNode(:a)], [], [], nil, [], nil, nil),
nil,
[:a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(a,b,a);end", [
["Duplicated parameter name.", 12..13]
]
end
expected = DefNode(
Location(),
nil,
ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], [], RestParameterNode(Location(), Location()), [], nil, nil),
nil,
[:a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(a,b,*a);end", [
["Duplicated parameter name.", 13..14]
]
expected = DefNode(
Location(),
nil,
ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], [], nil, [], KeywordRestParameterNode(Location(), Location()), nil),
nil,
[:a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(a,b,**a);end", [
["Duplicated parameter name.", 14..15]
]
expected = DefNode(
Location(),
nil,
ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], [], nil, [], nil, BlockParameterNode(Location(), Location())),
nil,
[:a, :b],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(a,b,&a);end", [
["Duplicated parameter name.", 13..14]
]
expected = DefNode(
Location(),
nil,
ParametersNode([], [OptionalParameterNode(:a, Location(), Location(), IntegerNode())], [RequiredParameterNode(:b)], RestParameterNode(Location(), Location()), [], nil, nil),
nil,
[:a, :b, :c],
Location(),
nil,
Location(),
Location(),
nil,
Location()
)
assert_errors expected, "def foo(a = 1,b,*c);end", [["Unexpected parameter *", 16..17]]
end
private
def assert_errors(expected, source, errors)
# Ripper behaves differently on JRuby/TruffleRuby, so only check this on CRuby
assert_nil Ripper.sexp_raw(source) if RUBY_ENGINE == "ruby"
result = YARP.parse(source)
node = result.value.statements.body.last
assert_equal_nodes(expected, node, compare_location: false)
assert_equal(errors, result.errors.map { |e| [e.message, e.location.start_offset..e.location.end_offset] })
end
def assert_error_messages(source, errors)
assert_nil Ripper.sexp_raw(source)
result = YARP.parse(source)
assert_equal(errors, result.errors.map(&:message))
end
def expression(source)
YARP.parse(source).value.statements.body.last
end
end