summaryrefslogtreecommitdiff
path: root/test/ruby/test_syntax.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_syntax.rb')
-rw-r--r--test/ruby/test_syntax.rb412
1 files changed, 341 insertions, 71 deletions
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 1d7b89de57..44162f06cb 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -13,8 +13,7 @@ class TestSyntax < Test::Unit::TestCase
def assert_syntax_files(test)
srcdir = File.expand_path("../../..", __FILE__)
srcdir = File.join(srcdir, test)
- assert_separately(%W[--disable-gem - #{srcdir}],
- __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
+ assert_separately(%W[- #{srcdir}], __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
dir = ARGV.shift
for script in Dir["#{dir}/**/*.rb"].sort
assert_valid_syntax(IO::read(script), script)
@@ -77,98 +76,123 @@ class TestSyntax < Test::Unit::TestCase
def test_anonymous_block_forwarding
assert_syntax_error("def b; c(&); end", /no anonymous block parameter/)
+ assert_syntax_error("def b(&) ->(&) {c(&)} end", /anonymous block parameter is also used/)
+ assert_valid_syntax("def b(&) ->() {c(&)} end")
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
- def b(&); c(&) end
- def c(&); yield 1 end
- a = nil
- b{|c| a = c}
- assert_equal(1, a)
-
- def inner
- yield
- end
+ def b(&); c(&) end
+ def c(&); yield 1 end
+ a = nil
+ b{|c| a = c}
+ assert_equal(1, a)
+
+ def inner
+ yield
+ end
- def block_only(&)
- inner(&)
- end
- assert_equal(1, block_only{1})
+ def block_only(&)
+ inner(&)
+ end
+ assert_equal(1, block_only{1})
- def pos(arg1, &)
- inner(&)
- end
- assert_equal(2, pos(nil){2})
+ def pos(arg1, &)
+ inner(&)
+ end
+ assert_equal(2, pos(nil){2})
- def pos_kwrest(arg1, **kw, &)
- inner(&)
- end
- assert_equal(3, pos_kwrest(nil){3})
+ def pos_kwrest(arg1, **kw, &)
+ inner(&)
+ end
+ assert_equal(3, pos_kwrest(nil){3})
- def no_kw(arg1, **nil, &)
- inner(&)
- end
- assert_equal(4, no_kw(nil){4})
+ def no_kw(arg1, **nil, &)
+ inner(&)
+ end
+ assert_equal(4, no_kw(nil){4})
- def rest_kw(*a, kwarg: 1, &)
- inner(&)
- end
- assert_equal(5, rest_kw{5})
+ def rest_kw(*a, kwarg: 1, &)
+ inner(&)
+ end
+ assert_equal(5, rest_kw{5})
- def kw(kwarg:1, &)
- inner(&)
- end
- assert_equal(6, kw{6})
+ def kw(kwarg:1, &)
+ inner(&)
+ end
+ assert_equal(6, kw{6})
- def pos_kw_kwrest(arg1, kwarg:1, **kw, &)
- inner(&)
- end
- assert_equal(7, pos_kw_kwrest(nil){7})
+ def pos_kw_kwrest(arg1, kwarg:1, **kw, &)
+ inner(&)
+ end
+ assert_equal(7, pos_kw_kwrest(nil){7})
- def pos_rkw(arg1, kwarg1:, &)
- inner(&)
- end
- assert_equal(8, pos_rkw(nil, kwarg1: nil){8})
+ def pos_rkw(arg1, kwarg1:, &)
+ inner(&)
+ end
+ assert_equal(8, pos_rkw(nil, kwarg1: nil){8})
- def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &)
- inner(&)
- end
- assert_equal(9, all(nil, nil, nil, nil, okw1: nil, okw2: nil){9})
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &)
+ inner(&)
+ end
+ assert_equal(9, all(nil, nil, nil, nil, okw1: nil, okw2: nil){9})
- def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &)
- inner(&)
- end
- assert_equal(10, all_kwrest(nil, nil, nil, nil, okw1: nil, okw2: nil){10})
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &)
+ inner(&)
+ end
+ assert_equal(10, all_kwrest(nil, nil, nil, nil, okw1: nil, okw2: nil){10})
end;
end
def test_anonymous_rest_forwarding
assert_syntax_error("def b; c(*); end", /no anonymous rest parameter/)
assert_syntax_error("def b; c(1, *); end", /no anonymous rest parameter/)
+ assert_syntax_error("def b(*) ->(*) {c(*)} end", /anonymous rest parameter is also used/)
+ assert_syntax_error("def b(a, *) ->(*) {c(1, *)} end", /anonymous rest parameter is also used/)
+ assert_syntax_error("def b(*) ->(a, *) {c(*)} end", /anonymous rest parameter is also used/)
+ assert_valid_syntax("def b(*) ->() {c(*)} end")
+ assert_valid_syntax("def b(a, *) ->() {c(1, *)} end")
+ assert_valid_syntax("def b(*) ->(a) {c(*)} end")
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
- def b(*); c(*) end
- def c(*a); a end
- def d(*); b(*, *) end
- assert_equal([1, 2], b(1, 2))
- assert_equal([1, 2, 1, 2], d(1, 2))
+ def b(*); c(*) end
+ def c(*a); a end
+ def d(*); b(*, *) end
+ assert_equal([1, 2], b(1, 2))
+ assert_equal([1, 2, 1, 2], d(1, 2))
end;
end
def test_anonymous_keyword_rest_forwarding
assert_syntax_error("def b; c(**); end", /no anonymous keyword rest parameter/)
assert_syntax_error("def b; c(k: 1, **); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def b(**) ->(**) {c(**)} end", /anonymous keyword rest parameter is also used/)
+ assert_syntax_error("def b(k:, **) ->(**) {c(k: 1, **)} end", /anonymous keyword rest parameter is also used/)
+ assert_syntax_error("def b(**) ->(k:, **) {c(**)} end", /anonymous keyword rest parameter is also used/)
+ assert_valid_syntax("def b(**) ->() {c(**)} end")
+ assert_valid_syntax("def b(k:, **) ->() {c(k: 1, **)} end")
+ assert_valid_syntax("def b(**) ->(k:) {c(**)} end")
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
- def b(**); c(**) end
- def c(**kw); kw end
- def d(**); b(k: 1, **) end
- def e(**); b(**, k: 1) end
- assert_equal({a: 1, k: 3}, b(a: 1, k: 3))
- assert_equal({a: 1, k: 3}, d(a: 1, k: 3))
- assert_equal({a: 1, k: 1}, e(a: 1, k: 3))
+ def b(**); c(**) end
+ def c(**kw); kw end
+ def d(**); b(k: 1, **) end
+ def e(**); b(**, k: 1) end
+ def f(a: nil, **); b(**) end
+ assert_equal({a: 1, k: 3}, b(a: 1, k: 3))
+ assert_equal({a: 1, k: 3}, d(a: 1, k: 3))
+ assert_equal({a: 1, k: 1}, e(a: 1, k: 3))
+ assert_equal({k: 3}, f(a: 1, k: 3))
end;
end
+ def test_argument_forwarding_with_anon_rest_kwrest_and_block
+ assert_syntax_error("def f(*, **, &); g(...); end", /unexpected \.\.\./)
+ assert_syntax_error("def f(...); g(*); end", /no anonymous rest parameter/)
+ assert_syntax_error("def f(...); g(0, *); end", /no anonymous rest parameter/)
+ assert_syntax_error("def f(...); g(**); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def f(...); g(x: 1, **); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def f(...); g(&); end", /no anonymous block parameter/)
+ end
+
def test_newline_in_block_parameters
bug = '[ruby-dev:45292]'
["", "a", "a, b"].product(["", ";x", [";", "x"]]) do |params|
@@ -210,6 +234,7 @@ class TestSyntax < Test::Unit::TestCase
def test_array_kwsplat_hash
kw = {}
h = {a: 1}
+ a = []
assert_equal([], [**{}])
assert_equal([], [**kw])
assert_equal([h], [**h])
@@ -224,6 +249,20 @@ class TestSyntax < Test::Unit::TestCase
assert_equal([1, kw], [1, kw])
assert_equal([1, h], [1, h])
+ assert_equal([], [*a, **{}])
+ assert_equal([], [*a, **kw])
+ assert_equal([h], [*a, **h])
+ assert_equal([{}], [*a, {}])
+ assert_equal([kw], [*a, kw])
+ assert_equal([h], [*a, h])
+
+ assert_equal([1], [1, *a, **{}])
+ assert_equal([1], [1, *a, **kw])
+ assert_equal([1, h], [1, *a, **h])
+ assert_equal([1, {}], [1, *a, {}])
+ assert_equal([1, kw], [1, *a, kw])
+ assert_equal([1, h], [1, *a, h])
+
assert_equal([], [**kw, **kw])
assert_equal([], [**kw, **{}, **kw])
assert_equal([1], [1, **kw, **{}, **kw])
@@ -326,6 +365,12 @@ class TestSyntax < Test::Unit::TestCase
assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4)})")}
assert_equal(4, r)
assert_equal([1, 2, 3, 4], a)
+ a.clear
+ r = nil
+ _z = {}
+ assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), **_z, k: a.add(2))")}
+ assert_equal(2, r)
+ assert_equal([1, 2], a)
end
def test_keyword_empty_splat
@@ -352,6 +397,7 @@ class TestSyntax < Test::Unit::TestCase
assert_syntax_error("def foo(var: var) var end", message)
assert_syntax_error("def foo(var: bar(var)) var end", message)
assert_syntax_error("def foo(var: bar {var}) var end", message)
+ assert_syntax_error("def foo(var: (1 in ^var)); end", message)
o = Object.new
assert_warn("") do
@@ -417,6 +463,7 @@ class TestSyntax < Test::Unit::TestCase
assert_syntax_error("def foo(var = bar {var}) var end", message)
assert_syntax_error("def foo(var = (def bar;end; var)) var end", message)
assert_syntax_error("def foo(var = (def self.bar;end; var)) var end", message)
+ assert_syntax_error("def foo(var = (1 in ^var)); end", message)
o = Object.new
assert_warn("") do
@@ -460,7 +507,7 @@ class TestSyntax < Test::Unit::TestCase
def test_warn_balanced
warning = <<WARN
-test:1: warning: `%s' after local variable or literal is interpreted as binary operator
+test:1: warning: '%s' after local variable or literal is interpreted as binary operator
test:1: warning: even though it seems like %s
WARN
[
@@ -627,6 +674,8 @@ WARN
assert_equal(42, obj.foo(42))
assert_equal(42, obj.foo(2, _: 0))
assert_equal(2, obj.foo(x: 2, _: 0))
+ ensure
+ self.class.remove_method(:foo)
end
def test_duplicated_opt_kw
@@ -666,7 +715,7 @@ WARN
end
def test_duplicated_when
- w = 'warning: duplicated `when\' clause with line 3 is ignored'
+ w = 'warning: duplicated \'when\' clause with line 3 is ignored'
assert_warning(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m) {
eval %q{
case 1
@@ -686,10 +735,28 @@ WARN
end
}
}
+ assert_warning(/3: #{w}/m) {
+ eval %q{
+ case 1
+ when __LINE__, __LINE__
+ when 3, 3
+ when 3, 3
+ end
+ }
+ }
+ assert_warning(/3: #{w}/m) {
+ eval %q{
+ case 1
+ when __FILE__, __FILE__
+ when "filename", "filename"
+ when "filename", "filename"
+ end
+ }, binding, "filename"
+ }
end
def test_duplicated_when_check_option
- w = /duplicated `when\' clause with line 3 is ignored/
+ w = /duplicated \'when\' clause with line 3 is ignored/
assert_in_out_err(%[-wc], "#{<<~"begin;"}\n#{<<~'end;'}", ["Syntax OK"], w)
begin;
case 1
@@ -968,6 +1035,14 @@ eom
assert_not_match(/end-of-input/, e.message)
end
+ def test_invalid_regexp
+ bug20295 = '[ruby-core:116913] [Bug #20295]'
+
+ assert_syntax_error("/[/=~s", /premature end of char-class/, bug20295)
+ assert_syntax_error("/(?<>)/=~s", /group name is empty/, bug20295)
+ assert_syntax_error("/(?<a>[)/=~s", /premature end of char-class/, bug20295)
+ end
+
def test_lineno_operation_brace_block
expected = __LINE__ + 1
actual = caller_lineno\
@@ -980,7 +1055,7 @@ eom
["p ", ""], # no-pop
["", "p Foo::Bar"], # pop
].each do |p1, p2|
- src = <<-EOM.gsub(/^\s*\n/, '')
+ src = <<~EOM
class Foo
#{"Bar = " + preset if preset}
end
@@ -1012,7 +1087,7 @@ eom
["p ", ""], # no-pop
["", "p ::Bar"], # pop
].each do |p1, p2|
- src = <<-EOM.gsub(/^\s*\n/, '')
+ src = <<~EOM
#{"Bar = " + preset if preset}
class Foo
#{p1}::Bar #{op}= 42
@@ -1179,12 +1254,18 @@ eom
assert_warn(/string literal in condition/) do
eval('1 if ""')
end
+ assert_warning(/string literal in condition/) do
+ eval('1 if __FILE__')
+ end
assert_warn(/regex literal in condition/) do
eval('1 if //')
end
assert_warning(/literal in condition/) do
eval('1 if 1')
end
+ assert_warning(/literal in condition/) do
+ eval('1 if __LINE__')
+ end
assert_warning(/symbol literal in condition/) do
eval('1 if :foo')
end
@@ -1258,7 +1339,7 @@ eom
end
def test_parenthesised_statement_argument
- assert_syntax_error("foo(bar rescue nil)", /unexpected `rescue' modifier/)
+ assert_syntax_error("foo(bar rescue nil)", /unexpected 'rescue' modifier/)
assert_valid_syntax("foo (bar rescue nil)")
end
@@ -1308,6 +1389,25 @@ eom
assert_valid_syntax 'p :foo, {proc do end => proc do end, b: proc do end}', bug13073
end
+ def test_invalid_encoding_symbol
+ assert_syntax_error('{"\xC3": 1}', "invalid symbol")
+ end
+
+ def test_invalid_symbol_in_hash_memory_leak
+ assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true)
+ str = '{"\xC3": 1}'.force_encoding("UTF-8")
+ code = proc do
+ eval(str)
+ raise "unreachable"
+ rescue SyntaxError
+ end
+
+ 1_000.times(&code)
+ begin;
+ 1_000_000.times(&code)
+ end;
+ end
+
def test_do_after_local_variable
obj = Object.new
def obj.m; yield; end
@@ -1356,9 +1456,10 @@ eom
"#{return}"
raise((return; "should not raise"))
begin raise; ensure return; end; self
- begin raise; ensure return; end and self
nil&defined?0--begin e=no_method_error(); return; 0;end
return puts('ignored') #=> ignored
+ BEGIN {return}
+ END {return if false}
end;
.split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
failed = proc do |n, s|
@@ -1388,6 +1489,54 @@ eom
end
end
+ def test_eval_return_toplevel
+ feature4840 = '[ruby-core:36785] [Feature #4840]'
+ line = __LINE__+2
+ code = "#{<<~"begin;"}#{<<~'end;'}"
+ begin;
+ eval "return"; raise
+ begin eval "return"; rescue SystemExit; exit false; end
+ begin eval "return"; ensure puts "ensured"; end #=> ensured
+ begin ensure eval "return"; end
+ begin raise; ensure; eval "return"; end
+ begin raise; rescue; eval "return"; end
+ eval "return false"; raise
+ eval "return 1"; raise
+ "#{eval "return"}"
+ raise((eval "return"; "should not raise"))
+ begin raise; ensure eval "return"; end; self
+ begin raise; ensure eval "return"; end and self
+ eval "return puts('ignored')" #=> ignored
+ BEGIN {eval "return"}
+ end;
+ .split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
+ failed = proc do |n, s|
+ RubyVM::InstructionSequence.compile(s, __FILE__, nil, n).disasm
+ end
+ Tempfile.create(%w"test_return_ .rb") do |lib|
+ lib.close
+ args = %W[-W0 -r#{lib.path}]
+ all_assertions_foreach(feature4840, *[:main, :lib].product([:class, :top], code)) do |main, klass, (n, s, *ex)|
+ if klass == :class
+ s = "class X; #{s}; end"
+ if main == :main
+ assert_in_out_err(%[-W0], s, ex, /return/, proc {failed[n, s]}, success: false)
+ else
+ File.write(lib, s)
+ assert_in_out_err(args, "", ex, /return/, proc {failed[n, s]}, success: false)
+ end
+ else
+ if main == :main
+ assert_in_out_err(%[-W0], s, ex, [], proc {failed[n, s]}, success: true)
+ else
+ File.write(lib, s)
+ assert_in_out_err(args, "", ex, [], proc {failed[n, s]}, success: true)
+ end
+ end
+ end
+ end
+ end
+
def test_return_toplevel_with_argument
assert_warn(/argument of top-level return is ignored/) {eval("return 1")}
end
@@ -1396,6 +1545,20 @@ eom
assert_in_out_err(['-e', 'class TestSyntax; proc{ return }.call; end'], "", [], /^-e:1:.*unexpected return \(LocalJumpError\)/)
end
+ def test_return_in_END
+ assert_normal_exit('END {return}')
+ end
+
+ def test_return_in_BEGIN_in_eval
+ # `BEGIN` in `eval` is allowed, even inside a method, and `return`
+ # from that block exits from that method without `LocalJumpError`.
+ obj = Object.new
+ def obj.ok
+ eval("BEGIN {return :ok}")
+ end
+ assert_equal :ok, assert_nothing_raised(LocalJumpError) {obj.ok}
+ end
+
def test_syntax_error_in_rescue
bug12613 = '[ruby-core:76531] [Bug #12613]'
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
@@ -1615,6 +1778,29 @@ eom
def test_command_with_cmd_brace_block
assert_valid_syntax('obj.foo (1) {}')
assert_valid_syntax('obj::foo (1) {}')
+ assert_valid_syntax('bar {}')
+ assert_valid_syntax('Bar {}')
+ assert_valid_syntax('bar() {}')
+ assert_valid_syntax('Bar() {}')
+ assert_valid_syntax('Foo::bar {}')
+ assert_valid_syntax('Foo::Bar {}')
+ assert_valid_syntax('Foo::bar() {}')
+ assert_valid_syntax('Foo::Bar() {}')
+ end
+
+ def test_command_newline_in_tlparen_args
+ assert_valid_syntax("p (1\n2\n),(3),(4)")
+ assert_valid_syntax("p (\n),(),()")
+ assert_valid_syntax("a.b (1\n2\n),(3),(4)")
+ assert_valid_syntax("a.b (\n),(),()")
+ end
+
+ def test_command_semicolon_in_tlparen_at_the_first_arg
+ bug19281 = '[ruby-core:111499] [Bug #19281]'
+ assert_valid_syntax('p (1;2),(3),(4)', bug19281)
+ assert_valid_syntax('p (;),(),()', bug19281)
+ assert_valid_syntax('a.b (1;2),(3),(4)', bug19281)
+ assert_valid_syntax('a.b (;),(),()', bug19281)
end
def test_numbered_parameter
@@ -1645,7 +1831,7 @@ eom
assert_syntax_error('def x(_4) end', /_4 is reserved for numbered parameter/)
assert_syntax_error('def _5; end', /_5 is reserved for numbered parameter/)
assert_syntax_error('def self._6; end', /_6 is reserved for numbered parameter/)
- assert_raise_with_message(NameError, /undefined local variable or method `_1'/) {
+ assert_raise_with_message(NameError, /undefined local variable or method '_1'/) {
eval('_1')
}
['class C', 'class << C', 'module M', 'def m', 'def o.m'].each do |c|
@@ -1660,6 +1846,61 @@ eom
assert_raise(NameError) {eval("_1")},
]
}
+
+ assert_valid_syntax("proc {def foo(_);end;_1}")
+ assert_valid_syntax("p { [_1 **2] }")
+ assert_valid_syntax("proc {_1;def foo();end;_1}")
+ end
+
+ def test_it
+ assert_valid_syntax('proc {it}')
+ assert_syntax_error('[1,2].then {it+_2}', /'it' is already used/)
+ assert_syntax_error('[1,2].then {_2+it}', /numbered parameter is already used/)
+ assert_equal([1, 2], eval('[1,2].then {it}'))
+ assert_syntax_error('[1,2].then {"#{it}#{_2}"}', /'it' is already used/)
+ assert_syntax_error('[1,2].then {"#{_2}#{it}"}', /numbered parameter is already used/)
+ assert_syntax_error('->{it+_2}.call(1,2)', /'it' is already used/)
+ assert_syntax_error('->{_2+it}.call(1,2)', /numbered parameter is already used/)
+ assert_equal(4, eval('->(a=->{it}){a}.call.call(4)'))
+ assert_equal(5, eval('-> a: ->{it} {a}.call.call(5)'))
+ assert_syntax_error('proc {|| it}', /ordinary parameter is defined/)
+ assert_syntax_error('proc {|;a| it}', /ordinary parameter is defined/)
+ assert_syntax_error("proc {|\n| it}", /ordinary parameter is defined/)
+ assert_syntax_error('proc {|x| it}', /ordinary parameter is defined/)
+ assert_equal([1, 2], eval('1.then {[it, 2.then {_1}]}'))
+ assert_equal([2, 1], eval('1.then {[2.then {_1}, it]}'))
+ assert_syntax_error('->(){it}', /ordinary parameter is defined/)
+ assert_syntax_error('->(x){it}', /ordinary parameter is defined/)
+ assert_syntax_error('->x{it}', /ordinary parameter is defined/)
+ assert_syntax_error('->x:_1{}', /ordinary parameter is defined/)
+ assert_syntax_error('->x=it{}', /ordinary parameter is defined/)
+ assert_valid_syntax('-> {it; -> {_2}}')
+ assert_valid_syntax('-> {-> {it}; _2}')
+ assert_equal([1, nil], eval('proc {that=it; it=nil; [that, it]}.call(1)'))
+ assert_equal(1, eval('proc {it = 1}.call'))
+ assert_warning(/1: warning: assigned but unused variable - it/) {
+ assert_equal(2, eval('a=Object.new; def a.foo; it = 2; end; a.foo'))
+ }
+ assert_equal(3, eval('proc {|it| it}.call(3)'))
+ assert_equal(4, eval('a=Object.new; def a.foo(it); it; end; a.foo(4)'))
+ assert_equal(5, eval('a=Object.new; def a.it; 5; end; a.it'))
+ assert_equal(6, eval('a=Class.new; a.class_eval{ def it; 6; end }; a.new.it'))
+ assert_raise_with_message(NameError, /undefined local variable or method 'it'/) do
+ eval('it')
+ end
+ ['class C', 'class << C', 'module M', 'def m', 'def o.m'].each do |c|
+ assert_valid_syntax("->{#{c};->{it};end;it}\n")
+ assert_valid_syntax("->{it;#{c};->{it};end}\n")
+ end
+ 1.times do
+ [
+ assert_equal(0, it),
+ assert_equal([:a], eval('[:a].map{it}')),
+ assert_raise(NameError) {eval('it')},
+ ]
+ end
+ assert_valid_syntax('proc {def foo(_);end;it}')
+ assert_syntax_error('p { [it **2] }', /unexpected \*\*arg/)
end
def test_value_expr_in_condition
@@ -1670,6 +1911,11 @@ eom
assert_valid_syntax("tap {a = (break unless true)}")
end
+ def test_value_expr_in_singleton
+ mesg = /void value expression/
+ assert_syntax_error("class << (return); end", mesg)
+ end
+
def test_tautological_condition
assert_valid_syntax("def f() return if false and invalid; nil end")
assert_valid_syntax("def f() return unless true or invalid; nil end")
@@ -1707,6 +1953,8 @@ eom
assert_syntax_error('def foo(...) foo[...] = x; end', /unexpected/)
assert_syntax_error('def foo(...) foo(...) { }; end', /both block arg and actual block given/)
assert_syntax_error('def foo(...) defined?(...); end', /unexpected/)
+ assert_syntax_error('def foo(*rest, ...) end', '... after rest argument')
+ assert_syntax_error('def foo(*, ...) end', '... after rest argument')
obj1 = Object.new
def obj1.bar(*args, **kws, &block)
@@ -1907,6 +2155,28 @@ eom
assert_equal 0...1, exp.call(a: 0)
end
+ def test_argument_forwarding_with_super
+ assert_valid_syntax('def foo(...) super {}; end')
+ assert_valid_syntax('def foo(...) super() {}; end')
+ assert_syntax_error('def foo(...) super(...) {}; end', /both block arg and actual block/)
+ assert_syntax_error('def foo(...) super(1, ...) {}; end', /both block arg and actual block/)
+ end
+
+ def test_class_module_Object_ancestors
+ assert_separately([], <<-RUBY)
+ m = Module.new
+ m::Bug18832 = 1
+ include m
+ class Bug18832; end
+ RUBY
+ assert_separately([], <<-RUBY)
+ m = Module.new
+ m::Bug18832 = 1
+ include m
+ module Bug18832; end
+ RUBY
+ end
+
def test_cdhash
assert_separately([], <<-RUBY)
n = case 1 when 2r then false else true end