diff options
238 files changed, 1272 insertions, 2236 deletions
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 798fde09e5..cc4f942283 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -575,6 +575,7 @@ module Prism # This is a result specific to the `parse` and `parse_file` methods. class ParseResult < Result autoload :Comments, "prism/parse_result/comments" + autoload :Errors, "prism/parse_result/errors" autoload :Newlines, "prism/parse_result/newlines" private_constant :Comments @@ -604,6 +605,12 @@ module Prism def mark_newlines! value.accept(Newlines.new(source.offsets.size)) # steep:ignore end + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + def errors_format + Errors.new(self).format + end end # This is a result specific to the `lex` and `lex_file` methods. diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb new file mode 100644 index 0000000000..40dda3c264 --- /dev/null +++ b/lib/prism/parse_result/errors.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require "stringio" + +module Prism + class ParseResult < Result + class Errors + attr_reader :parse_result + + def initialize(parse_result) + @parse_result = parse_result + end + + def format + error_lines = {} + parse_result.errors.each do |error| + location = error.location + (location.start_line..location.end_line).each do |line| + error_lines[line] ||= [] + error_lines[line] << error + end + end + + source_lines = parse_result.source.source.lines + source_lines << "" if error_lines.key?(source_lines.size + 1) + + io = StringIO.new + source_lines.each.with_index(1) do |line, line_number| + io.puts(line) + + (error_lines.delete(line_number) || []).each do |error| + location = error.location + + case line_number + when location.start_line + io.print(" " * location.start_column + "^") + + if location.start_line == location.end_line + if location.start_column != location.end_column + io.print("~" * (location.end_column - location.start_column - 1)) + end + + io.puts(" " + error.message) + else + io.puts("~" * (line.bytesize - location.start_column)) + end + when location.end_line + io.puts("~" * location.end_column + " " + error.message) + else + io.puts("~" * line.bytesize) + end + end + end + + io.puts + io.string + end + end + end +end diff --git a/test/prism/errors/1_2_3.txt b/test/prism/errors/1_2_3.txt new file mode 100644 index 0000000000..345452911f --- /dev/null +++ b/test/prism/errors/1_2_3.txt @@ -0,0 +1,11 @@ +(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt b/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt new file mode 100644 index 0000000000..2f40a6a328 --- /dev/null +++ b/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt @@ -0,0 +1,3 @@ +alias $a $1 + ^~ invalid argument being passed to `alias`; can't make alias for the number variables + diff --git a/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt b/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt new file mode 100644 index 0000000000..b6f013bab5 --- /dev/null +++ b/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt @@ -0,0 +1,3 @@ +alias $a b + ^ invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable + diff --git a/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt b/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt new file mode 100644 index 0000000000..8863f342f0 --- /dev/null +++ b/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt @@ -0,0 +1,3 @@ +alias a $b + ^~ invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable + diff --git a/test/prism/errors/alnum_delimiters.txt b/test/prism/errors/alnum_delimiters.txt new file mode 100644 index 0000000000..c9ed06ae51 --- /dev/null +++ b/test/prism/errors/alnum_delimiters.txt @@ -0,0 +1,3 @@ +%qXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_2.txt b/test/prism/errors/alnum_delimiters_2.txt new file mode 100644 index 0000000000..3f78b434d6 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_2.txt @@ -0,0 +1,3 @@ +%QXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_3.txt b/test/prism/errors/alnum_delimiters_3.txt new file mode 100644 index 0000000000..55ef8d29a5 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_3.txt @@ -0,0 +1,3 @@ +%wXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_4.txt b/test/prism/errors/alnum_delimiters_4.txt new file mode 100644 index 0000000000..603b54debd --- /dev/null +++ b/test/prism/errors/alnum_delimiters_4.txt @@ -0,0 +1,3 @@ +%WxfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_5.txt b/test/prism/errors/alnum_delimiters_5.txt new file mode 100644 index 0000000000..31c344ea90 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_5.txt @@ -0,0 +1,3 @@ +%iXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_6.txt b/test/prism/errors/alnum_delimiters_6.txt new file mode 100644 index 0000000000..79ffbbb1b8 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_6.txt @@ -0,0 +1,3 @@ +%IXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_7.txt b/test/prism/errors/alnum_delimiters_7.txt new file mode 100644 index 0000000000..809192e031 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_7.txt @@ -0,0 +1,3 @@ +%xXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_8.txt b/test/prism/errors/alnum_delimiters_8.txt new file mode 100644 index 0000000000..abfcf119c0 --- /dev/null +++ b/test/prism/errors/alnum_delimiters_8.txt @@ -0,0 +1,3 @@ +%rXfooX +^ unknown type of %string + diff --git a/test/prism/errors/alnum_delimiters_9.txt b/test/prism/errors/alnum_delimiters_9.txt new file mode 100644 index 0000000000..ae56d7be4f --- /dev/null +++ b/test/prism/errors/alnum_delimiters_9.txt @@ -0,0 +1,3 @@ +%sXfooX +^ unknown type of %string + diff --git a/test/prism/errors/argument_after_ellipsis.txt b/test/prism/errors/argument_after_ellipsis.txt new file mode 100644 index 0000000000..3d708648a4 --- /dev/null +++ b/test/prism/errors/argument_after_ellipsis.txt @@ -0,0 +1,3 @@ +def foo(...); foo(..., 1); end + ^ unexpected argument after `...` + diff --git a/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt b/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt new file mode 100644 index 0000000000..9c3f0ae3f7 --- /dev/null +++ b/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt @@ -0,0 +1,3 @@ +def a(...); b(...); end; def c(x, y, z); b(...); end + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt b/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt new file mode 100644 index 0000000000..017ba7eec9 --- /dev/null +++ b/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt @@ -0,0 +1,3 @@ +def a(x, y, z); b(...); end + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/arguments_after_block.txt b/test/prism/errors/arguments_after_block.txt new file mode 100644 index 0000000000..2d5e06ff77 --- /dev/null +++ b/test/prism/errors/arguments_after_block.txt @@ -0,0 +1,3 @@ +a(&block, foo) + ^~~ unexpected argument after a block argument + diff --git a/test/prism/errors/arguments_binding_power_for_and.txt b/test/prism/errors/arguments_binding_power_for_and.txt new file mode 100644 index 0000000000..0585a091f4 --- /dev/null +++ b/test/prism/errors/arguments_binding_power_for_and.txt @@ -0,0 +1,5 @@ +foo(*bar and baz) + ^~~ unexpected 'and'; expected a `)` to close the arguments + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/assign_to_numbered_parameter.txt b/test/prism/errors/assign_to_numbered_parameter.txt new file mode 100644 index 0000000000..74cc0c4032 --- /dev/null +++ b/test/prism/errors/assign_to_numbered_parameter.txt @@ -0,0 +1,11 @@ +a in _1 + ^~ _1 is reserved for numbered parameters +a => _1 + ^~ _1 is reserved for numbered parameters +1 => a, _1 + ^~ _1 is reserved for numbered parameters +1 in a, _1 + ^~ _1 is reserved for numbered parameters +/(?<_1>)/ =~ a + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/bad_arguments.txt b/test/prism/errors/bad_arguments.txt new file mode 100644 index 0000000000..ea19efd3c8 --- /dev/null +++ b/test/prism/errors/bad_arguments.txt @@ -0,0 +1,6 @@ +def foo(A, @a, $A, @@a);end + ^ invalid formal argument; formal argument cannot be a constant + ^~ invalid formal argument; formal argument cannot be an instance variable + ^~ invalid formal argument; formal argument cannot be a global variable + ^~~ invalid formal argument; formal argument cannot be a class variable + diff --git a/test/prism/errors/begin_at_toplevel.txt b/test/prism/errors/begin_at_toplevel.txt new file mode 100644 index 0000000000..ce3d3b8d00 --- /dev/null +++ b/test/prism/errors/begin_at_toplevel.txt @@ -0,0 +1,3 @@ +def foo; BEGIN {}; end + ^~~~~ BEGIN is permitted only at toplevel + diff --git a/test/prism/errors/binary_range_with_left_unary_range.txt b/test/prism/errors/binary_range_with_left_unary_range.txt new file mode 100644 index 0000000000..37e41f3971 --- /dev/null +++ b/test/prism/errors/binary_range_with_left_unary_range.txt @@ -0,0 +1,7 @@ +..1.. + ^~ unexpected range operator; .. and ... are non-associative and cannot be chained +...1.. + ^~ unexpected range operator; .. and ... are non-associative and cannot be chained + ^~ unexpected .., expecting end-of-input + ^~ unexpected .., ignoring it + diff --git a/test/prism/errors/block_arg_and_block.txt b/test/prism/errors/block_arg_and_block.txt new file mode 100644 index 0000000000..c355c40475 --- /dev/null +++ b/test/prism/errors/block_arg_and_block.txt @@ -0,0 +1,3 @@ +foo(&1) { } + ^~~ both block arg and actual block given; only one block is allowed + diff --git a/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt b/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt new file mode 100644 index 0000000000..f0fa964c8a --- /dev/null +++ b/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt @@ -0,0 +1,6 @@ +x.each { x end + ^~~ unexpected 'end', expecting end-of-input + ^~~ unexpected 'end', ignoring it + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a block beginning with `{` to end with `}` + diff --git a/test/prism/errors/break_1.txt b/test/prism/errors/break_1.txt new file mode 100644 index 0000000000..e7b26ad3a0 --- /dev/null +++ b/test/prism/errors/break_1.txt @@ -0,0 +1,4 @@ +break 1,; + ^ expected an argument +^~~~~~~~ Invalid break + diff --git a/test/prism/errors/break_1_2_3.txt b/test/prism/errors/break_1_2_3.txt new file mode 100644 index 0000000000..817207cbfe --- /dev/null +++ b/test/prism/errors/break_1_2_3.txt @@ -0,0 +1,8 @@ +break(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it +^~~~~~~~~~~~~ Invalid break + diff --git a/test/prism/errors/call_with_block_and_write.txt b/test/prism/errors/call_with_block_and_write.txt new file mode 100644 index 0000000000..f63d94770e --- /dev/null +++ b/test/prism/errors/call_with_block_and_write.txt @@ -0,0 +1,4 @@ +foo {} &&= 1 +^~~~~~ unexpected write target + ^~~ unexpected operator after a call with a block + diff --git a/test/prism/errors/call_with_block_operator_write.txt b/test/prism/errors/call_with_block_operator_write.txt new file mode 100644 index 0000000000..3c36050b34 --- /dev/null +++ b/test/prism/errors/call_with_block_operator_write.txt @@ -0,0 +1,4 @@ +foo {} += 1 +^~~~~~ unexpected write target + ^~ unexpected operator after a call with a block + diff --git a/test/prism/errors/call_with_block_or_write.txt b/test/prism/errors/call_with_block_or_write.txt new file mode 100644 index 0000000000..2cced0db75 --- /dev/null +++ b/test/prism/errors/call_with_block_or_write.txt @@ -0,0 +1,4 @@ +foo {} ||= 1 +^~~~~~ unexpected write target + ^~~ unexpected operator after a call with a block + diff --git a/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt b/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt new file mode 100644 index 0000000000..750915fb1f --- /dev/null +++ b/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt @@ -0,0 +1,14 @@ +begin + _1=:a;_2=:a;_3=:a;_4=:a;_5=:a + ^~ _1 is reserved for numbered parameters + ^~ _2 is reserved for numbered parameters + ^~ _3 is reserved for numbered parameters + ^~ _4 is reserved for numbered parameters + ^~ _5 is reserved for numbered parameters + _6=:a;_7=:a;_8=:a;_9=:a;_10=:a + ^~ _6 is reserved for numbered parameters + ^~ _7 is reserved for numbered parameters + ^~ _8 is reserved for numbered parameters + ^~ _9 is reserved for numbered parameters +end + diff --git a/test/prism/errors/case_without_clauses.txt b/test/prism/errors/case_without_clauses.txt new file mode 100644 index 0000000000..3bbbfdd97f --- /dev/null +++ b/test/prism/errors/case_without_clauses.txt @@ -0,0 +1,4 @@ +case :a +^~~~ expected a `when` or `in` clause after `case` +end + diff --git a/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt b/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt new file mode 100644 index 0000000000..c5a1179fb9 --- /dev/null +++ b/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt @@ -0,0 +1,5 @@ +case :a +^~~~ expected a `when` or `in` clause after `case` +else +end + diff --git a/test/prism/errors/check_value_expression.txt b/test/prism/errors/check_value_expression.txt new file mode 100644 index 0000000000..33a472d94c --- /dev/null +++ b/test/prism/errors/check_value_expression.txt @@ -0,0 +1,20 @@ +1 => ^(return) + ^~~~~~ unexpected void value expression +while true + 1 => ^(break) + ^~~~~ unexpected void value expression + 1 => ^(next) + ^~~~ unexpected void value expression + 1 => ^(redo) + ^~~~ unexpected void value expression + 1 => ^(retry) + ^~~~~ Invalid retry without rescue + ^~~~~ unexpected void value expression + 1 => ^(2 => a) + ^~~~~~ unexpected void value expression +end +1 => ^(if 1; (return) else (return) end) + ^~~~~~ unexpected void value expression +1 => ^(unless 1; (return) else (return) end) + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/class_definition_in_method_body.txt b/test/prism/errors/class_definition_in_method_body.txt new file mode 100644 index 0000000000..fcdc5746ee --- /dev/null +++ b/test/prism/errors/class_definition_in_method_body.txt @@ -0,0 +1,3 @@ +def foo;class A;end;end + ^~~~~ unexpected class definition in method body + diff --git a/test/prism/errors/class_definition_in_method_defs.txt b/test/prism/errors/class_definition_in_method_defs.txt new file mode 100644 index 0000000000..23bee0b6fb --- /dev/null +++ b/test/prism/errors/class_definition_in_method_defs.txt @@ -0,0 +1,7 @@ +def foo(bar = class A;end);end + ^~~~~ unexpected class definition in method body +def foo;rescue;class A;end;end + ^~~~~ unexpected class definition in method body +def foo;ensure;class A;end;end + ^~~~~ unexpected class definition in method body + diff --git a/test/prism/errors/class_name.txt b/test/prism/errors/class_name.txt new file mode 100644 index 0000000000..8b75896ddb --- /dev/null +++ b/test/prism/errors/class_name.txt @@ -0,0 +1,3 @@ +class 0.X end + ^~~ unexpected constant path after `class`; class/module name must be CONSTANT + diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt new file mode 100644 index 0000000000..a4357028c6 --- /dev/null +++ b/test/prism/errors/command_call_in.txt @@ -0,0 +1,7 @@ +foo 1 in a + ^ unexpected `in` keyword in arguments + ^ unexpected local variable or method, expecting end-of-input +a = foo 2 in b + ^ unexpected `in` keyword in arguments + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls.txt b/test/prism/errors/command_calls.txt new file mode 100644 index 0000000000..19812a1d0a --- /dev/null +++ b/test/prism/errors/command_calls.txt @@ -0,0 +1,3 @@ +[a b] + ^ unexpected local variable or method; expected a `,` separator for the array elements + diff --git a/test/prism/errors/command_calls_10.txt b/test/prism/errors/command_calls_10.txt new file mode 100644 index 0000000000..f4d9f0fabc --- /dev/null +++ b/test/prism/errors/command_calls_10.txt @@ -0,0 +1,3 @@ ++a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_11.txt b/test/prism/errors/command_calls_11.txt new file mode 100644 index 0000000000..868476c0c3 --- /dev/null +++ b/test/prism/errors/command_calls_11.txt @@ -0,0 +1,3 @@ +a + b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_12.txt b/test/prism/errors/command_calls_12.txt new file mode 100644 index 0000000000..50c9ae88e3 --- /dev/null +++ b/test/prism/errors/command_calls_12.txt @@ -0,0 +1,3 @@ +a && b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_13.txt b/test/prism/errors/command_calls_13.txt new file mode 100644 index 0000000000..50dc4a84a0 --- /dev/null +++ b/test/prism/errors/command_calls_13.txt @@ -0,0 +1,3 @@ +a =~ b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_14.txt b/test/prism/errors/command_calls_14.txt new file mode 100644 index 0000000000..1b16fd3245 --- /dev/null +++ b/test/prism/errors/command_calls_14.txt @@ -0,0 +1,3 @@ +a = b, c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_15.txt b/test/prism/errors/command_calls_15.txt new file mode 100644 index 0000000000..d2409fd002 --- /dev/null +++ b/test/prism/errors/command_calls_15.txt @@ -0,0 +1,3 @@ +a = *b c + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_16.txt b/test/prism/errors/command_calls_16.txt new file mode 100644 index 0000000000..ceb07dfe30 --- /dev/null +++ b/test/prism/errors/command_calls_16.txt @@ -0,0 +1,3 @@ +a, b = c = d f + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_17.txt b/test/prism/errors/command_calls_17.txt new file mode 100644 index 0000000000..a78ac0985d --- /dev/null +++ b/test/prism/errors/command_calls_17.txt @@ -0,0 +1,5 @@ +a ? b c : d e + ^ expected a `:` after the true expression of a ternary operator + ^ unexpected ':', expecting end-of-input + ^ unexpected ':', ignoring it + diff --git a/test/prism/errors/command_calls_18.txt b/test/prism/errors/command_calls_18.txt new file mode 100644 index 0000000000..393e7e0ae6 --- /dev/null +++ b/test/prism/errors/command_calls_18.txt @@ -0,0 +1,3 @@ +defined? a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_19.txt b/test/prism/errors/command_calls_19.txt new file mode 100644 index 0000000000..e045187f1e --- /dev/null +++ b/test/prism/errors/command_calls_19.txt @@ -0,0 +1,3 @@ +! ! a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_2.txt b/test/prism/errors/command_calls_2.txt new file mode 100644 index 0000000000..b0983c015b --- /dev/null +++ b/test/prism/errors/command_calls_2.txt @@ -0,0 +1,6 @@ +{a: b c} + ^ expected a `}` to close the hash literal + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected '}', expecting end-of-input + ^ unexpected '}', ignoring it + diff --git a/test/prism/errors/command_calls_20.txt b/test/prism/errors/command_calls_20.txt new file mode 100644 index 0000000000..3058ebce96 --- /dev/null +++ b/test/prism/errors/command_calls_20.txt @@ -0,0 +1,3 @@ +def f a = b c; end + ^ expected a delimiter to close the parameters + diff --git a/test/prism/errors/command_calls_21.txt b/test/prism/errors/command_calls_21.txt new file mode 100644 index 0000000000..73d8f83539 --- /dev/null +++ b/test/prism/errors/command_calls_21.txt @@ -0,0 +1,5 @@ +def f(a = b c); end + ^ unexpected local variable or method; expected a `)` to close the parameters + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_22.txt b/test/prism/errors/command_calls_22.txt new file mode 100644 index 0000000000..5a234e04e8 --- /dev/null +++ b/test/prism/errors/command_calls_22.txt @@ -0,0 +1,3 @@ +a = b rescue c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_23.txt b/test/prism/errors/command_calls_23.txt new file mode 100644 index 0000000000..db85589ffd --- /dev/null +++ b/test/prism/errors/command_calls_23.txt @@ -0,0 +1,3 @@ +def a = b rescue c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_24.txt b/test/prism/errors/command_calls_24.txt new file mode 100644 index 0000000000..3046b36dc1 --- /dev/null +++ b/test/prism/errors/command_calls_24.txt @@ -0,0 +1,5 @@ +->a=b c{} + ^ expected a `do` keyword or a `{` to open the lambda block + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a lambda block beginning with `do` to end with `end` + diff --git a/test/prism/errors/command_calls_25.txt b/test/prism/errors/command_calls_25.txt new file mode 100644 index 0000000000..5fddd90fdd --- /dev/null +++ b/test/prism/errors/command_calls_25.txt @@ -0,0 +1,8 @@ +->(a=b c){} + ^ expected a matching `)` + ^ expected a `do` keyword or a `{` to open the lambda block + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a lambda block beginning with `do` to end with `end` + diff --git a/test/prism/errors/command_calls_26.txt b/test/prism/errors/command_calls_26.txt new file mode 100644 index 0000000000..29ed4cb903 --- /dev/null +++ b/test/prism/errors/command_calls_26.txt @@ -0,0 +1,3 @@ +case; when a b; end + ^ expected a delimiter after the predicates of a `when` clause + diff --git a/test/prism/errors/command_calls_27.txt b/test/prism/errors/command_calls_27.txt new file mode 100644 index 0000000000..8d1c3ee077 --- /dev/null +++ b/test/prism/errors/command_calls_27.txt @@ -0,0 +1,3 @@ +case; in a if a b; end +^~~~ expected a predicate for a case matching statement + diff --git a/test/prism/errors/command_calls_28.txt b/test/prism/errors/command_calls_28.txt new file mode 100644 index 0000000000..4bfe88d67b --- /dev/null +++ b/test/prism/errors/command_calls_28.txt @@ -0,0 +1,3 @@ +case; in a unless a b; end +^~~~ expected a predicate for a case matching statement + diff --git a/test/prism/errors/command_calls_29.txt b/test/prism/errors/command_calls_29.txt new file mode 100644 index 0000000000..eae012ab44 --- /dev/null +++ b/test/prism/errors/command_calls_29.txt @@ -0,0 +1,3 @@ +begin; rescue a b; end + ^ expected a closing delimiter for the `rescue` clause + diff --git a/test/prism/errors/command_calls_3.txt b/test/prism/errors/command_calls_3.txt new file mode 100644 index 0000000000..77af72b904 --- /dev/null +++ b/test/prism/errors/command_calls_3.txt @@ -0,0 +1,3 @@ +...a b + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_30.txt b/test/prism/errors/command_calls_30.txt new file mode 100644 index 0000000000..48e35685cb --- /dev/null +++ b/test/prism/errors/command_calls_30.txt @@ -0,0 +1,3 @@ +begin; rescue a b => c; end + ^ expected a closing delimiter for the `rescue` clause + diff --git a/test/prism/errors/command_calls_4.txt b/test/prism/errors/command_calls_4.txt new file mode 100644 index 0000000000..4be14e57e4 --- /dev/null +++ b/test/prism/errors/command_calls_4.txt @@ -0,0 +1,3 @@ +if ...a b; end + ^ expected `then` or `;` or '\n' + diff --git a/test/prism/errors/command_calls_5.txt b/test/prism/errors/command_calls_5.txt new file mode 100644 index 0000000000..799a6c1136 --- /dev/null +++ b/test/prism/errors/command_calls_5.txt @@ -0,0 +1,3 @@ +a b, c d + ^ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/command_calls_6.txt b/test/prism/errors/command_calls_6.txt new file mode 100644 index 0000000000..6f09d36e94 --- /dev/null +++ b/test/prism/errors/command_calls_6.txt @@ -0,0 +1,6 @@ +a(b, c d) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_7.txt b/test/prism/errors/command_calls_7.txt new file mode 100644 index 0000000000..b5d74209fa --- /dev/null +++ b/test/prism/errors/command_calls_7.txt @@ -0,0 +1,6 @@ +a(*b c) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_8.txt b/test/prism/errors/command_calls_8.txt new file mode 100644 index 0000000000..e574063e72 --- /dev/null +++ b/test/prism/errors/command_calls_8.txt @@ -0,0 +1,6 @@ +a(**b c) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/command_calls_9.txt b/test/prism/errors/command_calls_9.txt new file mode 100644 index 0000000000..69515d959c --- /dev/null +++ b/test/prism/errors/command_calls_9.txt @@ -0,0 +1,6 @@ +a(&b c) + ^ unexpected local variable or method; expected a `)` to close the arguments + ^ unexpected local variable or method, expecting end-of-input + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/conditional_predicate_closed.txt b/test/prism/errors/conditional_predicate_closed.txt new file mode 100644 index 0000000000..6655fd2b1c --- /dev/null +++ b/test/prism/errors/conditional_predicate_closed.txt @@ -0,0 +1,6 @@ +if 0 0; elsif 0 0; end + ^ expected `then` or `;` or '\n' + ^ expected `then` or `;` or '\n' +unless 0 0; end + ^ expected `then` or `;` or '\n' + diff --git a/test/prism/errors/constant_assignment_in_method.txt b/test/prism/errors/constant_assignment_in_method.txt new file mode 100644 index 0000000000..1ee49bffe6 --- /dev/null +++ b/test/prism/errors/constant_assignment_in_method.txt @@ -0,0 +1,3 @@ +def foo();A=1;end + ^~~ dynamic constant assignment + diff --git a/test/prism/errors/constant_path_with_invalid_token_after.txt b/test/prism/errors/constant_path_with_invalid_token_after.txt new file mode 100644 index 0000000000..acb6dba30a --- /dev/null +++ b/test/prism/errors/constant_path_with_invalid_token_after.txt @@ -0,0 +1,4 @@ +A::$b + ^ expected a constant after the `::` operator + ^~ unexpected global variable, expecting end-of-input + diff --git a/test/prism/errors/content_after_unterminated_heredoc.txt b/test/prism/errors/content_after_unterminated_heredoc.txt new file mode 100644 index 0000000000..43815cd9d0 --- /dev/null +++ b/test/prism/errors/content_after_unterminated_heredoc.txt @@ -0,0 +1,2 @@ +<<~FOO.foo + ^~~ unterminated heredoc; can't find string "FOO" anywhere before EOF diff --git a/test/prism/errors/cr_without_lf_in_percent_expression.txt b/test/prism/errors/cr_without_lf_in_percent_expression.txt new file mode 100644 index 0000000000..903f8b4b4a --- /dev/null +++ b/test/prism/errors/cr_without_lf_in_percent_expression.txt @@ -0,0 +1,3 @@ +%
+ ^ unterminated string meets end of file + diff --git a/test/prism/errors/def_with_empty_expression_receiver.txt b/test/prism/errors/def_with_empty_expression_receiver.txt new file mode 100644 index 0000000000..153fe8a1c6 --- /dev/null +++ b/test/prism/errors/def_with_empty_expression_receiver.txt @@ -0,0 +1,3 @@ +def ().a; end + ^ expected a receiver for the method definition + diff --git a/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt b/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt new file mode 100644 index 0000000000..1aefc07f1a --- /dev/null +++ b/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt @@ -0,0 +1,4 @@ +def (a); end + ^ expected a `.` or `::` after the receiver in a method definition + ^ unexpected ';'; expected a method name + diff --git a/test/prism/errors/def_with_multiple_statements_receiver.txt b/test/prism/errors/def_with_multiple_statements_receiver.txt new file mode 100644 index 0000000000..80c9d4c190 --- /dev/null +++ b/test/prism/errors/def_with_multiple_statements_receiver.txt @@ -0,0 +1,10 @@ +def ( +a +b +^ expected a matching `)` +^ expected a `.` or `::` after the receiver in a method definition + ^ expected a delimiter to close the parameters +).c; end +^ unexpected ')', ignoring it + ^ unexpected '.', ignoring it + diff --git a/test/prism/errors/defining_numbered_parameter.txt b/test/prism/errors/defining_numbered_parameter.txt new file mode 100644 index 0000000000..2bf05d9563 --- /dev/null +++ b/test/prism/errors/defining_numbered_parameter.txt @@ -0,0 +1,3 @@ +def _1; end + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/defining_numbered_parameter_2.txt b/test/prism/errors/defining_numbered_parameter_2.txt new file mode 100644 index 0000000000..dc4739b126 --- /dev/null +++ b/test/prism/errors/defining_numbered_parameter_2.txt @@ -0,0 +1,3 @@ +def self._1; end + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt b/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt new file mode 100644 index 0000000000..953b9589d1 --- /dev/null +++ b/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt @@ -0,0 +1,4 @@ +"\u{000z}" + ^ invalid Unicode escape sequence + ^ unterminated Unicode escape + diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt new file mode 100644 index 0000000000..df49557617 --- /dev/null +++ b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt @@ -0,0 +1,3 @@ +a {|...|} + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt new file mode 100644 index 0000000000..c2405a5c66 --- /dev/null +++ b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt @@ -0,0 +1,3 @@ +->(...) {} + ^~~ unexpected ... when the parent method is not forwarding + diff --git a/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt b/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt new file mode 100644 index 0000000000..50795c9353 --- /dev/null +++ b/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt @@ -0,0 +1,3 @@ +"\u{0000001}" + ^~~~~~~ invalid Unicode escape sequence; maximum length is 6 digits + diff --git a/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt b/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt new file mode 100644 index 0000000000..1a93dc6c69 --- /dev/null +++ b/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt @@ -0,0 +1,3 @@ +?\u{0001 0002} + ^~~ invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed + diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt b/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt new file mode 100644 index 0000000000..11f23f0345 --- /dev/null +++ b/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt @@ -0,0 +1,3 @@ +-> (a, b, ) {} + ^ unexpected `,` in parameters + diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt b/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt new file mode 100644 index 0000000000..c0fec0c704 --- /dev/null +++ b/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt @@ -0,0 +1,3 @@ +def foo(a,b,c,);end + ^ unexpected `,` in parameters + diff --git a/test/prism/errors/dont_allow_return_inside_class_body.txt b/test/prism/errors/dont_allow_return_inside_class_body.txt new file mode 100644 index 0000000000..286eba2103 --- /dev/null +++ b/test/prism/errors/dont_allow_return_inside_class_body.txt @@ -0,0 +1,3 @@ +class A; return; end + ^~~~~~ Invalid return in class/module body + diff --git a/test/prism/errors/dont_allow_return_inside_module_body.txt b/test/prism/errors/dont_allow_return_inside_module_body.txt new file mode 100644 index 0000000000..85dd619a93 --- /dev/null +++ b/test/prism/errors/dont_allow_return_inside_module_body.txt @@ -0,0 +1,3 @@ +module A; return; end + ^~~~~~ Invalid return in class/module body + diff --git a/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt b/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt new file mode 100644 index 0000000000..71b5b94589 --- /dev/null +++ b/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt @@ -0,0 +1,7 @@ +begin +$+ = nil +^~ Can't set variable $+ +$1466 = nil +^~~~~ Can't set variable $1466 +end + diff --git a/test/prism/errors/double_arguments_forwarding.txt b/test/prism/errors/double_arguments_forwarding.txt new file mode 100644 index 0000000000..29c78f8c80 --- /dev/null +++ b/test/prism/errors/double_arguments_forwarding.txt @@ -0,0 +1,4 @@ +def foo(..., ...) + ^~~ unexpected parameter order +end + diff --git a/test/prism/errors/double_scope_numbered_parameters.txt b/test/prism/errors/double_scope_numbered_parameters.txt new file mode 100644 index 0000000000..0bb9df4ede --- /dev/null +++ b/test/prism/errors/double_scope_numbered_parameters.txt @@ -0,0 +1,3 @@ +-> { _1 + -> { _2 } } + ^~ numbered parameter is already used in outer block + diff --git a/test/prism/errors/double_splat_followed_by_splat_argument.txt b/test/prism/errors/double_splat_followed_by_splat_argument.txt new file mode 100644 index 0000000000..b2aec1167e --- /dev/null +++ b/test/prism/errors/double_splat_followed_by_splat_argument.txt @@ -0,0 +1,3 @@ +a(**kwargs, *args) + ^~~~~ unexpected `*` splat argument after a `**` keyword splat argument + diff --git a/test/prism/errors/duplicate_pattern_capture.txt b/test/prism/errors/duplicate_pattern_capture.txt new file mode 100644 index 0000000000..4b48fd3118 --- /dev/null +++ b/test/prism/errors/duplicate_pattern_capture.txt @@ -0,0 +1,17 @@ +case (); in [a, a]; end + ^ duplicated variable name +case (); in [a, *a]; end + ^ duplicated variable name +case (); in {a: a, b: a}; end + ^ duplicated variable name +case (); in {a: a, **a}; end + ^ duplicated variable name +case (); in [a, {a:}]; end + ^ duplicated variable name +case (); in [a, {a: {a: {a: [a]}}}]; end + ^ duplicated variable name +case (); in a => a; end + ^ duplicated variable name +case (); in [A => a, {a: b => a}]; end + ^ duplicated variable name + diff --git a/test/prism/errors/duplicate_pattern_hash_key.txt b/test/prism/errors/duplicate_pattern_hash_key.txt new file mode 100644 index 0000000000..201b51234f --- /dev/null +++ b/test/prism/errors/duplicate_pattern_hash_key.txt @@ -0,0 +1,4 @@ +case (); in {a:, a:}; end + ^~ duplicated key name + ^ duplicated variable name + diff --git a/test/prism/errors/duplicate_pattern_hash_key_2.txt b/test/prism/errors/duplicate_pattern_hash_key_2.txt new file mode 100644 index 0000000000..66756c454a --- /dev/null +++ b/test/prism/errors/duplicate_pattern_hash_key_2.txt @@ -0,0 +1,3 @@ +case (); in {a:1, a:2}; end + ^~ duplicated key name + diff --git a/test/prism/errors/duplicated_parameter_names.txt b/test/prism/errors/duplicated_parameter_names.txt new file mode 100644 index 0000000000..7b82685ca3 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names.txt @@ -0,0 +1,3 @@ +def foo(a,b,a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_2.txt b/test/prism/errors/duplicated_parameter_names_2.txt new file mode 100644 index 0000000000..8396993d56 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_2.txt @@ -0,0 +1,3 @@ +def foo(a,b,*a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_3.txt b/test/prism/errors/duplicated_parameter_names_3.txt new file mode 100644 index 0000000000..437a6623c3 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_3.txt @@ -0,0 +1,3 @@ +def foo(a,b,**a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_4.txt b/test/prism/errors/duplicated_parameter_names_4.txt new file mode 100644 index 0000000000..a420dd8a69 --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_4.txt @@ -0,0 +1,3 @@ +def foo(a,b,&a);end + ^ duplicated argument name + diff --git a/test/prism/errors/duplicated_parameter_names_5.txt b/test/prism/errors/duplicated_parameter_names_5.txt new file mode 100644 index 0000000000..694d3a668c --- /dev/null +++ b/test/prism/errors/duplicated_parameter_names_5.txt @@ -0,0 +1,3 @@ +def foo(a = 1,b,*c);end + ^ unexpected parameter `*` + diff --git a/test/prism/errors/ellipsis_in_no_paren_call.txt b/test/prism/errors/ellipsis_in_no_paren_call.txt new file mode 100644 index 0000000000..87a847d192 --- /dev/null +++ b/test/prism/errors/ellipsis_in_no_paren_call.txt @@ -0,0 +1,3 @@ +def foo(...); foo 1, ...; end + ^~~ unexpected `...` in an non-parenthesized call + diff --git a/test/prism/errors/for_loops_index_missing.txt b/test/prism/errors/for_loops_index_missing.txt new file mode 100644 index 0000000000..a57c22b044 --- /dev/null +++ b/test/prism/errors/for_loops_index_missing.txt @@ -0,0 +1,5 @@ +for in 1..10 +^~~ expected an index after `for` +i +end + diff --git a/test/prism/errors/for_loops_only_end.txt b/test/prism/errors/for_loops_only_end.txt new file mode 100644 index 0000000000..94cc5270b5 --- /dev/null +++ b/test/prism/errors/for_loops_only_end.txt @@ -0,0 +1,5 @@ +for end +^~~ expected an index after `for` + ^ expected an `in` after the index in a `for` statement + ^ expected a collection after the `in` in a `for` statement + diff --git a/test/prism/errors/forwarding_arg_after_keyword_rest.txt b/test/prism/errors/forwarding_arg_after_keyword_rest.txt new file mode 100644 index 0000000000..86fe4aad93 --- /dev/null +++ b/test/prism/errors/forwarding_arg_after_keyword_rest.txt @@ -0,0 +1,3 @@ +def f(**,...);end + ^~~ unexpected parameter order + diff --git a/test/prism/errors/forwarding_arg_and_block.txt b/test/prism/errors/forwarding_arg_and_block.txt new file mode 100644 index 0000000000..65c75a5d7c --- /dev/null +++ b/test/prism/errors/forwarding_arg_and_block.txt @@ -0,0 +1,3 @@ +def foo(...) = foo(...) { } + ^~~ both block arg and actual block given; only one block is allowed + diff --git a/test/prism/errors/incomplete_instance_var_string.txt b/test/prism/errors/incomplete_instance_var_string.txt new file mode 100644 index 0000000000..b28947fc0e --- /dev/null +++ b/test/prism/errors/incomplete_instance_var_string.txt @@ -0,0 +1,4 @@ +%@#@@# + ^ '@' without identifiers is not allowed as an instance variable name + ^ unexpected instance variable, expecting end-of-input + diff --git a/test/prism/errors/index_call_with_block_and_write.txt b/test/prism/errors/index_call_with_block_and_write.txt new file mode 100644 index 0000000000..3d92fbfea7 --- /dev/null +++ b/test/prism/errors/index_call_with_block_and_write.txt @@ -0,0 +1,5 @@ +foo[1] {} &&= 1 +^~~~~~~~~ unexpected write target + ^~~ unexpected operator after a call with arguments + ^~~ unexpected operator after a call with a block + diff --git a/test/prism/errors/index_call_with_block_operator_write.txt b/test/prism/errors/index_call_with_block_operator_write.txt new file mode 100644 index 0000000000..96c413cd39 --- /dev/null +++ b/test/prism/errors/index_call_with_block_operator_write.txt @@ -0,0 +1,5 @@ +foo[1] {} += 1 +^~~~~~~~~ unexpected write target + ^~ unexpected operator after a call with arguments + ^~ unexpected operator after a call with a block + diff --git a/test/prism/errors/index_call_with_block_or_write.txt b/test/prism/errors/index_call_with_block_or_write.txt new file mode 100644 index 0000000000..2d250fba06 --- /dev/null +++ b/test/prism/errors/index_call_with_block_or_write.txt @@ -0,0 +1,5 @@ +foo[1] {} ||= 1 +^~~~~~~~~ unexpected write target + ^~~ unexpected operator after a call with arguments + ^~~ unexpected operator after a call with a block + diff --git a/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt b/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt new file mode 100644 index 0000000000..8e78753b1c --- /dev/null +++ b/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt @@ -0,0 +1,3 @@ +/#{foo}/AZaz + ^~~~~ unknown regexp options - AZaz + diff --git a/test/prism/errors/invalid_global_variable_write.txt b/test/prism/errors/invalid_global_variable_write.txt new file mode 100644 index 0000000000..9d9018bcf1 --- /dev/null +++ b/test/prism/errors/invalid_global_variable_write.txt @@ -0,0 +1,4 @@ +$', +^~ Can't set variable $' +^~ unexpected write target + diff --git a/test/prism/errors/invalid_hex_escape.txt b/test/prism/errors/invalid_hex_escape.txt new file mode 100644 index 0000000000..4fb847f6d2 --- /dev/null +++ b/test/prism/errors/invalid_hex_escape.txt @@ -0,0 +1,3 @@ +"\xx" + ^~ invalid hex escape sequence + diff --git a/test/prism/errors/invalid_multi_target.txt b/test/prism/errors/invalid_multi_target.txt new file mode 100644 index 0000000000..9756278b0c --- /dev/null +++ b/test/prism/errors/invalid_multi_target.txt @@ -0,0 +1,3 @@ +foo, +^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_10.txt b/test/prism/errors/invalid_multi_target_10.txt new file mode 100644 index 0000000000..0e87b67d36 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_10.txt @@ -0,0 +1,3 @@ +Foo, +^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_11.txt b/test/prism/errors/invalid_multi_target_11.txt new file mode 100644 index 0000000000..8185cde79e --- /dev/null +++ b/test/prism/errors/invalid_multi_target_11.txt @@ -0,0 +1,3 @@ +::Foo, +^~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_12.txt b/test/prism/errors/invalid_multi_target_12.txt new file mode 100644 index 0000000000..f511a8a76f --- /dev/null +++ b/test/prism/errors/invalid_multi_target_12.txt @@ -0,0 +1,3 @@ +Foo::Foo, +^~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_13.txt b/test/prism/errors/invalid_multi_target_13.txt new file mode 100644 index 0000000000..7c9a3fb4e1 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_13.txt @@ -0,0 +1,3 @@ +Foo::foo, +^~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_14.txt b/test/prism/errors/invalid_multi_target_14.txt new file mode 100644 index 0000000000..88dc08de92 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_14.txt @@ -0,0 +1,3 @@ +foo[foo], +^~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_15.txt b/test/prism/errors/invalid_multi_target_15.txt new file mode 100644 index 0000000000..c140833467 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_15.txt @@ -0,0 +1,3 @@ +(foo, bar) +^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_16.txt b/test/prism/errors/invalid_multi_target_16.txt new file mode 100644 index 0000000000..20ea56331f --- /dev/null +++ b/test/prism/errors/invalid_multi_target_16.txt @@ -0,0 +1,3 @@ +foo((foo, bar)) + ^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_17.txt b/test/prism/errors/invalid_multi_target_17.txt new file mode 100644 index 0000000000..da1ced0c59 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_17.txt @@ -0,0 +1,3 @@ +foo((*)) + ^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_18.txt b/test/prism/errors/invalid_multi_target_18.txt new file mode 100644 index 0000000000..2beed193b4 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_18.txt @@ -0,0 +1,3 @@ +foo(((foo, bar), *)) + ^~~~~~~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_19.txt b/test/prism/errors/invalid_multi_target_19.txt new file mode 100644 index 0000000000..b5e3e6999a --- /dev/null +++ b/test/prism/errors/invalid_multi_target_19.txt @@ -0,0 +1,3 @@ +(foo, bar) + 1 +^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_2.txt b/test/prism/errors/invalid_multi_target_2.txt new file mode 100644 index 0000000000..68a7bbc305 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_2.txt @@ -0,0 +1,3 @@ +foo = 1; foo, + ^~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_20.txt b/test/prism/errors/invalid_multi_target_20.txt new file mode 100644 index 0000000000..e800bcf204 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_20.txt @@ -0,0 +1,3 @@ +(foo, bar) in baz +^~~~~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_3.txt b/test/prism/errors/invalid_multi_target_3.txt new file mode 100644 index 0000000000..51e6207603 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_3.txt @@ -0,0 +1,3 @@ +foo.bar, +^~~~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_4.txt b/test/prism/errors/invalid_multi_target_4.txt new file mode 100644 index 0000000000..f4c3599ffe --- /dev/null +++ b/test/prism/errors/invalid_multi_target_4.txt @@ -0,0 +1,3 @@ +*foo, +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_5.txt b/test/prism/errors/invalid_multi_target_5.txt new file mode 100644 index 0000000000..5d143a3f5d --- /dev/null +++ b/test/prism/errors/invalid_multi_target_5.txt @@ -0,0 +1,3 @@ +@foo, +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_6.txt b/test/prism/errors/invalid_multi_target_6.txt new file mode 100644 index 0000000000..6d15893f57 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_6.txt @@ -0,0 +1,3 @@ +@@foo, +^~~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_7.txt b/test/prism/errors/invalid_multi_target_7.txt new file mode 100644 index 0000000000..451f9f0a00 --- /dev/null +++ b/test/prism/errors/invalid_multi_target_7.txt @@ -0,0 +1,3 @@ +$foo, +^~~~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_8.txt b/test/prism/errors/invalid_multi_target_8.txt new file mode 100644 index 0000000000..fdbe272f9a --- /dev/null +++ b/test/prism/errors/invalid_multi_target_8.txt @@ -0,0 +1,4 @@ +$1, +^~ Can't set variable $1 +^~ unexpected write target + diff --git a/test/prism/errors/invalid_multi_target_9.txt b/test/prism/errors/invalid_multi_target_9.txt new file mode 100644 index 0000000000..038f355c5d --- /dev/null +++ b/test/prism/errors/invalid_multi_target_9.txt @@ -0,0 +1,4 @@ +$+, +^~ Can't set variable $+ +^~ unexpected write target + diff --git a/test/prism/errors/invalid_number_underscores.txt b/test/prism/errors/invalid_number_underscores.txt new file mode 100644 index 0000000000..8fc79ed7a2 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores.txt @@ -0,0 +1,3 @@ +1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_10.txt b/test/prism/errors/invalid_number_underscores_10.txt new file mode 100644 index 0000000000..53b0cc0719 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_10.txt @@ -0,0 +1,3 @@ +01_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_11.txt b/test/prism/errors/invalid_number_underscores_11.txt new file mode 100644 index 0000000000..469110f86f --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_11.txt @@ -0,0 +1,3 @@ +0d1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_12.txt b/test/prism/errors/invalid_number_underscores_12.txt new file mode 100644 index 0000000000..a9b63a4b6c --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_12.txt @@ -0,0 +1,3 @@ +0x1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_2.txt b/test/prism/errors/invalid_number_underscores_2.txt new file mode 100644 index 0000000000..2762e08790 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_2.txt @@ -0,0 +1,3 @@ +0b1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_3.txt b/test/prism/errors/invalid_number_underscores_3.txt new file mode 100644 index 0000000000..23f1e0b10b --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_3.txt @@ -0,0 +1,3 @@ +0o1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_4.txt b/test/prism/errors/invalid_number_underscores_4.txt new file mode 100644 index 0000000000..ced149752f --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_4.txt @@ -0,0 +1,3 @@ +01__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_5.txt b/test/prism/errors/invalid_number_underscores_5.txt new file mode 100644 index 0000000000..5e3f2bf682 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_5.txt @@ -0,0 +1,3 @@ +0d1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_6.txt b/test/prism/errors/invalid_number_underscores_6.txt new file mode 100644 index 0000000000..225b654248 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_6.txt @@ -0,0 +1,3 @@ +0x1__1 + ^ invalid underscore placement in number + diff --git a/test/prism/errors/invalid_number_underscores_7.txt b/test/prism/errors/invalid_number_underscores_7.txt new file mode 100644 index 0000000000..d953b4cbc4 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_7.txt @@ -0,0 +1,3 @@ +1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_8.txt b/test/prism/errors/invalid_number_underscores_8.txt new file mode 100644 index 0000000000..cbdcd95d8f --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_8.txt @@ -0,0 +1,3 @@ +0b1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_number_underscores_9.txt b/test/prism/errors/invalid_number_underscores_9.txt new file mode 100644 index 0000000000..173282ffb2 --- /dev/null +++ b/test/prism/errors/invalid_number_underscores_9.txt @@ -0,0 +1,3 @@ +0o1_1_ + ^ trailing '_' in number + diff --git a/test/prism/errors/invalid_operator_write_dot.txt b/test/prism/errors/invalid_operator_write_dot.txt new file mode 100644 index 0000000000..666817e60f --- /dev/null +++ b/test/prism/errors/invalid_operator_write_dot.txt @@ -0,0 +1,3 @@ +foo.+= 1 + ^ unexpected write target + diff --git a/test/prism/errors/invalid_operator_write_fcall.txt b/test/prism/errors/invalid_operator_write_fcall.txt new file mode 100644 index 0000000000..2748bf3291 --- /dev/null +++ b/test/prism/errors/invalid_operator_write_fcall.txt @@ -0,0 +1,3 @@ +foo! += 1 +^~~~ unexpected write target + diff --git a/test/prism/errors/it_with_ordinary_parameter.txt b/test/prism/errors/it_with_ordinary_parameter.txt new file mode 100644 index 0000000000..0fc34e9cc8 --- /dev/null +++ b/test/prism/errors/it_with_ordinary_parameter.txt @@ -0,0 +1,3 @@ +proc { || it } + ^~ `it` is not allowed when an ordinary parameter is defined + diff --git a/test/prism/errors/keywords_parameters_before_required_parameters.txt b/test/prism/errors/keywords_parameters_before_required_parameters.txt new file mode 100644 index 0000000000..42d036e950 --- /dev/null +++ b/test/prism/errors/keywords_parameters_before_required_parameters.txt @@ -0,0 +1,4 @@ +def foo(b:, a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/loop_conditional_is_closed.txt b/test/prism/errors/loop_conditional_is_closed.txt new file mode 100644 index 0000000000..2be1353319 --- /dev/null +++ b/test/prism/errors/loop_conditional_is_closed.txt @@ -0,0 +1,4 @@ +while 0 0; foo; end; until 0 0; foo; end + ^ expected a predicate expression for the `while` statement + ^ expected a predicate expression for the `until` statement + diff --git a/test/prism/errors/match_plus.txt b/test/prism/errors/match_plus.txt new file mode 100644 index 0000000000..5e349a96ad --- /dev/null +++ b/test/prism/errors/match_plus.txt @@ -0,0 +1,7 @@ +a in b + c + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it +a => b + c + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it + diff --git a/test/prism/errors/method_parameters_after_arguments_forwarding.txt b/test/prism/errors/method_parameters_after_arguments_forwarding.txt new file mode 100644 index 0000000000..ec2aefda1d --- /dev/null +++ b/test/prism/errors/method_parameters_after_arguments_forwarding.txt @@ -0,0 +1,4 @@ +def foo(..., a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/method_parameters_after_block.txt b/test/prism/errors/method_parameters_after_block.txt new file mode 100644 index 0000000000..6e2091d5d1 --- /dev/null +++ b/test/prism/errors/method_parameters_after_block.txt @@ -0,0 +1,4 @@ +def foo(&block, a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/method_with_arguments_after_anonymous_block.txt b/test/prism/errors/method_with_arguments_after_anonymous_block.txt new file mode 100644 index 0000000000..0d986b3c01 --- /dev/null +++ b/test/prism/errors/method_with_arguments_after_anonymous_block.txt @@ -0,0 +1,4 @@ +def foo(&, a) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/missing_terminator_in_parentheses.txt b/test/prism/errors/missing_terminator_in_parentheses.txt new file mode 100644 index 0000000000..af4b698f0c --- /dev/null +++ b/test/prism/errors/missing_terminator_in_parentheses.txt @@ -0,0 +1,3 @@ +(0 0) + ^ unexpected integer, expecting end-of-input + diff --git a/test/prism/errors/module_definition_in_method_body.txt b/test/prism/errors/module_definition_in_method_body.txt new file mode 100644 index 0000000000..59900c96dd --- /dev/null +++ b/test/prism/errors/module_definition_in_method_body.txt @@ -0,0 +1,3 @@ +def foo;module A;end;end + ^~~~~~ unexpected module definition in method body + diff --git a/test/prism/errors/module_definition_in_method_body_within_block.txt b/test/prism/errors/module_definition_in_method_body_within_block.txt new file mode 100644 index 0000000000..204be35607 --- /dev/null +++ b/test/prism/errors/module_definition_in_method_body_within_block.txt @@ -0,0 +1,7 @@ +def foo + bar do + module Foo;end + ^~~~~~ unexpected module definition in method body + end +end + diff --git a/test/prism/errors/module_definition_in_method_defs.txt b/test/prism/errors/module_definition_in_method_defs.txt new file mode 100644 index 0000000000..c5a6a8a2e8 --- /dev/null +++ b/test/prism/errors/module_definition_in_method_defs.txt @@ -0,0 +1,7 @@ +def foo(bar = module A;end);end + ^~~~~~ unexpected module definition in method body +def foo;rescue;module A;end;end + ^~~~~~ unexpected module definition in method body +def foo;ensure;module A;end;end + ^~~~~~ unexpected module definition in method body + diff --git a/test/prism/errors/module_name_recoverable.txt b/test/prism/errors/module_name_recoverable.txt new file mode 100644 index 0000000000..58a28a60c5 --- /dev/null +++ b/test/prism/errors/module_name_recoverable.txt @@ -0,0 +1,4 @@ +module Parent module end + ^~~~~~ unexpected constant path after `module`; class/module name must be CONSTANT + ^~~ unexpected 'end', assuming it is closing the parent module definition + diff --git a/test/prism/errors/multiple_error_in_parameters_order.txt b/test/prism/errors/multiple_error_in_parameters_order.txt new file mode 100644 index 0000000000..5dae0a105a --- /dev/null +++ b/test/prism/errors/multiple_error_in_parameters_order.txt @@ -0,0 +1,5 @@ +def foo(**args, a, b:) + ^ unexpected parameter order + ^~ unexpected parameter order +end + diff --git a/test/prism/errors/next_1.txt b/test/prism/errors/next_1.txt new file mode 100644 index 0000000000..b56b7f6ae6 --- /dev/null +++ b/test/prism/errors/next_1.txt @@ -0,0 +1,4 @@ +next 1,; + ^ expected an argument +^~~~~~~ Invalid next + diff --git a/test/prism/errors/next_1_2_3.txt b/test/prism/errors/next_1_2_3.txt new file mode 100644 index 0000000000..7abe577ab3 --- /dev/null +++ b/test/prism/errors/next_1_2_3.txt @@ -0,0 +1,8 @@ +next(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it +^~~~~~~~~~~~ Invalid next + diff --git a/test/prism/errors/non_assoc_equality.txt b/test/prism/errors/non_assoc_equality.txt new file mode 100644 index 0000000000..6ce8da88d6 --- /dev/null +++ b/test/prism/errors/non_assoc_equality.txt @@ -0,0 +1,19 @@ +1 == 2 == 3 + ^~ unexpected '==', expecting end-of-input + ^~ unexpected '==', ignoring it +1 != 2 != 3 + ^~ unexpected '!=', expecting end-of-input + ^~ unexpected '!=', ignoring it +1 === 2 === 3 + ^~~ unexpected '===', expecting end-of-input + ^~~ unexpected '===', ignoring it +1 =~ 2 =~ 3 + ^~ unexpected '=~', expecting end-of-input + ^~ unexpected '=~', ignoring it +1 !~ 2 !~ 3 + ^~ unexpected '!~', expecting end-of-input + ^~ unexpected '!~', ignoring it +1 <=> 2 <=> 3 + ^~~ unexpected '<=>', expecting end-of-input + ^~~ unexpected '<=>', ignoring it + diff --git a/test/prism/errors/non_assoc_range.txt b/test/prism/errors/non_assoc_range.txt new file mode 100644 index 0000000000..072cf6d3c6 --- /dev/null +++ b/test/prism/errors/non_assoc_range.txt @@ -0,0 +1,4 @@ +1....2 + ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it + diff --git a/test/prism/errors/numbered_parameters_in_block_arguments.txt b/test/prism/errors/numbered_parameters_in_block_arguments.txt new file mode 100644 index 0000000000..d01999c53e --- /dev/null +++ b/test/prism/errors/numbered_parameters_in_block_arguments.txt @@ -0,0 +1,3 @@ +foo { |_1| } + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator.txt b/test/prism/errors/optional_block_parameters_with_unary_operator.txt new file mode 100644 index 0000000000..fd45f12648 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator.txt @@ -0,0 +1,3 @@ +foo { |a = +b| } + ^ unexpected '+'; unary calls are not allowed in this context + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt new file mode 100644 index 0000000000..ba98f36f84 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt @@ -0,0 +1,3 @@ +foo { |a = -b| } + ^ unexpected '-'; unary calls are not allowed in this context + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt new file mode 100644 index 0000000000..9770059891 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt @@ -0,0 +1,3 @@ +foo { |a = !b| } + ^ unexpected '!'; unary calls are not allowed in this context + diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt new file mode 100644 index 0000000000..9bec68d7b3 --- /dev/null +++ b/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt @@ -0,0 +1,3 @@ +foo { |a = ~b| } + ^ unexpected '~'; unary calls are not allowed in this context + diff --git a/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt b/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt new file mode 100644 index 0000000000..db4fd6928a --- /dev/null +++ b/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt @@ -0,0 +1,4 @@ +def foo(x!,y?); end + ^~ unexpected name for a parameter + ^~ unexpected name for a parameter + diff --git a/test/prism/errors/pre_execution_context.txt b/test/prism/errors/pre_execution_context.txt new file mode 100644 index 0000000000..18b11bae97 --- /dev/null +++ b/test/prism/errors/pre_execution_context.txt @@ -0,0 +1,4 @@ +BEGIN { 1 + } + ^ unexpected '}'; expected an expression after the operator + ^ unexpected '}', assuming it is closing the parent 'BEGIN' block + diff --git a/test/prism/errors/pre_execution_missing_brace.txt b/test/prism/errors/pre_execution_missing_brace.txt new file mode 100644 index 0000000000..e51cd0732e --- /dev/null +++ b/test/prism/errors/pre_execution_missing_brace.txt @@ -0,0 +1,3 @@ +BEGIN 1 } + ^ expected a `{` after `BEGIN` + diff --git a/test/prism/errors/range_and_bin_op.txt b/test/prism/errors/range_and_bin_op.txt new file mode 100644 index 0000000000..4a7a396d0d --- /dev/null +++ b/test/prism/errors/range_and_bin_op.txt @@ -0,0 +1,4 @@ +1..2..3 + ^~ unexpected .., expecting end-of-input + ^~ unexpected .., ignoring it + diff --git a/test/prism/errors/range_and_bin_op_2.txt b/test/prism/errors/range_and_bin_op_2.txt new file mode 100644 index 0000000000..f2a31dcf82 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_2.txt @@ -0,0 +1,4 @@ +1..2.. + ^~ unexpected .., expecting end-of-input + ^~ unexpected .., ignoring it + diff --git a/test/prism/errors/range_and_bin_op_3.txt b/test/prism/errors/range_and_bin_op_3.txt new file mode 100644 index 0000000000..34390d0776 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_3.txt @@ -0,0 +1,3 @@ +1.. || 2 + ^ unexpected '|'; expected an expression after the operator + diff --git a/test/prism/errors/range_and_bin_op_4.txt b/test/prism/errors/range_and_bin_op_4.txt new file mode 100644 index 0000000000..56226480cf --- /dev/null +++ b/test/prism/errors/range_and_bin_op_4.txt @@ -0,0 +1,4 @@ +1.. & 2 + ^ unexpected '&', expecting end-of-input + ^ unexpected '&', ignoring it + diff --git a/test/prism/errors/range_and_bin_op_5.txt b/test/prism/errors/range_and_bin_op_5.txt new file mode 100644 index 0000000000..bc8b467914 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_5.txt @@ -0,0 +1,5 @@ +1.. * 2 + ^ unexpected *, expecting end-of-input + ^ unexpected write target + ^~~ unexpected write target + diff --git a/test/prism/errors/range_and_bin_op_6.txt b/test/prism/errors/range_and_bin_op_6.txt new file mode 100644 index 0000000000..5cdd7a4f44 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_6.txt @@ -0,0 +1,3 @@ +1.. / 2 + ^ unterminated regexp meets end of file; expected a closing delimiter + diff --git a/test/prism/errors/range_and_bin_op_7.txt b/test/prism/errors/range_and_bin_op_7.txt new file mode 100644 index 0000000000..3f91b5e97f --- /dev/null +++ b/test/prism/errors/range_and_bin_op_7.txt @@ -0,0 +1,3 @@ +1.. % 2 + ^ unterminated string meets end of file + diff --git a/test/prism/errors/range_and_bin_op_8.txt b/test/prism/errors/range_and_bin_op_8.txt new file mode 100644 index 0000000000..afbf3719d5 --- /dev/null +++ b/test/prism/errors/range_and_bin_op_8.txt @@ -0,0 +1,4 @@ +1.. ** 2 + ^~ unexpected **, expecting end-of-input + ^~ unexpected **, ignoring it + diff --git a/test/prism/errors/rational_number_with_exponential_portion.txt b/test/prism/errors/rational_number_with_exponential_portion.txt new file mode 100644 index 0000000000..01a03d538f --- /dev/null +++ b/test/prism/errors/rational_number_with_exponential_portion.txt @@ -0,0 +1,4 @@ +1e1r; 1e1ri + ^ unexpected local variable or method, expecting end-of-input + ^~ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/regular_expression_with_unknown_regexp_options.txt b/test/prism/errors/regular_expression_with_unknown_regexp_options.txt new file mode 100644 index 0000000000..c37291ca40 --- /dev/null +++ b/test/prism/errors/regular_expression_with_unknown_regexp_options.txt @@ -0,0 +1,3 @@ +/foo/AZaz + ^~~~~ unknown regexp options - AZaz + diff --git a/test/prism/errors/repeated_parameter_name_in_destructured_params.txt b/test/prism/errors/repeated_parameter_name_in_destructured_params.txt new file mode 100644 index 0000000000..766c235325 --- /dev/null +++ b/test/prism/errors/repeated_parameter_name_in_destructured_params.txt @@ -0,0 +1,3 @@ +def f(a, (b, (a))); end + ^ duplicated argument name + diff --git a/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt b/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt new file mode 100644 index 0000000000..406f326712 --- /dev/null +++ b/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt @@ -0,0 +1,4 @@ +def foo(**rest, b:) + ^~ unexpected parameter order +end + diff --git a/test/prism/errors/return_1.txt b/test/prism/errors/return_1.txt new file mode 100644 index 0000000000..b4ce8f1f2a --- /dev/null +++ b/test/prism/errors/return_1.txt @@ -0,0 +1,3 @@ +return 1,; + ^ expected an argument + diff --git a/test/prism/errors/return_1_2_3.txt b/test/prism/errors/return_1_2_3.txt new file mode 100644 index 0000000000..8f6dbaf194 --- /dev/null +++ b/test/prism/errors/return_1_2_3.txt @@ -0,0 +1,7 @@ +return(1, 2, 3) + ^ unexpected ',', expecting end-of-input + ^ unexpected ',', ignoring it + ^ expected a matching `)` + ^ unexpected ')', expecting end-of-input + ^ unexpected ')', ignoring it + diff --git a/test/prism/errors/returning_to_optional_parameters_multiple_times.txt b/test/prism/errors/returning_to_optional_parameters_multiple_times.txt new file mode 100644 index 0000000000..83ca731850 --- /dev/null +++ b/test/prism/errors/returning_to_optional_parameters_multiple_times.txt @@ -0,0 +1,4 @@ +def foo(a, b = 1, c, d = 2, e) + ^ unexpected parameter order +end + diff --git a/test/prism/errors/semicolon_after_inheritance_operator.txt b/test/prism/errors/semicolon_after_inheritance_operator.txt new file mode 100644 index 0000000000..6b67e6048a --- /dev/null +++ b/test/prism/errors/semicolon_after_inheritance_operator.txt @@ -0,0 +1,3 @@ +class Foo < Bar end + ^ unexpected `end`, expecting ';' or '\n' + diff --git a/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt b/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt new file mode 100644 index 0000000000..c4440ccc7e --- /dev/null +++ b/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt @@ -0,0 +1,3 @@ +def a=() = 42 + ^~ invalid method name; a setter method cannot be defined in an endless method definition + diff --git a/test/prism/errors/shadow_args_in_block.txt b/test/prism/errors/shadow_args_in_block.txt new file mode 100644 index 0000000000..1e7d5f9cd4 --- /dev/null +++ b/test/prism/errors/shadow_args_in_block.txt @@ -0,0 +1,3 @@ +tap{|a;a|} + ^ duplicated argument name + diff --git a/test/prism/errors/shadow_args_in_lambda.txt b/test/prism/errors/shadow_args_in_lambda.txt new file mode 100644 index 0000000000..2399a0ebd5 --- /dev/null +++ b/test/prism/errors/shadow_args_in_lambda.txt @@ -0,0 +1,5 @@ +->a;b{} + ^ expected a `do` keyword or a `{` to open the lambda block + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a lambda block beginning with `do` to end with `end` + diff --git a/test/prism/errors/singleton_method_for_literals.txt b/test/prism/errors/singleton_method_for_literals.txt new file mode 100644 index 0000000000..6247b4f025 --- /dev/null +++ b/test/prism/errors/singleton_method_for_literals.txt @@ -0,0 +1,39 @@ +def (1).g; end + ^ cannot define singleton method for literals +def ((a; 1)).foo; end + ^ cannot define singleton method for literals +def ((return; 1)).bar; end + ^ cannot define singleton method for literals +def (((1))).foo; end + ^ cannot define singleton method for literals +def (__FILE__).foo; end + ^~~~~~~~ cannot define singleton method for literals +def (__ENCODING__).foo; end + ^~~~~~~~~~~~ cannot define singleton method for literals +def (__LINE__).foo; end + ^~~~~~~~ cannot define singleton method for literals +def ("foo").foo; end + ^~~~~ cannot define singleton method for literals +def (3.14).foo; end + ^~~~ cannot define singleton method for literals +def (3.14i).foo; end + ^~~~~ cannot define singleton method for literals +def (:foo).foo; end + ^~~~ cannot define singleton method for literals +def (:'foo').foo; end + ^~~~~~ cannot define singleton method for literals +def (:'f{o}').foo; end + ^~~~~~~ cannot define singleton method for literals +def ('foo').foo; end + ^~~~~ cannot define singleton method for literals +def ("foo").foo; end + ^~~~~ cannot define singleton method for literals +def ("#{fo}o").foo; end + ^~~~~~~~ cannot define singleton method for literals +def (/foo/).foo; end + ^~~~~ cannot define singleton method for literals +def (/f#{oo}/).foo; end + ^~~~~~~~ cannot define singleton method for literals +def ([1]).foo; end + ^~~ cannot define singleton method for literals + diff --git a/test/prism/errors/splat_argument_after_keyword_argument.txt b/test/prism/errors/splat_argument_after_keyword_argument.txt new file mode 100644 index 0000000000..fd2dbd0003 --- /dev/null +++ b/test/prism/errors/splat_argument_after_keyword_argument.txt @@ -0,0 +1,3 @@ +a(foo: bar, *args) + ^~~~~ unexpected `*` splat argument after a `**` keyword splat argument + diff --git a/test/prism/errors/statement_at_non_statement.txt b/test/prism/errors/statement_at_non_statement.txt new file mode 100644 index 0000000000..40fe7d862e --- /dev/null +++ b/test/prism/errors/statement_at_non_statement.txt @@ -0,0 +1,9 @@ +foo(alias x y) + ^~~~~ unexpected an `alias` at a non-statement position +foo(BEGIN { bar }) + ^~~~~ unexpected a `BEGIN` at a non-statement position +foo(END { bar }) + ^~~ unexpected an `END` at a non-statement position +foo(undef x) + ^~~~~ unexpected an `undef` at a non-statement position + diff --git a/test/prism/errors/statement_operators.txt b/test/prism/errors/statement_operators.txt new file mode 100644 index 0000000000..04b7c57477 --- /dev/null +++ b/test/prism/errors/statement_operators.txt @@ -0,0 +1,25 @@ +alias x y + 1 + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it +alias x y.z + ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it +BEGIN { bar } + 1 + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it +BEGIN { bar }.z + ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it +END { bar } + 1 + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it +END { bar }.z + ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it +undef x + 1 + ^ unexpected '+', expecting end-of-input + ^ unexpected '+', ignoring it +undef x.z + ^ unexpected '.', expecting end-of-input + ^ unexpected '.', ignoring it + diff --git a/test/prism/errors/switching_to_named_arguments_twice.txt b/test/prism/errors/switching_to_named_arguments_twice.txt new file mode 100644 index 0000000000..5dae0a105a --- /dev/null +++ b/test/prism/errors/switching_to_named_arguments_twice.txt @@ -0,0 +1,5 @@ +def foo(**args, a, b:) + ^ unexpected parameter order + ^~ unexpected parameter order +end + diff --git a/test/prism/errors/switching_to_optional_arguments_twice.txt b/test/prism/errors/switching_to_optional_arguments_twice.txt new file mode 100644 index 0000000000..5dae0a105a --- /dev/null +++ b/test/prism/errors/switching_to_optional_arguments_twice.txt @@ -0,0 +1,5 @@ +def foo(**args, a, b:) + ^ unexpected parameter order + ^~ unexpected parameter order +end + diff --git a/test/prism/errors/symbol_in_hash.txt b/test/prism/errors/symbol_in_hash.txt new file mode 100644 index 0000000000..148040aa61 --- /dev/null +++ b/test/prism/errors/symbol_in_hash.txt @@ -0,0 +1,3 @@ +{x:'y':} + ^~ unexpected label terminator, expected a string literal terminator + diff --git a/test/prism/errors/symbol_in_keyword_parameter.txt b/test/prism/errors/symbol_in_keyword_parameter.txt new file mode 100644 index 0000000000..22d03cccb2 --- /dev/null +++ b/test/prism/errors/symbol_in_keyword_parameter.txt @@ -0,0 +1,3 @@ +def foo(x:'y':); end + ^~ unexpected label terminator, expected a string literal terminator + diff --git a/test/prism/errors/targeting_numbered_parameter.txt b/test/prism/errors/targeting_numbered_parameter.txt new file mode 100644 index 0000000000..39c40ad7b9 --- /dev/null +++ b/test/prism/errors/targeting_numbered_parameter.txt @@ -0,0 +1,3 @@ +-> { _1, = 0 } + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt b/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt new file mode 100644 index 0000000000..b7b54dd74e --- /dev/null +++ b/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt @@ -0,0 +1,4 @@ +::foo::A + ^ expected a constant after the `::` operator + ^~~ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/top_level_constant_with_downcased_identifier.txt b/test/prism/errors/top_level_constant_with_downcased_identifier.txt new file mode 100644 index 0000000000..032bcfaebb --- /dev/null +++ b/test/prism/errors/top_level_constant_with_downcased_identifier.txt @@ -0,0 +1,4 @@ +::foo + ^ expected a constant after the `::` operator + ^~~ unexpected local variable or method, expecting end-of-input + diff --git a/test/prism/errors/trailing_comma_in_calls.txt b/test/prism/errors/trailing_comma_in_calls.txt new file mode 100644 index 0000000000..44e8a1f0b3 --- /dev/null +++ b/test/prism/errors/trailing_comma_in_calls.txt @@ -0,0 +1,3 @@ +foo 1, + ^ expected an argument + diff --git a/test/prism/errors/unexpected_block.txt b/test/prism/errors/unexpected_block.txt new file mode 100644 index 0000000000..2c0741cd30 --- /dev/null +++ b/test/prism/errors/unexpected_block.txt @@ -0,0 +1,3 @@ +def foo = yield(&:+) + ^~~ block argument should not be given + diff --git a/test/prism/errors/unterminated_W_list.txt b/test/prism/errors/unterminated_W_list.txt new file mode 100644 index 0000000000..89cab68abb --- /dev/null +++ b/test/prism/errors/unterminated_W_list.txt @@ -0,0 +1,3 @@ +%w[ +^~~ unterminated list; expected a closing delimiter for the `%w` + diff --git a/test/prism/errors/unterminated_argument_expression.txt b/test/prism/errors/unterminated_argument_expression.txt new file mode 100644 index 0000000000..c250a94bec --- /dev/null +++ b/test/prism/errors/unterminated_argument_expression.txt @@ -0,0 +1,5 @@ +a % + ^ unterminated quoted string meets end of file + ^ unexpected end-of-input; expected an expression after the operator + ^ unexpected end-of-input, assuming it is closing the parent top level context + diff --git a/test/prism/errors/unterminated_embdoc.txt b/test/prism/errors/unterminated_embdoc.txt new file mode 100644 index 0000000000..1dd9ea3ac4 --- /dev/null +++ b/test/prism/errors/unterminated_embdoc.txt @@ -0,0 +1,3 @@ +=begin +^~~~~~ embedded document meets end of file + diff --git a/test/prism/errors/unterminated_embdoc_2.txt b/test/prism/errors/unterminated_embdoc_2.txt new file mode 100644 index 0000000000..1dd9ea3ac4 --- /dev/null +++ b/test/prism/errors/unterminated_embdoc_2.txt @@ -0,0 +1,3 @@ +=begin +^~~~~~ embedded document meets end of file + diff --git a/test/prism/errors/unterminated_empty_string.txt b/test/prism/errors/unterminated_empty_string.txt new file mode 100644 index 0000000000..597102f7ee --- /dev/null +++ b/test/prism/errors/unterminated_empty_string.txt @@ -0,0 +1,3 @@ +" + ^ unterminated string meets end of file + diff --git a/test/prism/errors/unterminated_global_variable.txt b/test/prism/errors/unterminated_global_variable.txt new file mode 100644 index 0000000000..ce3e960b2e --- /dev/null +++ b/test/prism/errors/unterminated_global_variable.txt @@ -0,0 +1,3 @@ +$ +^ '$' without identifiers is not allowed as a global variable name + diff --git a/test/prism/errors/unterminated_global_variable_2.txt b/test/prism/errors/unterminated_global_variable_2.txt new file mode 100644 index 0000000000..302293b538 --- /dev/null +++ b/test/prism/errors/unterminated_global_variable_2.txt @@ -0,0 +1,3 @@ +$ +^ '$' without identifiers is not allowed as a global variable name + diff --git a/test/prism/errors/unterminated_i_list.txt b/test/prism/errors/unterminated_i_list.txt new file mode 100644 index 0000000000..c48be9971d --- /dev/null +++ b/test/prism/errors/unterminated_i_list.txt @@ -0,0 +1,3 @@ +%i[ +^~~ unterminated list; expected a closing delimiter for the `%i` + diff --git a/test/prism/errors/unterminated_interpolated_string.txt b/test/prism/errors/unterminated_interpolated_string.txt new file mode 100644 index 0000000000..e74a4c9e20 --- /dev/null +++ b/test/prism/errors/unterminated_interpolated_string.txt @@ -0,0 +1,3 @@ +"hello + ^ unterminated string meets end of file + diff --git a/test/prism/errors/unterminated_interpolated_symbol.txt b/test/prism/errors/unterminated_interpolated_symbol.txt new file mode 100644 index 0000000000..faa7597280 --- /dev/null +++ b/test/prism/errors/unterminated_interpolated_symbol.txt @@ -0,0 +1,3 @@ +:"# + ^ unterminated symbol; expected a closing delimiter for the interpolated symbol + diff --git a/test/prism/errors/unterminated_parenthesized_expression.txt b/test/prism/errors/unterminated_parenthesized_expression.txt new file mode 100644 index 0000000000..9025eec453 --- /dev/null +++ b/test/prism/errors/unterminated_parenthesized_expression.txt @@ -0,0 +1,4 @@ +(1 + 2 + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected a matching `)` + diff --git a/test/prism/errors/unterminated_regular_expression.txt b/test/prism/errors/unterminated_regular_expression.txt new file mode 100644 index 0000000000..48f3a30810 --- /dev/null +++ b/test/prism/errors/unterminated_regular_expression.txt @@ -0,0 +1,3 @@ +/hello +^ unterminated regexp meets end of file; expected a closing delimiter + diff --git a/test/prism/errors/unterminated_regular_expression_with_heredoc.txt b/test/prism/errors/unterminated_regular_expression_with_heredoc.txt new file mode 100644 index 0000000000..d4688d6c9e --- /dev/null +++ b/test/prism/errors/unterminated_regular_expression_with_heredoc.txt @@ -0,0 +1,4 @@ +<<-END + /b + ^ unterminated regexp meets end of file; expected a closing delimiter +END + diff --git a/test/prism/errors/unterminated_s_symbol.txt b/test/prism/errors/unterminated_s_symbol.txt new file mode 100644 index 0000000000..0f4be932b3 --- /dev/null +++ b/test/prism/errors/unterminated_s_symbol.txt @@ -0,0 +1,3 @@ +%s[abc +^~~ unterminated quoted string; expected a closing delimiter for the dynamic symbol + diff --git a/test/prism/errors/unterminated_string.txt b/test/prism/errors/unterminated_string.txt new file mode 100644 index 0000000000..89c0a08b3e --- /dev/null +++ b/test/prism/errors/unterminated_string.txt @@ -0,0 +1,3 @@ +'hello +^ unterminated string meets end of file + diff --git a/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt b/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt new file mode 100644 index 0000000000..1a65c6149a --- /dev/null +++ b/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt @@ -0,0 +1,3 @@ +?\u{3 + ^~~~ unterminated Unicode escape + diff --git a/test/prism/errors/unterminated_xstring.txt b/test/prism/errors/unterminated_xstring.txt new file mode 100644 index 0000000000..ccd529774c --- /dev/null +++ b/test/prism/errors/unterminated_xstring.txt @@ -0,0 +1,3 @@ +`hello +^ expected a closing delimiter for the `%x` or backtick string + diff --git a/test/prism/errors/void_value_expression_in_arguments.txt b/test/prism/errors/void_value_expression_in_arguments.txt new file mode 100644 index 0000000000..f57aee1454 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_arguments.txt @@ -0,0 +1,17 @@ +foo(return) + ^~~~~~ unexpected void value expression +foo(1, return) + ^~~~~~ unexpected void value expression +foo(*return) + ^~~~~~ unexpected void value expression +foo(**return) + ^~~~~~ unexpected void value expression +foo(&return) + ^~~~~~ unexpected void value expression +foo(return => 1) + ^~~~~~ unexpected void value expression +foo(:a => return) + ^~~~~~ unexpected void value expression +foo(a: return) + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_array.txt b/test/prism/errors/void_value_expression_in_array.txt new file mode 100644 index 0000000000..a0e86fb135 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_array.txt @@ -0,0 +1,15 @@ +[return] + ^~~~~~ unexpected void value expression +[1, return] + ^~~~~~ unexpected void value expression +[ return => 1 ] + ^~~~~~ unexpected void value expression +[ 1 => return ] + ^~~~~~ unexpected void value expression +[ a: return ] + ^~~~~~ unexpected void value expression +[ *return ] + ^~~~~~ unexpected void value expression +[ **return ] + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_assignment.txt b/test/prism/errors/void_value_expression_in_assignment.txt new file mode 100644 index 0000000000..c651d7f39e --- /dev/null +++ b/test/prism/errors/void_value_expression_in_assignment.txt @@ -0,0 +1,9 @@ +a = return + ^~~~~~ unexpected void value expression +a = 1, return + ^~~~~~ unexpected void value expression +a, b = return, 1 + ^~~~~~ unexpected void value expression +a, b = 1, *return + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_begin_statement.txt b/test/prism/errors/void_value_expression_in_begin_statement.txt new file mode 100644 index 0000000000..4ad40b684d --- /dev/null +++ b/test/prism/errors/void_value_expression_in_begin_statement.txt @@ -0,0 +1,21 @@ +x = return 1 + ^~~~~~~~ unexpected void value expression +x = return, 1 + ^~~~~~ unexpected void value expression +x = 1, return + ^~~~~~ unexpected void value expression +x, y = return + ^~~~~~ unexpected void value expression +x = begin return ensure end + ^~~~~~ unexpected void value expression +x = begin ensure return end + ^~~~~~ unexpected void value expression +x = begin return ensure return end + ^~~~~~ unexpected void value expression +x = begin return; rescue; return end + ^~~~~~ unexpected void value expression +x = begin return; rescue; return; else return end + ^~~~~~ unexpected void value expression +x = begin; return; rescue; retry; end + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_binary_call.txt b/test/prism/errors/void_value_expression_in_binary_call.txt new file mode 100644 index 0000000000..096b42be4d --- /dev/null +++ b/test/prism/errors/void_value_expression_in_binary_call.txt @@ -0,0 +1,11 @@ +1 + (return) + ^~~~~~ unexpected void value expression +(return) + 1 + ^~~~~~ unexpected void value expression +1 and (return) +(return) and 1 + ^~~~~~ unexpected void value expression +1 or (return) +(return) or 1 + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_call.txt b/test/prism/errors/void_value_expression_in_call.txt new file mode 100644 index 0000000000..90e6481c4c --- /dev/null +++ b/test/prism/errors/void_value_expression_in_call.txt @@ -0,0 +1,11 @@ +(return).foo + ^~~~~~ unexpected void value expression +(return).(1) + ^~~~~~ unexpected void value expression +(return)[1] + ^~~~~~ unexpected void value expression +(return)[1] = 2 + ^~~~~~ unexpected void value expression +(return)::foo + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_constant_path.txt b/test/prism/errors/void_value_expression_in_constant_path.txt new file mode 100644 index 0000000000..1dab6902a2 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_constant_path.txt @@ -0,0 +1,5 @@ +(return)::A + ^~~~~~ unexpected void value expression +class (return)::A; end + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_def.txt b/test/prism/errors/void_value_expression_in_def.txt new file mode 100644 index 0000000000..fed52a6677 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_def.txt @@ -0,0 +1,10 @@ +def (return).x + ^~~~~~ unexpected void value expression +end +def x(a = return) + ^~~~~~ unexpected void value expression +end +def x(a: return) + ^~~~~~ unexpected void value expression +end + diff --git a/test/prism/errors/void_value_expression_in_expression.txt b/test/prism/errors/void_value_expression_in_expression.txt new file mode 100644 index 0000000000..f6165a7ba6 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_expression.txt @@ -0,0 +1,19 @@ +(return) ? 1 : 1 + ^~~~~~ unexpected void value expression +(return)..1 + ^~~~~~ unexpected void value expression +1..(return) + ^~~~~~ unexpected void value expression +(return)...1 + ^~~~~~ unexpected void value expression +1...(return) + ^~~~~~ unexpected void value expression +(..(return)) + ^~~~~~ unexpected void value expression +(...(return)) + ^~~~~~ unexpected void value expression +((return)..) + ^~~~~~ unexpected void value expression +((return)...) + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_hash.txt b/test/prism/errors/void_value_expression_in_hash.txt new file mode 100644 index 0000000000..7795511443 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_hash.txt @@ -0,0 +1,9 @@ +{ return => 1 } + ^~~~~~ unexpected void value expression +{ 1 => return } + ^~~~~~ unexpected void value expression +{ a: return } + ^~~~~~ unexpected void value expression +{ **return } + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_modifier.txt b/test/prism/errors/void_value_expression_in_modifier.txt new file mode 100644 index 0000000000..7d7b444e33 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_modifier.txt @@ -0,0 +1,13 @@ +1 if (return) + ^~~~~~ unexpected void value expression +1 unless (return) + ^~~~~~ unexpected void value expression +1 while (return) + ^~~~~~ unexpected void value expression +1 until (return) + ^~~~~~ unexpected void value expression +(return) => a + ^~~~~~ unexpected void value expression +(return) in a + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/void_value_expression_in_statement.txt b/test/prism/errors/void_value_expression_in_statement.txt new file mode 100644 index 0000000000..87dbfa5cc9 --- /dev/null +++ b/test/prism/errors/void_value_expression_in_statement.txt @@ -0,0 +1,26 @@ +if (return) + ^~~~~~ unexpected void value expression +end +unless (return) + ^~~~~~ unexpected void value expression +end +while (return) + ^~~~~~ unexpected void value expression +end +until (return) + ^~~~~~ unexpected void value expression +end +case (return) + ^~~~~~ unexpected void value expression +when 1 +end +class A < (return) + ^~~~~~ unexpected void value expression +end +class << (return) + ^~~~~~ unexpected void value expression +end +for x in (return) + ^~~~~~ unexpected void value expression +end + diff --git a/test/prism/errors/void_value_expression_in_unary_call.txt b/test/prism/errors/void_value_expression_in_unary_call.txt new file mode 100644 index 0000000000..61e849255c --- /dev/null +++ b/test/prism/errors/void_value_expression_in_unary_call.txt @@ -0,0 +1,5 @@ ++(return) + ^~~~~~ unexpected void value expression +not return + ^~~~~~ unexpected void value expression + diff --git a/test/prism/errors/while_endless_method.txt b/test/prism/errors/while_endless_method.txt new file mode 100644 index 0000000000..6f062d89d0 --- /dev/null +++ b/test/prism/errors/while_endless_method.txt @@ -0,0 +1,5 @@ +while def f = g do end + ^ expected a predicate expression for the `while` statement + ^ unexpected end-of-input, assuming it is closing the parent top level context + ^ expected an `end` to close the `while` statement + diff --git a/test/prism/errors/writing_numbered_parameter.txt b/test/prism/errors/writing_numbered_parameter.txt new file mode 100644 index 0000000000..17dcc6e8f0 --- /dev/null +++ b/test/prism/errors/writing_numbered_parameter.txt @@ -0,0 +1,3 @@ +-> { _1 = 0 } + ^~ _1 is reserved for numbered parameters + diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 4e900e37f4..4c5f93cc9f 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -4,1985 +4,63 @@ require_relative "test_helper" module Prism class ErrorsTest < TestCase - include DSL + base = File.expand_path("errors", __dir__) + filepaths = Dir["*.txt", base: base] - def test_constant_path_with_invalid_token_after - assert_error_messages "A::$b", [ - "expected a constant after the `::` operator", - "unexpected global variable, expecting end-of-input" + 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" ] end - def test_module_name_recoverable - expected = ModuleNode( - [], - Location(), - ConstantReadNode(:Parent), - StatementsNode( - [ModuleNode([], Location(), MissingNode(), nil, Location(), :"")] - ), - Location(), - :Parent - ) - - assert_errors expected, "module Parent module end", [ - ["unexpected constant path after `module`; class/module name must be CONSTANT", 14..20], - ["unexpected 'end', assuming it is closing the parent module definition", 21..24] - ] - 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 an index after `for`", 0..3] - ] - end - - def test_for_loops_only_end - expected = ForNode( - MissingNode(), - MissingNode(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "for end", [ - ["expected an index after `for`", 0..3], - ["expected an `in` after the index in a `for` statement", 3..3], - ["expected a collection after the `in` in a `for` statement", 3..3] - ] - end - - def test_pre_execution_missing_brace - expected = PreExecutionNode( - StatementsNode([expression("1")]), - Location(), - Location(), - Location() - ) - - assert_errors expected, "BEGIN 1 }", [ - ["expected a `{` after `BEGIN`", 5..5] - ] - end - - def test_pre_execution_context - expected = PreExecutionNode( - StatementsNode([ - CallNode( - 0, - expression("1"), - nil, - :+, - Location(), - nil, - ArgumentsNode(0, [MissingNode()]), - nil, - nil - ) - ]), - Location(), - Location(), - Location() - ) - - assert_errors expected, "BEGIN { 1 + }", [ - ["unexpected '}'; expected an expression after the operator", 12..13], - ["unexpected '}', assuming it is closing the parent 'BEGIN' block", 12..13] - ] - end - - def test_unterminated_embdoc - message = "embedded document meets end of file" - assert_error_messages "=begin", [message] - assert_error_messages "=begin\n", [message] - - refute_error_messages "=begin\n=end" - refute_error_messages "=begin\n=end\0" - refute_error_messages "=begin\n=end\C-d" - refute_error_messages "=begin\n=end\C-z" - end - - def test_unterminated_i_list - assert_errors expression("%i["), "%i[", [ - ["unterminated list; expected a closing delimiter for the `%i`", 0..3] - ] - end - - def test_unterminated_w_list - assert_errors expression("%w["), "%w[", [ - ["unterminated list; expected a closing delimiter for the `%w`", 0..3] - ] - end - - def test_unterminated_W_list - assert_errors expression("%W["), "%W[", [ - ["unterminated list; expected a closing delimiter for the `%W`", 0..3] - ] - end - - def test_unterminated_regular_expression - assert_errors expression("/hello"), "/hello", [ - ["unterminated regexp meets end of file; expected a closing delimiter", 0..1] - ] - end - - def test_unterminated_regular_expression_with_heredoc - source = "<<-END + /b\nEND\n" - - assert_errors expression(source), source, [ - ["unterminated regexp meets end of file; expected a closing delimiter", 9..10] - ] - end - - def test_unterminated_xstring - assert_errors expression("`hello"), "`hello", [ - ["expected a closing delimiter for the `%x` or backtick string", 0..1] - ] - end - - def test_unterminated_interpolated_string - expr = expression('"hello') - assert_errors expr, '"hello', [ - ["unterminated string meets end of file", 6..6] - ] - assert_equal expr.unescaped, "hello" - assert_equal expr.closing, "" - end - - def test_unterminated_string - expr = expression("'hello") - assert_errors expr, "'hello", [ - ["unterminated string meets end of file", 0..1] - ] - assert_equal expr.unescaped, "hello" - assert_equal expr.closing, "" - end - - def test_unterminated_empty_string - expr = expression('"') - assert_errors expr, '"', [ - ["unterminated string meets end of file", 1..1] - ] - assert_equal expr.unescaped, "" - assert_equal expr.closing, "" - end - - def test_incomplete_instance_var_string - assert_errors expression('%@#@@#'), '%@#@@#', [ - ["'@' without identifiers is not allowed as an instance variable name", 4..5], - ["unexpected instance variable, expecting end-of-input", 4..5] - ] - end - - def test_unterminated_s_symbol - assert_errors expression("%s[abc"), "%s[abc", [ - ["unterminated quoted string; expected a closing delimiter for the dynamic symbol", 0..3] - ] - end - - def test_unterminated_parenthesized_expression - assert_errors expression('(1 + 2'), '(1 + 2', [ - ["unexpected end-of-input, assuming it is closing the parent top level context", 6..6], - ["expected a matching `)`", 6..6] - ] - end - - def test_missing_terminator_in_parentheses - assert_error_messages "(0 0)", [ - "unexpected integer, expecting end-of-input" - ] - end - - def test_unterminated_argument_expression - assert_errors expression('a %'), 'a %', [ - ["unterminated quoted string meets end of file", 2..3], - ["unexpected end-of-input; expected an expression after the operator", 3..3], - ["unexpected end-of-input, assuming it is closing the parent top level context", 3..3] - ] - end - - def test_unterminated_interpolated_symbol - assert_error_messages ":\"#", [ - "unterminated symbol; expected a closing delimiter for the interpolated symbol" - ] - end - - def test_cr_without_lf_in_percent_expression - assert_errors expression("%\r"), "%\r", [ - ["unterminated string meets end of file", 2..2], - ] - end - - def test_1_2_3 - assert_errors expression("(1, 2, 3)"), "(1, 2, 3)", [ - ["unexpected ',', expecting end-of-input", 2..3], - ["unexpected ',', ignoring it", 2..3], - ["expected a matching `)`", 2..2], - ["unexpected ',', expecting end-of-input", 2..3], - ["unexpected ',', ignoring it", 2..3], - ["unexpected ',', expecting end-of-input", 5..6], - ["unexpected ',', ignoring it", 5..6], - ["unexpected ')', expecting end-of-input", 8..9], - ["unexpected ')', ignoring it", 8..9] - ] - end - - def test_return_1_2_3 - assert_error_messages "return(1, 2, 3)", [ - "unexpected ',', expecting end-of-input", - "unexpected ',', ignoring it", - "expected a matching `)`", - "unexpected ')', expecting end-of-input", - "unexpected ')', ignoring it" - ] - end - - def test_return_1 - assert_errors expression("return 1,;"), "return 1,;", [ - ["expected an argument", 8..9] - ] - end - - def test_next_1_2_3 - assert_errors expression("next(1, 2, 3)"), "next(1, 2, 3)", [ - ["unexpected ',', expecting end-of-input", 6..7], - ["unexpected ',', ignoring it", 6..7], - ["expected a matching `)`", 6..6], - ["unexpected ')', expecting end-of-input", 12..13], - ["unexpected ')', ignoring it", 12..13], - ["Invalid next", 0..12] - ] - end - - def test_next_1 - assert_errors expression("next 1,;"), "next 1,;", [ - ["expected an argument", 6..7], - ["Invalid next", 0..7] - ] - end - - def test_break_1_2_3 - assert_errors expression("break(1, 2, 3)"), "break(1, 2, 3)", [ - ["unexpected ',', expecting end-of-input", 7..8], - ["unexpected ',', ignoring it", 7..8], - ["expected a matching `)`", 7..7], - ["unexpected ')', expecting end-of-input", 13..14], - ["unexpected ')', ignoring it", 13..14], - ["Invalid break", 0..13] - ] - end - - def test_break_1 - assert_errors expression("break 1,;"), "break 1,;", [ - ["expected an argument", 7..8], - ["Invalid break", 0..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 the 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 the parent method is not forwarding", 43..46] - ] - end - - def test_top_level_constant_with_downcased_identifier - assert_error_messages "::foo", [ - "expected a constant after the `::` operator", - "unexpected local variable or method, expecting end-of-input" - ] - end - - def test_top_level_constant_starting_with_downcased_identifier - assert_error_messages "::foo::A", [ - "expected a constant after the `::` operator", - "unexpected local variable or method, expecting end-of-input" - ] - end - - def test_aliasing_global_variable_with_non_global_variable - assert_errors expression("alias $a b"), "alias $a b", [ - ["invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 9..10] - ] - end - - def test_aliasing_non_global_variable_with_global_variable - assert_errors expression("alias a $b"), "alias a $b", [ - ["invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", 8..10] - ] - end - - def test_aliasing_global_variable_with_global_number_variable - assert_errors expression("alias $a $1"), "alias $a $1", [ - ["invalid argument being passed to `alias`; can't make alias for the number variables", 9..11] - ] - end - - def test_def_with_expression_receiver_and_no_identifier - assert_errors expression("def (a); end"), "def (a); end", [ - ["expected a `.` or `::` after the receiver in a method definition", 7..7], - ["unexpected ';'; expected a method name", 7..8] - ] - end - - def test_def_with_multiple_statements_receiver - assert_errors expression("def (\na\nb\n).c; end"), "def (\na\nb\n).c; end", [ - ["expected a matching `)`", 8..8], - ["expected a `.` or `::` after the receiver in a method definition", 8..8], - ["expected a delimiter to close the parameters", 9..9], - ["unexpected ')', ignoring it", 10..11], - ["unexpected '.', ignoring it", 11..12] - ] - end - - def test_def_with_empty_expression_receiver - assert_errors expression("def ().a; end"), "def ().a; end", [ - ["expected a receiver for the method definition", 4..5] - ] - end - - def test_block_beginning_with_brace_and_ending_with_end - assert_error_messages "x.each { x end", [ - "unexpected 'end', expecting end-of-input", - "unexpected 'end', ignoring it", - "unexpected end-of-input, assuming it is closing the parent top level context", - "expected a block beginning with `{` to end with `}`" - ] - end - - def test_double_splat_followed_by_splat_argument - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - Location(), - ArgumentsNode( - ArgumentsNodeFlags::CONTAINS_KEYWORDS | ArgumentsNodeFlags::CONTAINS_KEYWORD_SPLAT, - [ - KeywordHashNode(0, [AssocSplatNode(expression("kwargs"), Location())]), - SplatNode(Location(), expression("args")) - ] - ), - Location(), - nil - ) - - assert_errors expected, "a(**kwargs, *args)", [ - ["unexpected `*` splat argument after a `**` keyword splat argument", 12..17] - ] - end - - def test_arguments_after_block - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - Location(), - ArgumentsNode(0, [expression("foo")]), - Location(), - BlockArgumentNode(expression("block"), Location()) - ) - - assert_errors expected, "a(&block, foo)", [ - ["unexpected argument after a block argument", 10..13] - ] - end - - def test_arguments_binding_power_for_and - assert_error_messages "foo(*bar and baz)", [ - "unexpected 'and'; expected a `)` to close the arguments", - "unexpected ')', expecting end-of-input", - "unexpected ')', ignoring it" - ] - end - - def test_splat_argument_after_keyword_argument - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - Location(), - ArgumentsNode(ArgumentsNodeFlags::CONTAINS_KEYWORDS, [ - KeywordHashNode(1, [ - AssocNode( - SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, nil, Location(), Location(), "foo"), - expression("bar"), - nil - ) - ]), - SplatNode(Location(), expression("args")) - ]), - Location(), - nil - ) - - assert_errors expected, "a(foo: bar, *args)", [ - ["unexpected `*` splat argument after a `**` keyword splat argument", 12..17] - ] - end - - def test_module_definition_in_method_body - expected = DefNode( - :foo, - Location(), - nil, - nil, - StatementsNode([ModuleNode([], Location(), ConstantReadNode(:A), nil, Location(), :A)]), - [], - Location(), - nil, - nil, - nil, - nil, - Location() - ) - - assert_errors expected, "def foo;module A;end;end", [ - ["unexpected module definition in method body", 8..14] - ] - end - - def test_module_definition_in_method_body_within_block - expected = DefNode( - :foo, - Location(), - nil, - nil, - StatementsNode( - [CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :bar, - Location(), - nil, - nil, - nil, - BlockNode( - [], - nil, - StatementsNode([ModuleNode([], Location(), ConstantReadNode(:Foo), nil, Location(), :Foo)]), - Location(), - Location() - ) - )] - ), - [], - Location(), - nil, - nil, - nil, - nil, - Location() - ) - - assert_errors expected, <<~RUBY, [["unexpected module definition in method body", 21..27]] - def foo - bar do - module Foo;end - end - end - RUBY - end - - def test_module_definition_in_method_defs - source = <<~RUBY - def foo(bar = module A;end);end - def foo;rescue;module A;end;end - def foo;ensure;module A;end;end - RUBY - message = "unexpected module definition in method body" - assert_errors expression(source), source, [ - [message, 14..20], - [message, 47..53], - [message, 79..85], - ] - end - - def test_class_definition_in_method_body - expected = DefNode( - :foo, - Location(), - nil, - nil, - StatementsNode( - [ClassNode( - [], - Location(), - ConstantReadNode(:A), - nil, - nil, - nil, - Location(), - :A - )] - ), - [], - Location(), - nil, - nil, - nil, - nil, - Location() - ) - - assert_errors expected, "def foo;class A;end;end", [ - ["unexpected class definition in method body", 8..13] - ] + filepaths.each do |filepath| + define_method(:"test_#{File.basename(filepath, ".txt")}") do + assert_errors(File.join(base, filepath)) + end end - def test_class_definition_in_method_defs + def test_embdoc_ending source = <<~RUBY - def foo(bar = class A;end);end - def foo;rescue;class A;end;end - def foo;ensure;class A;end;end + =begin\n=end + =begin\n=end\0 + =begin\n=end\C-d + =begin\n=end\C-z RUBY - message = "unexpected class definition in method body" - assert_errors expression(source), source, [ - [message, 14..19], - [message, 46..51], - [message, 77..82], - ] - end - - def test_bad_arguments - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([ - RequiredParameterNode(0, :A), - RequiredParameterNode(0, :@a), - RequiredParameterNode(0, :$A), - RequiredParameterNode(0, :@@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", [ - ["invalid formal argument; formal argument cannot be a constant", 8..9], - ["invalid formal argument; formal argument cannot be an instance variable", 11..13], - ["invalid formal argument; formal argument cannot be a global variable", 15..17], - ["invalid formal argument; formal argument cannot be a class variable", 19..22], - ] - end - if RUBY_VERSION >= "3.0" - def test_cannot_assign_to_a_reserved_numbered_parameter - expected = BeginNode( - Location(), - StatementsNode([ - LocalVariableWriteNode(:_1, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_2, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_3, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_4, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_5, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_6, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_7, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_8, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_9, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_10, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), 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, [ - ["_1 is reserved for numbered parameters", 8..10], - ["_2 is reserved for numbered parameters", 14..16], - ["_3 is reserved for numbered parameters", 20..22], - ["_4 is reserved for numbered parameters", 26..28], - ["_5 is reserved for numbered parameters", 32..34], - ["_6 is reserved for numbered parameters", 40..42], - ["_7 is reserved for numbered parameters", 46..48], - ["_8 is reserved for numbered parameters", 52..54], - ["_9 is reserved for numbered parameters", 58..60], - ] + source.each_line do |line| + assert_valid_syntax(source) + assert_predicate Prism.parse(source), :success? end end - def test_do_not_allow_trailing_commas_in_method_parameters - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [RequiredParameterNode(0, :a), RequiredParameterNode(0, :b), RequiredParameterNode(0, :c)], - [], - nil, - [], - [], - nil, - nil - ), - nil, - [:a, :b, :c], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,c,);end", [ - ["unexpected `,` in parameters", 13..14] - ] - end - - def test_do_not_allow_trailing_commas_in_lambda_parameters - expected = LambdaNode( - [:a, :b], - Location(), - Location(), - Location(), - BlockParametersNode( - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], nil, nil), - [], - Location(), - Location() - ), - nil - ) - assert_errors expected, "-> (a, b, ) {}", [ - ["unexpected `,` in parameters", 8..9] - ] - end - - def test_do_not_allow_multiple_codepoints_in_a_single_character_literal - expected = StringNode(StringFlags::FORCED_UTF8_ENCODING, Location(), Location(), nil, "\u0001\u0002") - - assert_errors expected, '?\u{0001 0002}', [ - ["invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed", 9..12] - ] + def test_unterminated_string_closing + statement = Prism.parse_statement("'hello") + assert_equal statement.unescaped, "hello" + assert_empty statement.closing end - def test_invalid_hex_escape - assert_errors expression('"\\xx"'), '"\\xx"', [ - ["invalid hex escape sequence", 1..3], - ] + def test_unterminated_interpolated_string_closing + statement = Prism.parse_statement('"hello') + assert_equal statement.unescaped, "hello" + assert_empty statement.closing end - def test_do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation - expected = StringNode(0, Location(), Location(), Location(), "\u0001") - - assert_errors expected, '"\u{0000001}"', [ - ["invalid Unicode escape sequence; maximum length is 6 digits", 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(0, Location(), Location(), Location(), "\u0000z}") - - assert_errors expected, '"\u{000z}"', [ - ["invalid Unicode escape sequence", 7..7], - ["unterminated Unicode escape", 7..7] - ] - end - - def test_unterminated_unicode_brackets_should_be_a_syntax_error - assert_errors expression('?\\u{3'), '?\\u{3', [ - ["unterminated Unicode escape", 1..5], - ] - end - - def test_method_parameters_after_block - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [], - nil, - BlockParameterNode(0, :block, 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( - :foo, - Location(), - nil, - ParametersNode([], [], nil, [RequiredParameterNode(0, :a)], [], nil, BlockParameterNode(0, nil, 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( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [], - 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( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - 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( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :rest, 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( - :foo, - Location(), - nil, - ParametersNode([], [], nil, [ForwardingParameterNode()], [], 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( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :args, 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( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :args, 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( - :foo, - Location(), - nil, - ParametersNode( - [], - [], - nil, - [RequiredParameterNode(0, :a)], - [RequiredKeywordParameterNode(0, :b, Location())], - KeywordRestParameterNode(0, :args, 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( - :foo, - Location(), - nil, - ParametersNode( - [RequiredParameterNode(0, :a)], - [ - OptionalParameterNode(0, :b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 1)), - OptionalParameterNode(0, :d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 2)) - ], - nil, - [RequiredParameterNode(0, :c), RequiredParameterNode(0, :e)], - [], - 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 = CaseMatchNode( - SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), - [], - ElseNode(Location(), nil, Location()), - Location(), - Location() - ) - - assert_errors expected, "case :a\nelse\nend", [ - ["expected a `when` or `in` clause after `case`", 0..4] - ] - end - - def test_case_without_clauses - expected = CaseNode( - SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), - [], - nil, - Location(), - Location() - ) - - assert_errors expected, "case :a\nend", [ - ["expected a `when` or `in` clause after `case`", 0..4] - ] - end - - def test_setter_method_cannot_be_defined_in_an_endless_method_definition - expected = DefNode( - :a=, - Location(), - nil, - nil, - StatementsNode([IntegerNode(IntegerBaseFlags::DECIMAL, 42)]), - [], - Location(), - nil, - Location(), - Location(), - Location(), - nil - ) - - assert_errors expected, "def a=() = 42", [ - ["invalid method name; a 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 ... when the parent method is not forwarding", 3..6] - ] - end - - def test_do_not_allow_forward_arguments_in_blocks - expected = CallNode( - CallNodeFlags::IGNORE_VISIBILITY, - nil, - nil, - :a, - Location(), - nil, - nil, - nil, - BlockNode( - [], - BlockParametersNode(ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil), [], Location(), Location()), - nil, - Location(), - Location() - ) - ) - - assert_errors expected, "a {|...|}", [ - ["unexpected ... when the parent method is not forwarding", 4..7] - ] - end - - def test_dont_allow_return_inside_class_body - expected = ClassNode( - [], - Location(), - ConstantReadNode(:A), - nil, - nil, - StatementsNode([ReturnNode(0, Location(), nil)]), - Location(), - :A - ) - - assert_errors expected, "class A; return; end", [ - ["Invalid return in class/module body", 9..15] - ] - end - - def test_dont_allow_return_inside_module_body - expected = ModuleNode( - [], - Location(), - ConstantReadNode(:A), - StatementsNode([ReturnNode(0, Location(), nil)]), - Location(), - :A - ) - - assert_errors expected, "module A; return; end", [ - ["Invalid return in class/module body", 10..16] - ] - end - - def test_dont_allow_setting_to_back_and_nth_reference - expected = BeginNode( - Location(), - StatementsNode([ - GlobalVariableWriteNode(:$+, Location(), NilNode(), Location()), - GlobalVariableWriteNode(:$1466, Location(), NilNode(), Location()) - ]), - nil, - nil, - nil, - Location() - ) - - assert_errors expected, "begin\n$+ = nil\n$1466 = nil\nend", [ - ["Can't set variable $+", 6..8], - ["Can't set variable $1466", 15..20] - ] - end - - def test_duplicated_parameter_names - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b), RequiredParameterNode(ParameterFlags::REPEATED_PARAMETER, :a)], [], nil, [], [], nil, nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,a);end", [ - ["duplicated argument name", 12..13] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], RestParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location()), [], [], nil, nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,*a);end", [ - ["duplicated argument name", 13..14] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], KeywordRestParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location()), nil), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,**a);end", [ - ["duplicated argument name", 14..15] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], nil, BlockParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location())), - nil, - [:a, :b], - Location(), - nil, - Location(), - Location(), - nil, - Location() - ) - - assert_errors expected, "def foo(a,b,&a);end", [ - ["duplicated argument name", 13..14] - ] - - expected = DefNode( - :foo, - Location(), - nil, - ParametersNode([], [OptionalParameterNode(0, :a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL, 1))], RestParameterNode(0, :c, Location(), Location()), [RequiredParameterNode(0, :b)], [], 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 - - def test_content_after_unterminated_heredoc - receiver = StringNode(0, Location(), Location(), Location(), "") - expected = CallNode(0, receiver, Location(), :foo, Location(), nil, nil, nil, nil) - - assert_errors expected, "<<~FOO.foo\n", [ - ["unterminated heredoc; can't find string \"FOO\" anywhere before EOF", 3..6] - ] + def test_unterminated_empty_string_closing + statement = Prism.parse_statement('"') + assert_empty statement.unescaped + assert_empty statement.closing end def test_invalid_message_name assert_equal :"", Prism.parse_statement("+.@foo,+=foo").write_name end - def test_invalid_operator_write_fcall - source = "foo! += 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..4] - ] - end - - def test_invalid_operator_write_dot - source = "foo.+= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 5..6] - ] - end - - def test_unterminated_global_variable - message = "'$' without identifiers is not allowed as a global variable name" - - assert_errors expression("$"), "$", [[message, 0..1]] - assert_errors expression("$ "), "$ ", [[message, 0..1]] - end - - def test_invalid_global_variable_write - assert_errors expression("$',"), "$',", [ - ["Can't set variable $'", 0..2], - ["unexpected write target", 0..2] - ] - end - - def test_invalid_multi_target - error_messages = ["unexpected write target"] - - assert_error_messages "foo,", error_messages - assert_error_messages "foo = 1; foo,", error_messages - assert_error_messages "foo.bar,", error_messages - assert_error_messages "*foo,", error_messages - assert_error_messages "@foo,", error_messages - assert_error_messages "@@foo,", error_messages - assert_error_messages "$foo,", error_messages - assert_error_messages "$1,", ["Can't set variable $1", *error_messages] - assert_error_messages "$+,", ["Can't set variable $+", *error_messages] - assert_error_messages "Foo,", error_messages - assert_error_messages "::Foo,", error_messages - assert_error_messages "Foo::Foo,", error_messages - assert_error_messages "Foo::foo,", error_messages - assert_error_messages "foo[foo],", error_messages - assert_error_messages "(foo, bar)", error_messages - assert_error_messages "foo((foo, bar))", error_messages - assert_error_messages "foo((*))", error_messages - assert_error_messages "foo(((foo, bar), *))", error_messages - assert_error_messages "(foo, bar) + 1", error_messages - assert_error_messages "(foo, bar) in baz", error_messages - end - - def test_call_with_block_and_write - source = "foo {} &&= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..6], - ["unexpected operator after a call with a block", 7..10] - ] - end - - def test_call_with_block_or_write - source = "foo {} ||= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..6], - ["unexpected operator after a call with a block", 7..10] - ] - end - - def test_call_with_block_operator_write - source = "foo {} += 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..6], - ["unexpected operator after a call with a block", 7..9] - ] - end - - def test_index_call_with_block_and_write - source = "foo[1] {} &&= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..9], - ["unexpected operator after a call with arguments", 10..13], - ["unexpected operator after a call with a block", 10..13] - ] - end - - def test_index_call_with_block_or_write - source = "foo[1] {} ||= 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..9], - ["unexpected operator after a call with arguments", 10..13], - ["unexpected operator after a call with a block", 10..13] - ] - end - - def test_index_call_with_block_operator_write - source = "foo[1] {} += 1" - assert_errors expression(source), source, [ - ["unexpected write target", 0..9], - ["unexpected operator after a call with arguments", 10..12], - ["unexpected operator after a call with a block", 10..12] - ] - end - - if RUBY_VERSION >= "3.0" - def test_writing_numbered_parameter - assert_error_messages "-> { _1 = 0 }", [ - "_1 is reserved for numbered parameters" - ] - end - - def test_targeting_numbered_parameter - assert_error_messages "-> { _1, = 0 }", [ - "_1 is reserved for numbered parameters" - ] - end - - def test_defining_numbered_parameter - error_messages = ["_1 is reserved for numbered parameters"] - - assert_error_messages "def _1; end", error_messages - assert_error_messages "def self._1; end", error_messages - end - end - - def test_double_scope_numbered_parameters - source = "-> { _1 + -> { _2 } }" - errors = [["numbered parameter is already used in outer block", 15..17]] - - assert_errors expression(source), source, errors - end - - def test_invalid_number_underscores - error_messages = ["invalid underscore placement in number"] - assert_error_messages "1__1", error_messages - assert_error_messages "0b1__1", error_messages - assert_error_messages "0o1__1", error_messages - assert_error_messages "01__1", error_messages - assert_error_messages "0d1__1", error_messages - assert_error_messages "0x1__1", error_messages - - error_messages = ["trailing '_' in number"] - assert_error_messages "1_1_", error_messages - assert_error_messages "0b1_1_", error_messages - assert_error_messages "0o1_1_", error_messages - assert_error_messages "01_1_", error_messages - assert_error_messages "0d1_1_", error_messages - assert_error_messages "0x1_1_", error_messages - end - - def test_alnum_delimiters - error_messages = ["unknown type of %string"] - - assert_error_messages "%qXfooX", error_messages - assert_error_messages "%QXfooX", error_messages - assert_error_messages "%wXfooX", error_messages - assert_error_messages "%WxfooX", error_messages - assert_error_messages "%iXfooX", error_messages - assert_error_messages "%IXfooX", error_messages - assert_error_messages "%xXfooX", error_messages - assert_error_messages "%rXfooX", error_messages - assert_error_messages "%sXfooX", error_messages - end - - def test_begin_at_toplevel - source = "def foo; BEGIN {}; end" - assert_errors expression(source), source, [ - ["BEGIN is permitted only at toplevel", 9..14], - ] - end - - if RUBY_VERSION >= "3.0" - def test_numbered_parameters_in_block_arguments - source = "foo { |_1| }" - assert_errors expression(source), source, [ - ["_1 is reserved for numbered parameters", 7..9], - ] - end - end - - def test_conditional_predicate_closed - source = "if 0 0; elsif 0 0; end\nunless 0 0; end" - assert_errors expression(source), source, [ - ["expected `then` or `;` or '\\n" + "'", 5..6], - ["expected `then` or `;` or '\\n" + "'", 16..17], - ["expected `then` or `;` or '\\n" + "'", 32..33], - ] - end - - def test_parameter_name_ending_with_bang_or_question_mark - source = "def foo(x!,y?); end" - errors = [ - ["unexpected name for a parameter", 8..10], - ["unexpected name for a parameter", 11..13] - ] - assert_errors expression(source), source, errors - end - - def test_class_name - source = "class 0.X end" - assert_errors expression(source), source, [ - ["unexpected constant path after `class`; class/module name must be CONSTANT", 6..9], - ] - end - - def test_loop_conditional_is_closed - source = "while 0 0; foo; end; until 0 0; foo; end" - assert_errors expression(source), source, [ - ["expected a predicate expression for the `while` statement", 7..7], - ["expected a predicate expression for the `until` statement", 28..28], - ] - end - - def test_forwarding_arg_after_keyword_rest - source = "def f(**,...);end" - assert_errors expression(source), source, [ - ["unexpected parameter order", 9..12] - ] - end - - def test_semicolon_after_inheritance_operator - source = "class Foo < Bar end" - assert_errors expression(source), source, [ - ["unexpected `end`, expecting ';' or '\\n'", 15..15], - ] - end - - def test_shadow_args_in_lambda - source = "->a;b{}" - - assert_errors expression(source), source, [ - ["expected a `do` keyword or a `{` to open the lambda block", 3..3], - ["unexpected end-of-input, assuming it is closing the parent top level context", 7..7], - ["expected a lambda block beginning with `do` to end with `end`", 7..7] - ] - end - - def test_shadow_args_in_block - source = "tap{|a;a|}" - assert_errors expression(source), source, [ - ["duplicated argument name", 7..8], - ] - end - - def test_repeated_parameter_name_in_destructured_params - source = "def f(a, (b, (a))); end" - - assert_errors expression(source), source, [ - ["duplicated argument name", 14..15], - ] - end - - def test_assign_to_numbered_parameter - source = <<~RUBY - a in _1 - a => _1 - 1 => a, _1 - 1 in a, _1 - /(?<_1>)/ =~ a - RUBY - - message = "_1 is reserved for numbered parameters" - assert_errors expression(source), source, [ - [message, 5..7], - [message, 13..15], - [message, 24..26], - [message, 35..37], - [message, 42..44] - ] - end - - def test_symbol_in_keyword_parameter - source = "def foo(x:'y':); end" - assert_errors expression(source), source, [ - ["unexpected label terminator, expected a string literal terminator", 12..14] - ] - end - - def test_symbol_in_hash - source = "{x:'y':}" - assert_errors expression(source), source, [ - ["unexpected label terminator, expected a string literal terminator", 5..7] - ] - end - - def test_while_endless_method - source = "while def f = g do end" - - assert_errors expression(source), source, [ - ["expected a predicate expression for the `while` statement", 22..22], - ["unexpected end-of-input, assuming it is closing the parent top level context", 22..22], - ["expected an `end` to close the `while` statement", 22..22] - ] - end - - def test_match_plus - source = <<~RUBY - a in b + c - a => b + c - RUBY - - assert_errors expression(source), source, [ - ["unexpected '+', expecting end-of-input", 7..8], - ["unexpected '+', ignoring it", 7..8], - ["unexpected '+', expecting end-of-input", 18..19], - ["unexpected '+', ignoring it", 18..19] - ] - end - - def test_rational_number_with_exponential_portion - source = '1e1r; 1e1ri' - - assert_errors expression(source), source, [ - ["unexpected local variable or method, expecting end-of-input", 3..4], - ["unexpected local variable or method, expecting end-of-input", 9..11] - ] - end - - def test_check_value_expression - source = <<~RUBY - 1 => ^(return) - while true - 1 => ^(break) - 1 => ^(next) - 1 => ^(redo) - 1 => ^(retry) - 1 => ^(2 => a) - end - 1 => ^(if 1; (return) else (return) end) - 1 => ^(unless 1; (return) else (return) end) - RUBY - - message = "unexpected void value expression" - assert_errors expression(source), source, [ - [message, 7..13], - [message, 35..40], - [message, 51..55], - [message, 66..70], - ["Invalid retry without rescue", 81..86], - [message, 81..86], - [message, 97..103], - [message, 123..129], - [message, 168..174], - ] - end - - def test_void_value_expression_in_statement - source = <<~RUBY - if (return) - end - unless (return) - end - while (return) - end - until (return) - end - case (return) - when 1 - end - class A < (return) - end - class << (return) - end - for x in (return) - end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..10], - [message, 24..30], - [message, 43..49], - [message, 62..68], - [message, 80..86], - [message, 110..116], - [message, 132..138], - [message, 154..160], - ] - end - - def test_void_value_expression_in_begin_statement - source = <<~RUBY - x = return 1 - x = return, 1 - x = 1, return - x, y = return - x = begin return ensure end - x = begin ensure return end - x = begin return ensure return end - x = begin return; rescue; return end - x = begin return; rescue; return; else return end - x = begin; return; rescue; retry; end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..12], - [message, 17..23], - [message, 34..40], - [message, 48..54], - [message, 65..71], - [message, 100..106], - [message, 121..127], - [message, 156..162], - [message, 222..228], - [message, 244..250], - ] - - refute_error_messages("x = begin return; rescue; end") - refute_error_messages("x = begin return; rescue; return; else end") - refute_error_messages("x = begin; rescue; retry; end") - refute_error_messages("x = begin 1; rescue; retry; ensure; end") - refute_error_messages("x = begin 1; rescue; return; end") - end - - def test_void_value_expression_in_def - source = <<~RUBY - def (return).x - end - def x(a = return) - end - def x(a: return) - end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 5..11], - [message, 29..35], - [message, 50..56], - ] - end - - def test_void_value_expression_in_assignment - source = <<~RUBY - a = return - a = 1, return - a, b = return, 1 - a, b = 1, *return - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..10], - [message, 18..24], - [message, 32..38], - [message, 53..59], - ] - end - - def test_void_value_expression_in_modifier - source = <<~RUBY - 1 if (return) - 1 unless (return) - 1 while (return) - 1 until (return) - (return) => a - (return) in a - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 6..12], - [message, 24..30], - [message, 41..47], - [message, 58..64], - [message, 67..73], - [message, 81..87] - ] - end - - def test_void_value_expression_in_expression - source = <<~RUBY - (return) ? 1 : 1 - (return)..1 - 1..(return) - (return)...1 - 1...(return) - (..(return)) - (...(return)) - ((return)..) - ((return)...) - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 18..24], - [message, 33..39], - [message, 42..48], - [message, 59..65], - [message, 71..77], - [message, 85..91], - [message, 96..102], - [message, 109..115] - ] - end - - def test_void_value_expression_in_array - source = <<~RUBY - [return] - [1, return] - [ return => 1 ] - [ 1 => return ] - [ a: return ] - [ *return ] - [ **return ] - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 13..19], - [message, 23..29], - [message, 44..50], - [message, 58..64], - [message, 70..76], - [message, 83..89], - ] - end - - def test_void_value_expression_in_hash - source = <<~RUBY - { return => 1 } - { 1 => return } - { a: return } - { **return } - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 2..8], - [message, 23..29], - [message, 37..43], - [message, 50..56], - ] - end - - def test_void_value_expression_in_call - source = <<~RUBY - (return).foo - (return).(1) - (return)[1] - (return)[1] = 2 - (return)::foo - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 14..20], - [message, 27..33], - [message, 39..45], - [message, 55..61], - ] - end - - def test_void_value_expression_in_constant_path - source = <<~RUBY - (return)::A - class (return)::A; end - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 1..7], - [message, 19..25], - ] - end - - def test_void_value_expression_in_arguments - source = <<~RUBY - foo(return) - foo(1, return) - foo(*return) - foo(**return) - foo(&return) - foo(return => 1) - foo(:a => return) - foo(a: return) - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 4..10], - [message, 19..25], - [message, 32..38], - [message, 46..52], - [message, 59..65], - [message, 71..77], - [message, 94..100], - [message, 109..115], - ] - end - - def test_void_value_expression_in_unary_call - source = <<~RUBY - +(return) - not return - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 2..8], - [message, 14..20], - ] - end - - def test_void_value_expression_in_binary_call - source = <<~RUBY - 1 + (return) - (return) + 1 - 1 and (return) - (return) and 1 - 1 or (return) - (return) or 1 - RUBY - - message = 'unexpected void value expression' - assert_errors expression(source), source, [ - [message, 5..11], - [message, 14..20], - [message, 42..48], - [message, 71..77], - ] - end - - def test_trailing_comma_in_calls - assert_errors expression("foo 1,"), "foo 1,", [ - ["expected an argument", 5..6] - ] - end - - def test_argument_after_ellipsis - source = 'def foo(...); foo(..., 1); end' - assert_errors expression(source), source, [ - ['unexpected argument after `...`', 23..24] - ] - end - - def test_ellipsis_in_no_paren_call - source = 'def foo(...); foo 1, ...; end' - assert_errors expression(source), source, [ - ['unexpected `...` in an non-parenthesized call', 21..24] - ] - end - - def test_non_assoc_range - source = '1....2' - - assert_errors expression(source), source, [ - ["unexpected '.', expecting end-of-input", 4..5], - ["unexpected '.', ignoring it", 4..5] - ] - end - - def test_upcase_end_in_def - assert_warning_messages "def foo; END { }; end", [ - "END in method; use at_exit" - ] - end - - def test_warnings_verbosity - warning = Prism.parse("def foo; END { }; end").warnings[0] - assert_equal "END in method; use at_exit", warning.message - assert_equal :default, warning.level - - warning = Prism.parse("foo /regexp/").warnings[0] - assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message - assert_equal :verbose, warning.level - end - - def test_statement_operators - source = <<~RUBY - alias x y + 1 - alias x y.z - BEGIN { bar } + 1 - BEGIN { bar }.z - END { bar } + 1 - END { bar }.z - undef x + 1 - undef x.z - RUBY - - assert_errors expression(source), source, [ - ["unexpected '+', expecting end-of-input", 10..11], - ["unexpected '+', ignoring it", 10..11], - ["unexpected '.', expecting end-of-input", 23..24], - ["unexpected '.', ignoring it", 23..24], - ["unexpected '+', expecting end-of-input", 40..41], - ["unexpected '+', ignoring it", 40..41], - ["unexpected '.', expecting end-of-input", 57..58], - ["unexpected '.', ignoring it", 57..58], - ["unexpected '+', expecting end-of-input", 72..73], - ["unexpected '+', ignoring it", 72..73], - ["unexpected '.', expecting end-of-input", 87..88], - ["unexpected '.', ignoring it", 87..88], - ["unexpected '+', expecting end-of-input", 98..99], - ["unexpected '+', ignoring it", 98..99], - ["unexpected '.', expecting end-of-input", 109..110], - ["unexpected '.', ignoring it", 109..110] - ] - end - - def test_statement_at_non_statement - source = <<~RUBY - foo(alias x y) - foo(BEGIN { bar }) - foo(END { bar }) - foo(undef x) - RUBY - assert_errors expression(source), source, [ - ['unexpected an `alias` at a non-statement position', 4..9], - ['unexpected a `BEGIN` at a non-statement position', 19..24], - ['unexpected an `END` at a non-statement position', 38..41], - ['unexpected an `undef` at a non-statement position', 55..60], - ] - end - - def test_binary_range_with_left_unary_range - source = <<~RUBY - ..1.. - ...1.. - RUBY - - assert_errors expression(source), source, [ - ["unexpected range operator; .. and ... are non-associative and cannot be chained", 3..5], - ["unexpected range operator; .. and ... are non-associative and cannot be chained", 10..12], - ["unexpected .., expecting end-of-input", 10..12], - ["unexpected .., ignoring it", 10..12] - ] - end - - def test_circular_param + def test_circular_parameters source = <<~RUBY def foo(bar = bar) = 42 def foo(bar: bar) = 42 @@ -1990,294 +68,26 @@ module Prism proc { |foo: foo| } RUBY - assert_errors( - expression(source), - source, - [ - ["circular argument reference - bar", 8..11], - ["circular argument reference - bar", 32..35], - ["circular argument reference - foo", 55..58], - ["circular argument reference - foo", 76..79] - ], - check_valid_syntax: false, - version: "3.3.0" - ) - - refute_error_messages("def foo(bar: bar = 1); end") - end - - def test_command_calls - sources = <<~RUBY.lines - [a b] - {a: b c} - ...a b - if ...a b; end - a b, c d - a(b, c d) - a(*b c) - a(**b c) - a(&b c) - +a b - a + b c - a && b c - a =~ b c - a = b, c d - a = *b c - a, b = c = d f - a ? b c : d e - defined? a b - ! ! a b - def f a = b c; end - def f(a = b c); end - a = b rescue c d - def a = b rescue c d - ->a=b c{} - ->(a=b c){} - case; when a b; end - case; in a if a b; end - case; in a unless a b; end - begin; rescue a b; end - begin; rescue a b => c; end - RUBY - - sources.each do |source| - refute_valid_syntax(source) - assert_false(Prism.parse(source).success?) + 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_range_and_bin_op - sources = <<~RUBY.lines - 1..2..3 - 1..2.. - 1.. || 2 - 1.. & 2 - 1.. * 2 - 1.. / 2 - 1.. % 2 - 1.. ** 2 - RUBY - - sources.each do |source| - refute_valid_syntax(source) - assert_false(Prism.parse(source).success?) - end - end - - def test_command_call_in - source = <<~RUBY - foo 1 in a - a = foo 2 in b - RUBY - - assert_errors expression(source), source, [ - ["unexpected `in` keyword in arguments", 9..10], - ["unexpected local variable or method, expecting end-of-input", 9..10], - ["unexpected `in` keyword in arguments", 24..25], - ["unexpected local variable or method, expecting end-of-input", 24..25] - ] - end - - def test_constant_assignment_in_method - source = 'def foo();A=1;end' - assert_errors expression(source), source, [ - ['dynamic constant assignment', 10..13] - ] - end - - def test_non_assoc_equality - source = <<~RUBY - 1 == 2 == 3 - 1 != 2 != 3 - 1 === 2 === 3 - 1 =~ 2 =~ 3 - 1 !~ 2 !~ 3 - 1 <=> 2 <=> 3 - RUBY - - assert_errors expression(source), source, [ - ["unexpected '==', expecting end-of-input", 7..9], - ["unexpected '==', ignoring it", 7..9], - ["unexpected '!=', expecting end-of-input", 19..21], - ["unexpected '!=', ignoring it", 19..21], - ["unexpected '===', expecting end-of-input", 32..35], - ["unexpected '===', ignoring it", 32..35], - ["unexpected '=~', expecting end-of-input", 45..47], - ["unexpected '=~', ignoring it", 45..47], - ["unexpected '!~', expecting end-of-input", 57..59], - ["unexpected '!~', ignoring it", 57..59], - ["unexpected '<=>', expecting end-of-input", 70..73], - ["unexpected '<=>', ignoring it", 70..73] - ] - end - - def test_block_arg_and_block - source = 'foo(&1) { }' - assert_errors expression(source), source, [ - ["both block arg and actual block given; only one block is allowed", 8..11] - ] - end - - def test_forwarding_arg_and_block - source = 'def foo(...) = foo(...) { }' - assert_errors expression(source), source, [ - ['both block arg and actual block given; only one block is allowed', 24..27] - ] - end - - def test_it_with_ordinary_parameter - source = "proc { || it }" - errors = [["`it` is not allowed when an ordinary parameter is defined", 10..12]] - - assert_errors expression(source), source, errors, check_valid_syntax: RUBY_VERSION >= "3.4.0" - end - - def test_regular_expression_with_unknown_regexp_options - source = "/foo/AZaz" - errors = [["unknown regexp options - AZaz", 4..9]] - - assert_errors expression(source), source, errors - end - - def test_interpolated_regular_expression_with_unknown_regexp_options - source = "/\#{foo}/AZaz" - errors = [["unknown regexp options - AZaz", 7..12]] - - assert_errors expression(source), source, errors - end - - def test_singleton_method_for_literals - source = <<~'RUBY' - def (1).g; end - def ((a; 1)).foo; end - def ((return; 1)).bar; end - def (((1))).foo; end - def (__FILE__).foo; end - def (__ENCODING__).foo; end - def (__LINE__).foo; end - def ("foo").foo; end - def (3.14).foo; end - def (3.14i).foo; end - def (:foo).foo; end - def (:'foo').foo; end - def (:'f{o}').foo; end - def ('foo').foo; end - def ("foo").foo; end - def ("#{fo}o").foo; end - def (/foo/).foo; end - def (/f#{oo}/).foo; end - def ([1]).foo; end - RUBY - errors = [ - ["cannot define singleton method for literals", 5..6], - ["cannot define singleton method for literals", 24..25], - ["cannot define singleton method for literals", 51..52], - ["cannot define singleton method for literals", 71..72], - ["cannot define singleton method for literals", 90..98], - ["cannot define singleton method for literals", 114..126], - ["cannot define singleton method for literals", 142..150], - ["cannot define singleton method for literals", 166..171], - ["cannot define singleton method for literals", 187..191], - ["cannot define singleton method for literals", 207..212], - ["cannot define singleton method for literals", 228..232], - ["cannot define singleton method for literals", 248..254], - ["cannot define singleton method for literals", 270..277], - ["cannot define singleton method for literals", 293..298], - ["cannot define singleton method for literals", 314..319], - ["cannot define singleton method for literals", 335..343], - ["cannot define singleton method for literals", 359..364], - ["cannot define singleton method for literals", 380..388], - ["cannot define singleton method for literals", 404..407] - ] - assert_errors expression(source), source, errors - end - - def test_assignment_to_literal_in_conditionals - source = <<~RUBY - if (a = 2); end - if ($a = 2); end - if (@a = 2); end - if (@@a = 2); end - if a elsif b = 2; end - unless (a = 2); end - unless ($a = 2); end - unless (@a = 2); end - unless (@@a = 2); end - while (a = 2); end - while ($a = 2); end - while (@a = 2); end - while (@@a = 2); end - until (a = 2); end - until ($a = 2); end - until (@a = 2); end - until (@@a = 2); end - foo if a = 2 - foo if (a, b = 2) - (@foo = 1) ? a : b - !(a = 2) - not a = 2 - RUBY - assert_warning_messages source, [ - "found '= literal' in conditional, should be ==" - ] * source.lines.count - end - - def test_duplicate_pattern_capture - source = <<~RUBY - case (); in [a, a]; end - case (); in [a, *a]; end - case (); in {a: a, b: a}; end - case (); in {a: a, **a}; end - case (); in [a, {a:}]; end - case (); in [a, {a: {a: {a: [a]}}}]; end - case (); in a => a; end - case (); in [A => a, {a: b => a}]; end - RUBY - - assert_error_messages source, Array.new(source.lines.length, "duplicated variable name") - refute_error_messages "case (); in [_a, _a]; end" - end - - def test_duplicate_pattern_hash_key - assert_error_messages "case (); in {a:, a:}; end", ["duplicated key name", "duplicated variable name"] - assert_error_messages "case (); in {a:1, a:2}; end", ["duplicated key name"] - refute_error_messages "case (); in [{a:1}, {a:2}]; end" - end - - def test_unexpected_block - assert_error_messages "def foo = yield(&:+)", ["block argument should not be given"] - end - private - def assert_errors(expected, source, errors, check_valid_syntax: true, **options) - refute_valid_syntax(source) if check_valid_syntax + def assert_errors(filepath) + expected = File.read(filepath) - result = Prism.parse(source, **options) - 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) + source = expected.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "") refute_valid_syntax(source) - result = Prism.parse(source) - assert_equal(errors, result.errors.map(&:message)) - end - - def refute_error_messages(source) - assert_valid_syntax(source) - assert Prism.parse_success?(source), "Expected #{source.inspect} to parse successfully" - end - def assert_warning_messages(source, warnings) result = Prism.parse(source) - assert_equal(warnings, result.warnings.map(&:message)) - end + errors = result.errors + refute_empty errors, "Expected errors in #{filepath}" - def expression(source) - Prism.parse(source).value.statements.body.last + actual = result.errors_format + assert_equal expected, actual, "Expected errors to match for #{filepath}" end end end diff --git a/test/prism/fixtures/patterns.txt b/test/prism/fixtures/patterns.txt index 7ce3b9e4a8..29f8b4cf80 100644 --- a/test/prism/fixtures/patterns.txt +++ b/test/prism/fixtures/patterns.txt @@ -215,3 +215,6 @@ foo => Object[{x:}] a, b ) = c + +case (); in [_a, _a]; end +case (); in [{a:1}, {a:2}]; end diff --git a/test/prism/result/warnings_test.rb b/test/prism/result/warnings_test.rb index ea062d4221..747440dd76 100644 --- a/test/prism/result/warnings_test.rb +++ b/test/prism/result/warnings_test.rb @@ -75,6 +75,37 @@ module Prism assert_warning("1 if 2..foo", "integer") end + def test_literal_in_conditionals + source = <<~RUBY + if (a = 2); a; end + if ($a = 2); end + if (@a = 2); end + if (@@a = 2); end + if a; elsif b = 2; b end + unless (a = 2); a; end + unless ($a = 2); end + unless (@a = 2); end + unless (@@a = 2); end + while (a = 2); a; end + while ($a = 2); end + while (@a = 2); end + while (@@a = 2); end + until (a = 2); a; end + until ($a = 2); end + until (@a = 2); end + until (@@a = 2); end + foo if (a, b = 2); [a, b] + foo if a = 2 and a + (@foo = 1) ? a : b + !(a = 2) and a + not a = 2 and a + RUBY + + source.each_line(chomp: true) do |line| + assert_warning(line, "found '= literal' in conditional, should be ==") + end + end + def test_keyword_eol assert_warning("if\ntrue; end", "end of line") assert_warning("if true\nelsif\nfalse; end", "end of line") @@ -227,12 +258,22 @@ module Prism assert_warning("tap { redo; foo }", "statement not reached") end + def test_warnings_verbosity + warning = Prism.parse("def foo; END { }; end").warnings.first + assert_equal "END in method; use at_exit", warning.message + assert_equal :default, warning.level + + warning = Prism.parse("foo /regexp/").warnings.first + assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message + assert_equal :verbose, warning.level + end + private def assert_warning(source, message) warnings = Prism.parse(source).warnings - assert_equal 1, warnings.length + assert_equal 1, warnings.length, "Expected only one warning in #{source.inspect}, got #{warnings.map(&:message).inspect}" assert_include warnings.first.message, message if defined?(RubyVM::AbstractSyntaxTree) |