2 # frozen_string_literal: false
6 class TestParse < Test::Unit::TestCase
16 assert_syntax_error('------,,', /\n\z/, 'Message to pipe should end with a newline')
17 assert_syntax_error("{hello\n world}", /hello/)
20 def test_else_without_rescue
21 assert_syntax_error(<<-END, %r":#{__LINE__+2}: else without rescue"o, [__FILE__, __LINE__+1])
29 def test_alias_backref
30 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /can't make alias/) do
43 assert_nothing_raised do
44 eval <<-END, nil, __FILE__, __LINE__+1
51 assert_equal([false, 42, nil, false], [a, b, c, d])
54 assert_nothing_raised { eval("a &= t.foo 5") }
57 a = [nil, nil, true, true]
58 assert_nothing_raised do
59 eval <<-END, nil, __FILE__, __LINE__+1
66 assert_equal([42, nil, true, 42], a)
70 attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux
72 o.foo = o.Foo = o::baz = nil
73 o.bar = o.Bar = o::qux = 1
74 assert_nothing_raised do
75 eval <<-END, nil, __FILE__, __LINE__+1
84 assert_equal([42, 42], [o.foo, o.bar])
85 assert_equal([42, 42], [o.Foo, o.Bar])
86 assert_equal([42, 42], [o::baz, o::qux])
88 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /Can't set variable/) do
94 def t.bar(x); x + yield; end
97 assert_nothing_raised do
98 eval <<-END, nil, __FILE__, __LINE__+1
107 assert_equal("foOBar", a)
108 assert_equal("foOBar", b)
111 assert_nothing_raised do
112 t.instance_eval <<-END, __FILE__, __LINE__+1
113 a = bar "foo" do "bar" end
116 assert_equal("foobar", a)
119 assert_nothing_raised do
120 eval <<-END, nil, __FILE__, __LINE__+1
121 a = t::bar "foo" do "bar" end
124 assert_equal("foobar", a)
127 @baz = r + (block_given? ? [yield] : [])
130 assert_nothing_raised do
131 t.instance_eval "baz (1), 2"
133 assert_equal([1, 2], t.instance_eval { @baz })
139 attr_accessor :foo, :bar, :Foo, :Bar
143 assert_nothing_raised do
144 eval <<-END, nil, __FILE__, __LINE__+1
145 c::foo, c::bar = 1, 2
147 c::FOO, c::BAR = 1, 2
150 assert_equal([1, 2], [c::foo, c::bar])
151 assert_equal([1, 2], [c.Foo, c.Bar])
152 assert_equal([1, 2], [c::FOO, c::BAR])
155 def test_dynamic_constant_assignment
156 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /dynamic constant/) do
159 self::FOO, self::BAR = 1, 2
165 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /Can't set variable/) do
171 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /dynamic constant/) do
181 assert_valid_syntax("#{<<~"begin;"}\n#{<<~'end;'}") do
188 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /Can't set variable/) do
195 def test_class_module
196 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /must be CONSTANT/) do
202 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /in method body/) do
211 assert_valid_syntax("#{<<~"begin;"}\n#{<<~'end;'}") do
223 assert_nothing_raised do
224 o.instance_eval <<-END, __FILE__, __LINE__+1
233 attr_accessor :foo, :bar, :Foo, :Bar, :baz, :qux
235 o.foo = o.Foo = o::baz = nil
236 o.bar = o.Bar = o::qux = 1
237 assert_nothing_raised do
238 eval <<-END, nil, __FILE__, __LINE__+1
247 assert_equal([42, 42], [o.foo, o.bar])
248 assert_equal([42, 42], [o.Foo, o.Bar])
249 assert_equal([42, 42], [o::baz, o::qux])
252 assert_nothing_raised do
253 eval <<-END, nil, __FILE__, __LINE__+1
257 assert_equal(-4.0, a)
260 def test_block_variable
262 def o.foo(*r); yield(*r); end
265 assert_nothing_raised do
266 eval <<-END, nil, __FILE__, __LINE__+1
267 o.foo 1 do|; a| a = 42 end
274 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be a constant/) do
280 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be an instance variable/) do
286 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be a global variable/) do
292 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be a class variable/) do
298 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /cannot be an instance variable/) do
300 o.foo {|; @a| @a = 42 }
307 assert_nothing_raised do
308 eval <<-END, nil, __FILE__, __LINE__+1
318 def test_block_call_colon2
320 def o.foo(x); x + yield; end
323 assert_nothing_raised do
324 o.instance_eval <<-END, __FILE__, __LINE__+1
325 a = foo 1 do 42 end.to_s
326 b = foo 1 do 42 end::to_s
329 assert_equal("43", a)
330 assert_equal("43", b)
335 assert_nothing_raised do
336 eval <<-END, nil, __FILE__, __LINE__+1
337 a = proc {|x| x + "bar" }.("foo")
338 b = proc {|x| x + "bar" }::("foo")
341 assert_equal("foobar", a)
342 assert_equal("foobar", b)
346 assert_raise(Errno::ENOENT) do
352 assert_equal([], %W( ))
353 assert_syntax_error('%w[abc', /unterminated list/)
358 assert_equal("foo 1 bar", "foo #@@foo bar")
360 assert_equal("foo 1 bar", "foo #$1 bar")
361 assert_equal('foo #@1 bar', eval('"foo #@1 bar"'))
364 def test_dstr_disallowed_variable
365 bug8375 = '[ruby-core:54885] [Bug #8375]'
366 %w[@ @. @@ @@1 @@. $ $%].each do |src|
368 str = assert_nothing_raised(SyntaxError, "#{bug8375} #{src.dump}") do
369 break eval('"'+src+'"')
371 assert_equal(src, str, bug8375)
376 assert_nothing_raised { eval(':""') }
379 def assert_disallowed_variable(type, noname, invalid)
380 noname.each do |name|
381 assert_syntax_error("proc{a = #{name} }", "`#{noname[0]}' without identifiers is not allowed as #{type} variable name")
383 invalid.each do |name|
384 assert_syntax_error("proc {a = #{name} }", "`#{name}' is not allowed as #{type} variable name")
388 def test_disallowed_instance_variable
389 assert_disallowed_variable("an instance", %w[@ @.], %w[])
392 def test_disallowed_class_variable
393 assert_disallowed_variable("a class", %w[@@ @@.], %w[@@1])
396 def test_disallowed_gloal_variable
397 assert_disallowed_variable("a global", %w[$], %w[$%])
402 assert_nothing_raised do
403 eval <<-END, nil, __FILE__, __LINE__+1
404 def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end
407 assert_equal(-1405, o.foo(1,2,3,4) {|x| -x })
408 assert_equal(-1302, o.foo(1,2,3) {|x| -x })
409 assert_equal(-1200, o.foo(1,2) {|x| -x })
410 assert_equal(-42100, o.foo(1) {|x| -x })
411 assert_raise(ArgumentError) { o.foo() }
414 assert_nothing_raised do
415 eval <<-END, nil, __FILE__, __LINE__+1
416 def o.foo(a=42,z,&b); b.call(a*1000+z*100); end
419 assert_equal(-1200, o.foo(1,2) {|x| -x } )
420 assert_equal(-42100, o.foo(1) {|x| -x } )
421 assert_raise(ArgumentError) { o.foo() }
424 assert_nothing_raised do
425 eval <<-END, nil, __FILE__, __LINE__+1
426 def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end
429 assert_equal(-303, o.foo(1,2,3) {|x| -x } )
430 assert_equal(-201, o.foo(1,2) {|x| -x } )
431 assert_equal(-100, o.foo(1) {|x| -x } )
432 assert_raise(ArgumentError) { o.foo() }
435 def test_duplicate_argument
436 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", '') do
442 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /duplicated argument/) do
448 assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /duplicated argument/) do
455 def test_define_singleton_error
456 msg = /singleton method for literals/
457 assert_parse_error(%q[def ("foo").foo; end], msg)
458 assert_parse_error(%q[def (1).foo; end], msg)
459 assert_parse_error(%q[def ((1;1)).foo; end], msg)
460 assert_parse_error(%q[def ((;1)).foo; end], msg)
461 assert_parse_error(%q[def ((1+1;1)).foo; end], msg)
462 assert_parse_error(%q[def ((%s();1)).foo; end], msg)
463 assert_parse_error(%q[def ((%w();1)).foo; end], msg)
464 assert_parse_error(%q[def ("#{42}").foo; end], msg)
465 assert_parse_error(%q[def (:"#{42}").foo; end], msg)
469 all_assertions_foreach(nil,
470 ['(cond1..cond2)', true],
471 ['((cond1..cond2))', true],
473 # '(;;;cond1..cond2)', # don't care
476 '(%s(); cond1..cond2)',
477 '(%w(); cond1..cond2)',
478 '(1; (2; (3; 4; cond1..cond2)))',
479 '(1+1; cond1..cond2)',
481 code = code.sub("cond1", "n==4").sub("cond2", "n==5")
483 assert_equal([4,5], eval("(1..9).select {|n| true if #{code}}"))
485 assert_raise_with_message(ArgumentError, /bad value for range/, code) {
486 verbose_bak, $VERBOSE = $VERBOSE, nil # disable "warning: possibly useless use of a literal in void context"
488 eval("[4].each {|n| true if #{code}}")
490 $VERBOSE = verbose_bak
497 def test_op_asgn1_with_block
500 blk = proc {|x| a << x }
510 eval <<-END, nil, __FILE__, __LINE__+1
513 assert_equal([:aref, :aset], a)
515 eval <<-END, nil, __FILE__, __LINE__+1
516 t[42, &blk] ||= t.dummy 42 # command_asgn test
518 assert_equal([:aref, :aset], a)
525 assert_nothing_raised do
526 eval <<-END, nil, __FILE__, __LINE__+1
527 def t.`(x); "foo" + x + "bar"; end
531 assert_nothing_raised do
532 eval <<-END, nil, __FILE__, __LINE__+1
534 1.times {|;z| t.` ("zzz") }
536 t.instance_eval <<-END, __FILE__, __LINE__+1
541 assert_equal("foozzzbar", a)
542 assert_equal("foozzzbar", b)
543 assert_equal("foocccbar", c)
546 def test_carrige_return
547 assert_equal(2, eval("1 +\r\n1"))
551 mesg = 'from the backslash through the invalid char'
553 e = assert_syntax_error('"\xg1"', /hex escape/)
554 assert_equal(' ^~'"\n", e.message.lines.last, mesg)
556 e = assert_syntax_error('"\u{1234"', 'unterminated Unicode escape')
557 assert_equal(' ^'"\n", e.message.lines.last, mesg)
559 e = assert_syntax_error('"\u{xxxx}"', 'invalid Unicode escape')
560 assert_equal(' ^'"\n", e.message.lines.last, mesg)
562 e = assert_syntax_error('"\u{xxxx', 'Unicode escape')
563 assert_pattern_list([
564 /.*: invalid Unicode escape\n.*\n/,
567 /.*: unterminated Unicode escape\n.*\n/,
570 /.*: unterminated string.*\n.*\n/,
574 e = assert_syntax_error('"\M1"', /escape character syntax/)
575 assert_equal(' ^~~'"\n", e.message.lines.last, mesg)
577 e = assert_syntax_error('"\C1"', /escape character syntax/)
578 assert_equal(' ^~~'"\n", e.message.lines.last, mesg)
580 src = '"\xD0\u{90'"\n""000000000000000000000000"
581 assert_syntax_error(src, /:#{__LINE__}: unterminated/o)
583 assert_syntax_error('"\u{100000000}"', /invalid Unicode escape/)
584 assert_equal("", eval('"\u{}"'))
585 assert_equal("", eval('"\u{ }"'))
587 assert_equal("\x81", eval('"\C-\M-a"'))
588 assert_equal("\177", eval('"\c?"'))
590 assert_warning(/use \\C-\\s/) {assert_equal("\x00", eval('"\C- "'))}
591 assert_warning(/use \\M-\\s/) {assert_equal("\xa0", eval('"\M- "'))}
592 assert_warning(/use \\M-\\C-\\s/) {assert_equal("\x80", eval('"\M-\C- "'))}
593 assert_warning(/use \\C-\\M-\\s/) {assert_equal("\x80", eval('"\C-\M- "'))}
594 assert_warning(/use \\t/) {assert_equal("\x09", eval("\"\\C-\t\""))}
595 assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\M-\t\""))}
596 assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\M-\\C-\t\""))}
597 assert_warning(/use \\M-\\t/) {assert_equal("\x89", eval("\"\\C-\\M-\t\""))}
598 assert_syntax_error("\"\\C-\x01\"", 'Invalid escape character syntax')
599 assert_syntax_error("\"\\M-\x01\"", 'Invalid escape character syntax')
600 assert_syntax_error("\"\\M-\\C-\x01\"", 'Invalid escape character syntax')
601 assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax')
603 e = assert_syntax_error('"\c\u0000"', 'Invalid escape character syntax')
604 assert_equal(' ^~~~'"\n", e.message.lines.last)
605 e = assert_syntax_error('"\c\U0000"', 'Invalid escape character syntax')
606 assert_equal(' ^~~~'"\n", e.message.lines.last)
608 e = assert_syntax_error('"\C-\u0000"', 'Invalid escape character syntax')
609 assert_equal(' ^~~~~'"\n", e.message.lines.last)
610 e = assert_syntax_error('"\C-\U0000"', 'Invalid escape character syntax')
611 assert_equal(' ^~~~~'"\n", e.message.lines.last)
613 e = assert_syntax_error('"\M-\u0000"', 'Invalid escape character syntax')
614 assert_equal(' ^~~~~'"\n", e.message.lines.last)
615 e = assert_syntax_error('"\M-\U0000"', 'Invalid escape character syntax')
616 assert_equal(' ^~~~~'"\n", e.message.lines.last)
618 e = assert_syntax_error(%["\\C-\u3042"], 'Invalid escape character syntax')
619 assert_match(/^\s \^(?# \\ ) ~(?# C ) ~(?# - ) ~+(?# U+3042 )$/x, e.message.lines.last)
620 assert_not_include(e.message, "invalid multibyte char")
624 assert_syntax_error('?', /incomplete/)
625 assert_syntax_error('? ', /unexpected/)
626 assert_syntax_error("?\n", /unexpected/)
627 assert_syntax_error("?\t", /unexpected/)
628 assert_syntax_error("?\v", /unexpected/)
629 assert_syntax_error("?\r", /unexpected/)
630 assert_syntax_error("?\f", /unexpected/)
631 assert_syntax_error(" ?a\x8a".force_encoding("utf-8"), /invalid multibyte/)
632 assert_equal("\u{1234}", eval("?\u{1234}"))
633 assert_equal("\u{1234}", eval('?\u{1234}'))
634 assert_equal("\u{1234}", eval('?\u1234'))
635 assert_syntax_error('?\u{41 42}', 'Multiple codepoints at single character literal')
636 e = assert_syntax_error('"#{?\u123}"', 'invalid Unicode escape')
637 assert_not_match(/end-of-input/, e.message)
639 assert_warning(/use ?\\C-\\s/) {assert_equal("\x00", eval('?\C- '))}
640 assert_warning(/use ?\\M-\\s/) {assert_equal("\xa0", eval('?\M- '))}
641 assert_warning(/use ?\\M-\\C-\\s/) {assert_equal("\x80", eval('?\M-\C- '))}
642 assert_warning(/use ?\\C-\\M-\\s/) {assert_equal("\x80", eval('?\C-\M- '))}
643 assert_warning(/use ?\\t/) {assert_equal("\x09", eval("?\\C-\t"))}
644 assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\M-\t"))}
645 assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\M-\\C-\t"))}
646 assert_warning(/use ?\\M-\\t/) {assert_equal("\x89", eval("?\\C-\\M-\t"))}
647 assert_syntax_error("?\\C-\x01", 'Invalid escape character syntax')
648 assert_syntax_error("?\\M-\x01", 'Invalid escape character syntax')
649 assert_syntax_error("?\\M-\\C-\x01", 'Invalid escape character syntax')
650 assert_syntax_error("?\\C-\\M-\x01", 'Invalid escape character syntax')
652 assert_equal("\xff", eval("# encoding: ascii-8bit\n""?\\\xFF"))
656 assert_equal(:foo, eval('%s(foo)'))
657 assert_syntax_error('%s', /unterminated quoted string/)
658 assert_syntax_error('%ss', /unknown type/)
659 assert_syntax_error('%z()', /unknown type/)
660 assert_syntax_error("%\u3042", /unknown type/)
661 assert_syntax_error("%q\u3042", /unknown type/)
662 assert_syntax_error("%", /unterminated quoted string/)
666 bug = '[ruby-dev:41447]'
667 sym = "foo\0bar".to_sym
668 assert_nothing_raised(SyntaxError, bug) do
669 assert_equal(sym, eval(":'foo\0bar'"))
671 assert_nothing_raised(SyntaxError, bug) do
672 assert_equal(sym, eval(':"foo\u0000bar"'))
674 assert_nothing_raised(SyntaxError, bug) do
675 assert_equal(sym, eval(':"foo\u{0}bar"'))
677 assert_nothing_raised(SyntaxError) do
678 assert_equal(:foobar, eval(':"foo\u{}bar"'))
679 assert_equal(:foobar, eval(':"foo\u{ }bar"'))
682 assert_syntax_error(':@@', /is not allowed/)
683 assert_syntax_error(':@@1', /is not allowed/)
684 assert_syntax_error(':@', /is not allowed/)
685 assert_syntax_error(':@1', /is not allowed/)
686 assert_syntax_error(':$01234', /is not allowed/)
689 def test_parse_string
690 assert_syntax_error("/\n", /unterminated/)
693 def test_here_document
696 assert_syntax_error("<\<FOO\n", /can't find string "FOO"/)
698 assert_nothing_raised(SyntaxError) do
705 assert_equal "\#$\n", x
707 assert_syntax_error("<\<\"\n", /unterminated here document identifier/)
709 assert_syntax_error("<<``\n", /can't find string ""/)
711 assert_syntax_error("<<--\n", /unexpected <</)
713 assert_nothing_raised(SyntaxError) do
721 assert_equal "\#$\nfoo\n", x
723 assert_nothing_raised do
724 eval "x = <<""FOO\r\n1\r\nFOO"
726 assert_equal("1\n", x)
728 assert_nothing_raised do
729 x = eval "<<' FOO'\n""[Bug #19539]\n"" FOO\n"
731 assert_equal("[Bug #19539]\n", x)
733 assert_nothing_raised do
734 x = eval "<<-' FOO'\n""[Bug #19539]\n"" FOO\n"
736 assert_equal("[Bug #19539]\n", x)
739 def test_magic_comment
742 assert_nothing_raised do
743 eval <<-END, nil, __FILE__, __LINE__+1
748 assert_equal(Encoding.find("UTF-8"), x)
750 assert_nothing_raised do
751 eval <<-END, nil, __FILE__, __LINE__+1
756 assert_equal(Encoding.find("UTF-8"), x)
758 assert_raise(ArgumentError) do
759 eval <<-END, nil, __FILE__, __LINE__+1
760 # coding = foobarbazquxquux_dummy_enconding
765 assert_nothing_raised do
766 eval <<-END, nil, __FILE__, __LINE__+1
771 assert_equal(__ENCODING__, x)
773 assert_raise(ArgumentError) do
774 EnvUtil.with_default_external(Encoding::US_ASCII) {eval <<-END, nil, __FILE__, __LINE__+1}
780 assert_raise(ArgumentError) do
781 EnvUtil.with_default_internal(Encoding::US_ASCII) {eval <<-END, nil, __FILE__, __LINE__+1}
787 assert_raise(ArgumentError) do
788 eval <<-END, nil, __FILE__, __LINE__+1
789 # coding = filesystem
794 assert_raise(ArgumentError) do
795 eval <<-END, nil, __FILE__, __LINE__+1
804 assert_nothing_raised do
805 eval "\xef\xbb\xbf x = __ENCODING__"
807 assert_equal(Encoding.find("UTF-8"), x)
808 assert_raise(NameError) { eval "\xef" }
811 def test_dot_in_next_line
813 assert_nothing_raised do
814 eval <<-END, nil, __FILE__, __LINE__+1
824 assert_nothing_raised { eval("x **= 2") }
829 assert_valid_syntax("=begin\n""=end")
830 assert_valid_syntax("=begin\n""=end\0")
831 assert_valid_syntax("=begin\n""=end\C-d")
832 assert_valid_syntax("=begin\n""=end\C-z")
835 def test_embedded_rd_error
836 error = 'embedded document meets end of file'
837 assert_syntax_error("=begin\n", error)
838 assert_syntax_error("=begin", error)
842 assert_predicate(assert_warning(/out of range/) {eval("1e10000")}, :infinite?)
843 assert_syntax_error('1_E', /trailing `_'/)
844 assert_syntax_error('1E1E1', /unexpected constant/)
847 def test_global_variable
848 assert_equal(nil, assert_warning(/not initialized/) {eval('$-x')})
849 assert_equal(nil, eval('alias $preserve_last_match $&'))
850 assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
851 $test_parse_foobarbazqux = nil
852 assert_equal(nil, $&)
853 assert_equal(nil, eval('alias $& $preserve_last_match'))
854 assert_syntax_error('a = $#', /as a global variable name\na = \$\#\n \^~$/)
857 def test_invalid_instance_variable
858 pattern = /without identifiers is not allowed as an instance variable name/
859 assert_syntax_error('@%', pattern)
860 assert_syntax_error('@', pattern)
863 def test_invalid_class_variable
864 pattern = /without identifiers is not allowed as a class variable name/
865 assert_syntax_error('@@%', pattern)
866 assert_syntax_error('@@', pattern)
869 def test_invalid_char
870 bug10117 = '[ruby-core:64243] [Bug #10117]'
871 invalid_char = /Invalid char `\\x01'/
873 assert_in_out_err(%W"-e \x01x", "", [], invalid_char, bug10117)
874 assert_syntax_error("\x01x", invalid_char, bug10117)
875 assert_equal(nil, eval("\x04x"))
879 def test_literal_concat
881 assert_equal("foobarbaz", eval('"foo" "bar#{x}"'))
882 assert_equal("baz", x)
885 def test_unassignable
886 assert_syntax_error(%q(self = 1), /Can't change the value of self/)
887 assert_syntax_error(%q(nil = 1), /Can't assign to nil/)
888 assert_syntax_error(%q(true = 1), /Can't assign to true/)
889 assert_syntax_error(%q(false = 1), /Can't assign to false/)
890 assert_syntax_error(%q(__FILE__ = 1), /Can't assign to __FILE__/)
891 assert_syntax_error(%q(__LINE__ = 1), /Can't assign to __LINE__/)
892 assert_syntax_error(%q(__ENCODING__ = 1), /Can't assign to __ENCODING__/)
893 assert_syntax_error("def foo; FOO = 1; end", /dynamic constant assignment/)
894 assert_syntax_error("x, true", /Can't assign to true/)
898 assert_syntax_error("foo(&proc{}) {}", /both block arg and actual block/)
902 assert_syntax_error("$& = 1", /Can't set variable/)
907 class << o; self; end.instance_eval do
908 define_method(:[]=) {|*r, &b| b.call(r) }
911 assert_nothing_raised do
912 eval <<-END, nil, __FILE__, __LINE__+1
913 o[&proc{|x| r = x }] = 1
919 def test_void_expr_stmts_value
921 useless_use = /useless use/
922 assert_nil assert_warning(useless_use) {eval("x; nil")}
923 assert_nil assert_warning(useless_use) {eval("1+1; nil")}
924 assert_nil assert_warning('') {eval("1.+(1); nil")}
925 assert_nil assert_warning(useless_use) {eval("TestParse; nil")}
926 assert_nil assert_warning(useless_use) {eval("::TestParse; nil")}
927 assert_nil assert_warning(useless_use) {eval("x..x; nil")}
928 assert_nil assert_warning(useless_use) {eval("x...x; nil")}
929 assert_nil assert_warning(useless_use) {eval("self; nil")}
930 assert_nil assert_warning(useless_use) {eval("nil; nil")}
931 assert_nil assert_warning(useless_use) {eval("true; nil")}
932 assert_nil assert_warning(useless_use) {eval("false; nil")}
933 assert_nil assert_warning(useless_use) {eval("defined?(1); nil")}
936 assert_syntax_error("1; next; 2", /Invalid next/)
939 def test_assign_in_conditional
940 # multiple assignment
941 assert_warning(/`= literal' in conditional/) do
942 eval <<-END, nil, __FILE__, __LINE__+1
943 (x, y = 1, 2) ? 1 : 2
947 # instance variable assignment
948 assert_warning(/`= literal' in conditional/) do
949 eval <<-END, nil, __FILE__, __LINE__+1
958 # local variable assignment
959 assert_warning(/`= literal' in conditional/) do
960 eval <<-END, nil, __FILE__, __LINE__+1
971 # global variable assignment
972 assert_separately([], <<-RUBY)
973 assert_warning(/`= literal' in conditional/) do
974 eval <<-END, nil, __FILE__, __LINE__+1
984 # dynamic variable assignment
985 assert_warning(/`= literal' in conditional/) do
986 eval <<-END, nil, __FILE__, __LINE__+1
999 # class variable assignment
1000 assert_warning(/`= literal' in conditional/) do
1001 eval <<-END, nil, __FILE__, __LINE__+1
1010 # constant declaration
1011 assert_separately([], <<-RUBY)
1012 assert_warning(/`= literal' in conditional/) do
1013 eval <<-END, nil, __FILE__, __LINE__+1
1024 def test_literal_in_conditional
1025 assert_warning(/string literal in condition/) do
1026 eval <<-END, nil, __FILE__, __LINE__+1
1031 assert_warning(/regex literal in condition/) do
1033 eval <<-END, nil, __FILE__, __LINE__+1
1034 /foo#{x}baz/ ? 1 : 2
1038 assert_nothing_raised do
1039 eval <<-END, nil, __FILE__, __LINE__+1
1040 (true..false) ? 1 : 2
1044 assert_warning(/string literal in flip-flop/) do
1045 eval <<-END, nil, __FILE__, __LINE__+1
1046 ("foo".."bar") ? 1 : 2
1050 assert_warning(/literal in condition/) do
1052 eval <<-END, nil, __FILE__, __LINE__+1
1053 :"foo#{"x"}baz" ? 1 : 2
1055 assert_equal "bar", x
1059 def test_no_blockarg
1060 assert_syntax_error("yield(&:+)", /block argument should not be given/)
1063 def test_method_block_location
1064 bug5614 = '[ruby-core:40936]'
1066 e = assert_raise(NoMethodError) do
1068 expected = __LINE__+1
1073 actual = e.backtrace.first[/\A#{Regexp.quote(__FILE__)}:(\d+):/o, 1].to_i
1074 assert_equal(expected, actual, bug5614)
1077 def test_no_shadowing_variable_warning
1078 assert_no_warning(/shadowing outer local variable/) {eval("a=1; tap {|a|}")}
1081 def test_shadowing_private_local_variable
1082 assert_equal 1, eval("_ = 1; [[2]].each{ |(_)| }; _")
1085 def test_unused_variable
1087 assert_warning(/assigned but unused variable/) {o.instance_eval("def foo; a=1; nil; end")}
1088 assert_warning(/assigned but unused variable/) {o.instance_eval("def bar; a=1; a(); end")}
1090 assert_warning(/#{a}/) {o.instance_eval("def foo0; #{a}=1; nil; end")}
1091 assert_warning(/assigned but unused variable/) {o.instance_eval("def foo1; tap {a=1; a()}; end")}
1092 assert_warning('') {o.instance_eval("def bar1; a=a=1; nil; end")}
1093 assert_warning(/assigned but unused variable/) {o.instance_eval("def bar2; a, = 1, 2; end")}
1094 assert_warning('') {o.instance_eval("def marg1(a); nil; end")}
1095 assert_warning('') {o.instance_eval("def marg2((a)); nil; end")}
1098 def test_named_capture_conflict
1100 assert_warning('') {eval("a = 1; /(?<a>)/ =~ ''")}
1102 assert_warning('') {eval("#{a} = 1; /(?<#{a}>)/ =~ ''")}
1105 def test_named_capture_in_block
1106 all_assertions_foreach(nil,
1109 '(%s();/(?<a>.*)/)',
1110 '(%w();/(?<a>.*)/)',
1111 '(1; (2; 3; (4; /(?<a>.*)/)))',
1112 '(1+1; /(?<a>.*)/)',
1115 token = Random.bytes(4).unpack1("H*")
1117 assert_equal(token, eval("#{code} =~ #{token.dump}; a"))
1119 verbose_bak, $VERBOSE = $VERBOSE, nil # disable "warning: possibly useless use of a literal in void context"
1121 assert_nil(eval("#{code} =~ #{token.dump}; defined?(a)"), code)
1123 $VERBOSE = verbose_bak
1129 def test_rescue_in_command_assignment
1130 bug = '[ruby-core:75621] [Bug #12402]'
1131 all_assertions(bug) do |a|
1132 a.for("lhs = arg") do
1134 v = raise(bug) rescue "ok"
1135 assert_equal("ok", v)
1137 a.for("lhs op_asgn arg") do
1139 v += raise(bug) rescue 1
1142 a.for("lhs[] op_asgn arg") do
1144 v[0] += raise(bug) rescue 1
1145 assert_equal([1], v)
1147 a.for("lhs.m op_asgn arg") do
1150 v.m += raise(bug) rescue 1
1151 assert_equal(k.new(1), v)
1153 a.for("lhs::m op_asgn arg") do
1156 v::m += raise(bug) rescue 1
1157 assert_equal(k.new(1), v)
1159 a.for("lhs.C op_asgn arg") do
1162 v.C += raise(bug) rescue 1
1163 assert_equal(k.new(1), v)
1165 a.for("lhs::C op_asgn arg") do
1167 v::C ||= raise(bug) rescue 1
1168 assert_equal(1, v::C)
1170 a.for("lhs = command") do
1172 v = raise bug rescue "ok"
1173 assert_equal("ok", v)
1175 a.for("lhs op_asgn command") do
1177 v += raise bug rescue 1
1180 a.for("lhs[] op_asgn command") do
1182 v[0] += raise bug rescue 1
1183 assert_equal([1], v)
1185 a.for("lhs.m op_asgn command") do
1188 v.m += raise bug rescue 1
1189 assert_equal(k.new(1), v)
1191 a.for("lhs::m op_asgn command") do
1194 v::m += raise bug rescue 1
1195 assert_equal(k.new(1), v)
1197 a.for("lhs.C op_asgn command") do
1200 v.C += raise bug rescue 1
1201 assert_equal(k.new(1), v)
1203 a.for("lhs::C op_asgn command") do
1205 v::C ||= raise bug rescue 1
1206 assert_equal(1, v::C)
1211 def test_yyerror_at_eol
1212 assert_syntax_error(" 0b", /\^/)
1213 assert_syntax_error(" 0b\n", /\^/)
1216 def test_unclosed_unicode_escape_at_eol_bug_19750
1217 assert_separately([], "#{<<-"begin;"}\n#{<<~'end;'}")
1219 assert_syntax_error("/\\u", /too short escape sequence/)
1220 assert_syntax_error("/\\u{", /unterminated regexp meets end of file/)
1221 assert_syntax_error("/\\u{\\n", /invalid Unicode list/)
1222 assert_syntax_error("/a#\\u{\\n/", /invalid Unicode list/)
1223 re = eval("/a#\\u{\n$/x")
1224 assert_match(re, 'a')
1225 assert_not_match(re, 'a#')
1226 re = eval("/a#\\u\n$/x")
1227 assert_match(re, 'a')
1228 assert_not_match(re, 'a#')
1232 def test_error_def_in_argument
1233 assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}")
1235 assert_syntax_error("def f r:def d; def f 0end", /unexpected/)
1238 assert_syntax_error("def\nf(000)end", /^ \^~~/)
1239 assert_syntax_error("def\nf(&0)end", /^ \^/)
1242 def test_method_location_in_rescue
1243 bug = '[ruby-core:79388] [Bug #13181]'
1244 obj, line = Object.new, __LINE__+1
1249 caller_locations(1, 1)[0]
1252 assert_equal(line, obj.location.lineno, bug)
1255 def test_negative_line_number
1256 bug = '[ruby-core:80920] [Bug #13523]'
1258 obj.instance_eval("def t(e = false);raise if e; __LINE__;end", "test", -100)
1259 assert_equal(-100, obj.t, bug)
1260 assert_equal(-100, obj.method(:t).source_location[1], bug)
1261 e = assert_raise(RuntimeError) {obj.t(true)}
1262 assert_equal(-100, e.backtrace_locations.first.lineno, bug)
1265 def test_file_in_indented_heredoc
1266 name = '[ruby-core:80987] [Bug #13540]' # long enough to be shared
1267 assert_equal(name+"\n", eval("#{<<-"begin;"}\n#{<<-'end;'}", nil, name))
1275 def test_heredoc_interpolation
1285 #{_other = "/#{var}"}
1293 assert_equal "something\n/1\n", v1
1294 assert_equal "something\n/1\n", v2
1295 assert_equal "something\n/1\n", v3
1301 def test_heredoc_unterminated_interpolation
1307 assert_syntax_error(code, /can't find string "A"/)
1310 def test_unexpected_token_error
1311 assert_syntax_error('"x"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', /unexpected/)
1314 def test_unexpected_token_after_numeric
1315 assert_syntax_error('0000xyz', /^ \^~~\Z/)
1316 assert_syntax_error('1.2i1.1', /^ \^~~\Z/)
1317 assert_syntax_error('1.2.3', /^ \^~\Z/)
1318 assert_syntax_error('1.', /unexpected end-of-input/)
1319 assert_syntax_error('1e', /expecting end-of-input/)
1322 def test_truncated_source_line
1323 e = assert_syntax_error("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 0123456789012345678901234567890123456789",
1324 /unexpected local variable or method/)
1325 line = e.message.lines[1]
1326 assert_operator(line, :start_with?, "...")
1327 assert_operator(line, :end_with?, "...\n")
1330 def test_unterminated_regexp_error
1331 e = assert_syntax_error("/x", /unterminated regexp meets end of file/)
1332 assert_not_match(/unexpected tSTRING_END/, e.message)
1336 o = Struct.new(:x).new
1340 o.instance_eval {i (-1.3).abs}
1341 assert_equal(1.3, o.x)
1343 o.instance_eval {i = 0; i (-1.3).abs; i}
1344 assert_equal(1.3, o.x)
1347 def test_serial_comparison
1348 assert_warning(/comparison '<' after/) do
1351 eval("if false; 0 < x < 2; end")
1357 assert_equal(42, eval("42\0""end"))
1358 assert_equal(42, eval("42\C-d""end"))
1359 assert_equal(42, eval("42\C-z""end"))
1363 assert_syntax_error("def m\n\0""end", /unexpected/)
1364 assert_syntax_error("def m\n\C-d""end", /unexpected/)
1365 assert_syntax_error("def m\n\C-z""end", /unexpected/)
1368 def test_unexpected_eof
1369 assert_syntax_error('unless', /^ \^\Z/)
1372 def test_location_of_invalid_token
1373 assert_syntax_error('class xxx end', /^ \^~~\Z/)
1376 def test_whitespace_warning
1377 assert_syntax_error("\\foo", /backslash/)
1378 assert_syntax_error("\\ ", /escaped space/)
1379 assert_syntax_error("\\\t", /escaped horizontal tab/)
1380 assert_syntax_error("\\\f", /escaped form feed/)
1381 assert_syntax_error("\\\r", /escaped carriage return/)
1382 assert_warn(/middle of line/) {eval(" \r ")}
1383 assert_syntax_error("\\\v", /escaped vertical tab/)
1386 def test_command_def_cmdarg
1387 assert_valid_syntax("\n#{<<~"begin;"}\n#{<<~'end;'}")
1394 NONASCII_CONSTANTS = [
1395 *%W"\u{00de} \u{00C0}".flat_map {|c| [c, c.encode("iso-8859-15")]},
1396 "\u{1c4}", "\u{1f2}", "\u{1f88}", "\u{370}",
1397 *%W"\u{391} \u{ff21}".flat_map {|c| [c, c.encode("cp932"), c.encode("euc-jp")]},
1400 def assert_nonascii_const
1401 assert_all_assertions_foreach("NONASCII_CONSTANTS", *NONASCII_CONSTANTS) do |n|
1403 assert_not_operator(m, :const_defined?, n)
1404 assert_raise_with_message(NameError, /uninitialized/) do
1407 assert_nil(eval("defined?(m::#{n})"))
1411 assert_operator(m, :const_defined?, n)
1412 assert_equal("constant", eval("defined?(m::#{n})"))
1413 assert_same(v, m.const_get(n))
1415 m.__send__(:remove_const, n)
1416 assert_not_operator(m, :const_defined?, n)
1417 assert_nil(eval("defined?(m::#{n})"))
1421 def test_nonascii_const_set
1422 assert_nonascii_const do |m, n|
1427 def test_nonascii_constant
1428 assert_nonascii_const do |m, n|
1429 m.module_eval("class #{n}; self; end")
1433 def test_cdmarg_after_command_args_and_tlbrace_arg
1434 assert_valid_syntax('let () { m(a) do; end }')
1437 def test_void_value_in_rhs
1438 w = "void value expression"
1440 "x = return 1", "x = return, 1", "x = 1, return", "x, y = return",
1441 "x = begin return ensure end",
1442 "x = begin ensure return end",
1443 "x = begin return ensure return end",
1444 "x = begin return; rescue; return end",
1445 "x = begin return; rescue; return; else return end",
1447 ex = assert_syntax_error(code, w)
1448 assert_equal(1, ex.message.scan(w).size, ->{"same #{w.inspect} warning should be just once\n#{w.message}"})
1451 "x = begin return; rescue; end",
1452 "x = begin return; rescue; return; else end",
1454 assert_valid_syntax(code)
1458 def eval_separately(code)
1459 Class.new.class_eval(code)
1462 def assert_raise_separately(error, message, code)
1463 assert_raise_with_message(error, message) do
1464 eval_separately(code)
1468 def assert_ractor_shareable(obj)
1469 assert Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} to be ractor shareable"}
1472 def assert_not_ractor_shareable(obj)
1473 assert !Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} not to be ractor shareable"}
1476 def test_shareable_constant_value_invalid
1477 assert_warning(/invalid value/) do
1478 assert_valid_syntax("# shareable_constant_value: invalid-option", verbose: true)
1482 def test_shareable_constant_value_ignored
1483 assert_warning(/ignored/) do
1484 assert_valid_syntax("nil # shareable_constant_value: true", verbose: true)
1488 def test_shareable_constant_value_simple
1489 obj = [['unsharable_value']]
1490 a, b, c = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}")
1492 # shareable_constant_value: experimental_everything
1494 # shareable_constant_value: none
1496 # shareable_constant_value: literal
1497 C = [["shareable", "constant#{nil}"]]
1502 assert_ractor_shareable(a)
1503 assert_not_ractor_shareable(b)
1504 assert_ractor_shareable(c)
1505 assert_equal([1], a[0])
1506 assert_ractor_shareable(a[0])
1508 a, obj = eval_separately(<<~'end;')
1509 # shareable_constant_value: experimental_copy
1510 obj = [["unshareable"]]
1515 assert_ractor_shareable(a)
1516 assert_not_ractor_shareable(obj)
1518 assert !obj.equal?(a)
1521 def test_shareable_constant_value_nested
1522 a, b = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}")
1524 # shareable_constant_value: none
1526 # shareable_constant_value: experimental_everything
1533 assert_ractor_shareable(a)
1534 assert_not_ractor_shareable(b)
1535 assert_equal([1], a[0])
1536 assert_ractor_shareable(a[0])
1539 def test_shareable_constant_value_unshareable_literal
1540 assert_raise_separately(Ractor::IsolationError, /unshareable object to C/,
1541 "#{<<~"begin;"}\n#{<<~'end;'}")
1543 # shareable_constant_value: literal
1544 C = ["Not " + "shareable"]
1547 assert_raise_separately(Ractor::IsolationError, /unshareable object to B::C/,
1548 "#{<<~"begin;"}\n#{<<~'end;'}")
1550 # shareable_constant_value: literal
1552 B::C = ["Not " + "shareable"]
1555 assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
1557 assert_raise_with_message(Ractor::IsolationError, /unshareable object to ::C/) do
1558 # shareable_constant_value: literal
1559 ::C = ["Not " + "shareable"]
1563 assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
1565 assert_raise_with_message(Ractor::IsolationError, /unshareable object to ::B::C/) do
1566 # shareable_constant_value: literal
1568 ::B::C = ["Not " + "shareable"]
1573 def test_shareable_constant_value_nonliteral
1574 assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}")
1576 # shareable_constant_value: literal
1581 assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}")
1583 # shareable_constant_value: literal
1588 def test_shareable_constant_value_unfrozen
1589 assert_raise_separately(Ractor::Error, /does not freeze object correctly/,
1590 "#{<<~"begin;"}\n#{<<~'end;'}")
1592 # shareable_constant_value: experimental_everything
1594 def o.freeze; self; end
1599 def test_if_after_class
1600 assert_valid_syntax('module if true; Object end::Kernel; end')
1601 assert_valid_syntax('module while true; break Object end::Kernel; end')
1602 assert_valid_syntax('class if true; Object end::Kernel; end')
1603 assert_valid_syntax('class while true; break Object end::Kernel; end')
1606 def test_escaped_space
1607 assert_syntax_error('x = \ 42', /escaped space/)
1611 expected = {:foo => 1}
1614 assert_valid_syntax(code)
1615 assert_equal(expected, eval(code))
1618 assert_valid_syntax(code)
1619 assert_equal(expected, eval(code))
1621 class << (obj = Object.new)
1628 assert_valid_syntax(code = "#{<<~"do;"}\n#{<<~'end;'}")
1633 assert_equal(expected, eval(code))
1634 assert_equal(expected, obj.arg)
1636 assert_valid_syntax(code = "#{<<~"do;"}\n#{<<~'end;'}")
1641 assert_equal(expected, eval(code))
1642 assert_equal(expected, obj.arg)
1645 def test_ungettable_gvar
1646 assert_syntax_error('$01234', /not allowed/)
1647 assert_syntax_error('"#$01234"', /not allowed/)
1651 def test_past_scope_variable
1652 assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}}
1656 def assert_parse(code)
1657 assert_kind_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.parse(code))
1660 def assert_parse_error(code, message)
1661 assert_raise_with_message(SyntaxError, message) do
1662 $VERBOSE, verbose_bak = nil, $VERBOSE
1664 RubyVM::AbstractSyntaxTree.parse(code)
1666 $VERBOSE = verbose_bak