1# frozen_string_literal: false
2require 'test/unit'
3
4class TestSyntax < Test::Unit::TestCase
5  using Module.new {
6    refine(Object) do
7      def `(s) #`
8        s
9      end
10    end
11  }
12
13  def assert_syntax_files(test)
14    srcdir = File.expand_path("../../..", __FILE__)
15    srcdir = File.join(srcdir, test)
16    assert_separately(%W[--disable-gem - #{srcdir}],
17                      __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
18      dir = ARGV.shift
19      for script in Dir["#{dir}/**/*.rb"].sort
20        assert_valid_syntax(IO::read(script), script)
21      end
22    eom
23  end
24
25  def test_syntax_lib; assert_syntax_files("lib"); end
26  def test_syntax_sample; assert_syntax_files("sample"); end
27  def test_syntax_ext; assert_syntax_files("ext"); end
28  def test_syntax_test; assert_syntax_files("test"); end
29
30  def test_defined_empty_argument
31    bug8220 = '[ruby-core:53999] [Bug #8220]'
32    assert_ruby_status(%w[--disable-gem], 'puts defined? ()', bug8220)
33  end
34
35  def test_must_ascii_compatible
36    require 'tempfile'
37    f = Tempfile.new("must_ac_")
38    Encoding.list.each do |enc|
39      next unless enc.ascii_compatible?
40      make_tmpsrc(f, "# -*- coding: #{enc.name} -*-")
41      assert_nothing_raised(ArgumentError, enc.name) {load(f.path)}
42    end
43    Encoding.list.each do |enc|
44      next if enc.ascii_compatible?
45      make_tmpsrc(f, "# -*- coding: #{enc.name} -*-")
46      assert_raise(ArgumentError, enc.name) {load(f.path)}
47    end
48  ensure
49    f&.close!
50  end
51
52  def test_script_lines
53    require 'tempfile'
54    f = Tempfile.new("bug4361_")
55    bug4361 = '[ruby-dev:43168]'
56    with_script_lines do |debug_lines|
57      Encoding.list.each do |enc|
58        next unless enc.ascii_compatible?
59        make_tmpsrc(f, "# -*- coding: #{enc.name} -*-\n#----------------")
60        load(f.path)
61        assert_equal([f.path], debug_lines.keys)
62        assert_equal([enc, enc], debug_lines[f.path].map(&:encoding), bug4361)
63      end
64    end
65  ensure
66    f&.close!
67  end
68
69  def test_newline_in_block_parameters
70    bug = '[ruby-dev:45292]'
71    ["", "a", "a, b"].product(["", ";x", [";", "x"]]) do |params|
72      params = ["|", *params, "|"].join("\n")
73      assert_valid_syntax("1.times{#{params}}", __FILE__, "#{bug} #{params.inspect}")
74    end
75  end
76
77  tap do |_,
78    bug6115 = '[ruby-dev:45308]',
79    blockcall = '["elem"].each_with_object [] do end',
80    methods = [['map', 'no'], ['inject([])', 'with']],
81    blocks = [['do end', 'do'], ['{}', 'brace']],
82    *|
83    [%w'. dot', %w':: colon'].product(methods, blocks) do |(c, n1), (m, n2), (b, n3)|
84      m = m.tr_s('()', ' ').strip if n2 == 'do'
85      name = "test_#{n3}_block_after_blockcall_#{n1}_#{n2}_arg"
86      code = "#{blockcall}#{c}#{m} #{b}"
87      define_method(name) {assert_valid_syntax(code, bug6115)}
88    end
89  end
90
91  def test_do_block_in_cmdarg
92    bug9726 = '[ruby-core:61950] [Bug #9726]'
93    assert_valid_syntax("tap (proc do end)", __FILE__, bug9726)
94  end
95
96  def test_normal_argument
97    assert_valid_syntax('def foo(x) end')
98    assert_syntax_error('def foo(X) end', /constant/)
99    assert_syntax_error('def foo(@x) end', /instance variable/)
100    assert_syntax_error('def foo(@@x) end', /class variable/)
101  end
102
103  def test_optional_argument
104    assert_valid_syntax('def foo(x=nil) end')
105    assert_syntax_error('def foo(X=nil) end', /constant/)
106    assert_syntax_error('def foo(@x=nil) end', /instance variable/)
107    assert_syntax_error('def foo(@@x=nil) end', /class variable/)
108  end
109
110  def test_keyword_rest
111    bug5989 = '[ruby-core:42455]'
112    assert_valid_syntax("def kwrest_test(**a) a; end", __FILE__, bug5989)
113    assert_valid_syntax("def kwrest_test2(**a, &b) end", __FILE__, bug5989)
114    o = Object.new
115    def o.kw(**a) a end
116    assert_equal({}, o.kw, bug5989)
117    assert_equal({foo: 1}, o.kw(foo: 1), bug5989)
118    assert_equal({foo: 1, bar: 2}, o.kw(foo: 1, bar: 2), bug5989)
119    EnvUtil.under_gc_stress do
120      eval("def o.m(k: 0) k end")
121    end
122    assert_equal(42, o.m(k: 42), '[ruby-core:45744]')
123    bug7922 = '[ruby-core:52744] [Bug #7922]'
124    def o.bug7922(**) end
125    assert_nothing_raised(ArgumentError, bug7922) {o.bug7922(foo: 42)}
126  end
127
128  class KW2
129    def kw(k1: 1, k2: 2) [k1, k2] end
130  end
131
132  def test_keyword_splat
133    assert_valid_syntax("foo(**h)", __FILE__)
134    o = KW2.new
135    h = {k1: 11, k2: 12}
136    assert_equal([11, 12], o.kw(**h))
137    assert_equal([11, 12], o.kw(k2: 22, **h))
138    assert_equal([11, 22], o.kw(**h, **{k2: 22}))
139    assert_equal([11, 12], o.kw(**{k2: 22}, **h))
140  end
141
142  def test_keyword_duplicated_splat
143    bug10315 = '[ruby-core:65368] [Bug #10315]'
144
145    o = KW2.new
146    assert_equal([23, 2], o.kw(**{k1: 22}, **{k1: 23}), bug10315)
147
148    h = {k3: 31}
149    assert_raise(ArgumentError) {o.kw(**h)}
150    h = {"k1"=>11, k2: 12}
151    assert_raise(TypeError) {o.kw(**h)}
152  end
153
154  def test_keyword_duplicated
155    bug10315 = '[ruby-core:65625] [Bug #10315]'
156    a = []
157    def a.add(x) push(x); x; end
158    def a.f(k:) k; end
159    a.clear
160    r = nil
161    assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), k: a.add(2))")}
162    assert_equal(2, r)
163    assert_equal([1, 2], a, bug10315)
164    a.clear
165    r = nil
166    assert_warn(/duplicated/) {r = eval("a.f({k: a.add(1), k: a.add(2)})")}
167    assert_equal(2, r)
168    assert_equal([1, 2], a, bug10315)
169  end
170
171  def test_keyword_empty_splat
172    assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
173    begin;
174      bug10719 = '[ruby-core:67446] [Bug #10719]'
175      assert_valid_syntax("foo(a: 1, **{})", bug10719)
176    end;
177    assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
178    begin;
179      bug13756 = '[ruby-core:82113] [Bug #13756]'
180      assert_valid_syntax("defined? foo(**{})", bug13756)
181    end;
182    assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
183    begin;
184      bug15271 = '[ruby-core:89648] [Bug #15271]'
185      assert_valid_syntax("a **{}", bug15271)
186    end;
187  end
188
189  def test_keyword_self_reference
190    bug9593 = '[ruby-core:61299] [Bug #9593]'
191    o = Object.new
192    assert_warn(/circular argument reference - var/) do
193      o.instance_eval("def foo(var: defined?(var)) var end")
194    end
195    assert_equal(42, o.foo(var: 42))
196    assert_equal("local-variable", o.foo, bug9593)
197
198    o = Object.new
199    assert_warn(/circular argument reference - var/) do
200      o.instance_eval("def foo(var: var) var end")
201    end
202    assert_nil(o.foo, bug9593)
203
204    o = Object.new
205    assert_warn(/circular argument reference - var/) do
206      o.instance_eval("def foo(var: bar(var)) var end")
207    end
208
209    o = Object.new
210    assert_warn(/circular argument reference - var/) do
211      o.instance_eval("def foo(var: bar {var}) var end")
212    end
213
214    o = Object.new
215    assert_warn("") do
216      o.instance_eval("def foo(var: bar {|var| var}) var end")
217    end
218
219    o = Object.new
220    assert_warn("") do
221      o.instance_eval("def foo(var: def bar(var) var; end) var end")
222    end
223
224    o = Object.new
225    assert_warn("") do
226      o.instance_eval("proc {|var: 1| var}")
227    end
228  end
229
230  def test_keyword_invalid_name
231    bug11663 = '[ruby-core:71356] [Bug #11663]'
232
233    o = o = Object.new
234    assert_syntax_error('def o.foo(arg1?:) end', /arg1\?/, bug11663)
235    assert_syntax_error('def o.foo(arg1?:, arg2:) end', /arg1\?/, bug11663)
236    assert_syntax_error('proc {|arg1?:|}', /arg1\?/, bug11663)
237    assert_syntax_error('proc {|arg1?:, arg2:|}', /arg1\?/, bug11663)
238
239    bug10545 = '[ruby-dev:48742] [Bug #10545]'
240    assert_syntax_error('def o.foo(FOO: a) end', /constant/, bug10545)
241    assert_syntax_error('def o.foo(@foo: a) end', /instance variable/)
242    assert_syntax_error('def o.foo(@@foo: a) end', /class variable/)
243  end
244
245  def test_optional_self_reference
246    bug9593 = '[ruby-core:61299] [Bug #9593]'
247    o = Object.new
248    assert_warn(/circular argument reference - var/) do
249      o.instance_eval("def foo(var = defined?(var)) var end")
250    end
251    assert_equal(42, o.foo(42))
252    assert_equal("local-variable", o.foo, bug9593)
253
254    o = Object.new
255    assert_warn(/circular argument reference - var/) do
256      o.instance_eval("def foo(var = var) var end")
257    end
258    assert_nil(o.foo, bug9593)
259
260    o = Object.new
261    assert_warn(/circular argument reference - var/) do
262      o.instance_eval("def foo(var = bar(var)) var end")
263    end
264
265    o = Object.new
266    assert_warn(/circular argument reference - var/) do
267      o.instance_eval("def foo(var = bar {var}) var end")
268    end
269
270    o = Object.new
271    assert_warn(/circular argument reference - var/) do
272      o.instance_eval("def foo(var = (def bar;end; var)) var end")
273    end
274
275    o = Object.new
276    assert_warn(/circular argument reference - var/) do
277      o.instance_eval("def foo(var = (def self.bar;end; var)) var end")
278    end
279
280    o = Object.new
281    assert_warn("") do
282      o.instance_eval("def foo(var = bar {|var| var}) var end")
283    end
284
285    o = Object.new
286    assert_warn("") do
287      o.instance_eval("def foo(var = def bar(var) var; end) var end")
288    end
289
290    o = Object.new
291    assert_warn("") do
292      o.instance_eval("proc {|var = 1| var}")
293    end
294  end
295
296  def test_warn_grouped_expression
297    bug5214 = '[ruby-core:39050]'
298    assert_warning("", bug5214) do
299      assert_valid_syntax("foo \\\n(\n  true)", "test", verbose: true)
300    end
301  end
302
303  def test_warn_unreachable
304    assert_warning("test:3: warning: statement not reached\n") do
305      code = "loop do\n" "break\n" "foo\n" "end"
306      assert_valid_syntax(code, "test", verbose: true)
307    end
308  end
309
310  def test_warn_balanced
311    warning = <<WARN
312test:1: warning: `%s' after local variable or literal is interpreted as binary operator
313test:1: warning: even though it seems like %s
314WARN
315    [
316     [:**, "argument prefix"],
317     [:*, "argument prefix"],
318     [:<<, "here document"],
319     [:&, "argument prefix"],
320     [:+, "unary operator"],
321     [:-, "unary operator"],
322     [:/, "regexp literal"],
323     [:%, "string literal"],
324    ].each do |op, syn|
325      all_assertions do |a|
326        ["puts 1 #{op}0", "puts :a #{op}0", "m = 1; puts m #{op}0"].each do |src|
327          a.for(src) do
328            assert_warning(warning % [op, syn], src) do
329              assert_valid_syntax(src, "test", verbose: true)
330            end
331          end
332        end
333      end
334    end
335  end
336
337  def test_cmd_symbol_after_keyword
338    bug6347 = '[ruby-dev:45563]'
339    assert_not_label(:foo, 'if true then not_label:foo end', bug6347)
340    assert_not_label(:foo, 'if false; else not_label:foo end', bug6347)
341    assert_not_label(:foo, 'begin not_label:foo end', bug6347)
342    assert_not_label(:foo, 'begin ensure not_label:foo end', bug6347)
343  end
344
345  def test_cmd_symbol_in_string
346    bug6347 = '[ruby-dev:45563]'
347    assert_not_label(:foo, '"#{not_label:foo}"', bug6347)
348  end
349
350  def test_cmd_symbol_singleton_class
351    bug6347 = '[ruby-dev:45563]'
352    @not_label = self
353    assert_not_label(:foo, 'class << not_label:foo; end', bug6347)
354  end
355
356  def test_cmd_symbol_superclass
357    bug6347 = '[ruby-dev:45563]'
358    @not_label = Object
359    assert_not_label(:foo, 'class Foo < not_label:foo; end', bug6347)
360  end
361
362  def test_no_label_with_percent
363    assert_syntax_error('{%"a": 1}', /unexpected ':'/)
364    assert_syntax_error("{%'a': 1}", /unexpected ':'/)
365    assert_syntax_error('{%Q"a": 1}', /unexpected ':'/)
366    assert_syntax_error("{%Q'a': 1}", /unexpected ':'/)
367    assert_syntax_error('{%q"a": 1}', /unexpected ':'/)
368    assert_syntax_error("{%q'a': 1}", /unexpected ':'/)
369  end
370
371  def test_block_after_cond
372    bug10653 = '[ruby-dev:48790] [Bug #10653]'
373    assert_valid_syntax("false ? raise {} : tap {}", bug10653)
374    assert_valid_syntax("false ? raise do end : tap do end", bug10653)
375  end
376
377  def test_paren_after_label
378    bug11456 = '[ruby-dev:49221] [Bug #11456]'
379    assert_valid_syntax("{foo: (1 rescue 0)}", bug11456)
380    assert_valid_syntax("{foo: /=/}", bug11456)
381  end
382
383  def test_percent_string_after_label
384    bug11812 = '[ruby-core:72084]'
385    assert_valid_syntax('{label:%w(*)}', bug11812)
386    assert_valid_syntax('{label: %w(*)}', bug11812)
387  end
388
389  def test_heredoc_after_label
390    bug11849 = '[ruby-core:72396] [Bug #11849]'
391    assert_valid_syntax("{label:<<DOC\n""DOC\n""}", bug11849)
392    assert_valid_syntax("{label:<<-DOC\n""DOC\n""}", bug11849)
393    assert_valid_syntax("{label:<<~DOC\n""DOC\n""}", bug11849)
394    assert_valid_syntax("{label: <<DOC\n""DOC\n""}", bug11849)
395    assert_valid_syntax("{label: <<-DOC\n""DOC\n""}", bug11849)
396    assert_valid_syntax("{label: <<~DOC\n""DOC\n""}", bug11849)
397  end
398
399  def test_cmdarg_kwarg_lvar_clashing_method
400    bug12073 = '[ruby-core:73816] [Bug#12073]'
401    a = a = 1
402    assert_valid_syntax("a b: 1")
403    assert_valid_syntax("a = 1; a b: 1", bug12073)
404  end
405
406  def test_duplicated_arg
407    assert_syntax_error("def foo(a, a) end", /duplicated argument name/)
408    assert_valid_syntax("def foo(_, _) end")
409    (obj = Object.new).instance_eval("def foo(_, x, _) x end")
410    assert_equal(2, obj.foo(1, 2, 3))
411  end
412
413  def test_duplicated_rest
414    assert_syntax_error("def foo(a, *a) end", /duplicated argument name/)
415    assert_valid_syntax("def foo(_, *_) end")
416    (obj = Object.new).instance_eval("def foo(_, x, *_) x end")
417    assert_equal(2, obj.foo(1, 2, 3))
418  end
419
420  def test_duplicated_opt
421    assert_syntax_error("def foo(a, a=1) end", /duplicated argument name/)
422    assert_valid_syntax("def foo(_, _=1) end")
423    (obj = Object.new).instance_eval("def foo(_, x, _=42) x end")
424    assert_equal(2, obj.foo(1, 2))
425  end
426
427  def test_duplicated_opt_rest
428    assert_syntax_error("def foo(a=1, *a) end", /duplicated argument name/)
429    assert_valid_syntax("def foo(_=1, *_) end")
430    (obj = Object.new).instance_eval("def foo(_, x=42, *_) x end")
431    assert_equal(42, obj.foo(1))
432    assert_equal(2, obj.foo(1, 2))
433  end
434
435  def test_duplicated_rest_opt
436    assert_syntax_error("def foo(*a, a=1) end", /duplicated argument name/)
437  end
438
439  def test_duplicated_rest_post
440    assert_syntax_error("def foo(*a, a) end", /duplicated argument name/)
441    assert_valid_syntax("def foo(*_, _) end")
442    (obj = Object.new).instance_eval("def foo(*_, x, _) x end")
443    assert_equal(2, obj.foo(1, 2, 3))
444    assert_equal(2, obj.foo(2, 3))
445    (obj = Object.new).instance_eval("def foo(*_, _, x) x end")
446    assert_equal(3, obj.foo(1, 2, 3))
447    assert_equal(3, obj.foo(2, 3))
448  end
449
450  def test_duplicated_opt_post
451    assert_syntax_error("def foo(a=1, a) end", /duplicated argument name/)
452    assert_valid_syntax("def foo(_=1, _) end")
453    (obj = Object.new).instance_eval("def foo(_=1, x, _) x end")
454    assert_equal(2, obj.foo(1, 2, 3))
455    assert_equal(2, obj.foo(2, 3))
456    (obj = Object.new).instance_eval("def foo(_=1, _, x) x end")
457    assert_equal(3, obj.foo(1, 2, 3))
458    assert_equal(3, obj.foo(2, 3))
459  end
460
461  def test_duplicated_kw
462    assert_syntax_error("def foo(a, a: 1) end", /duplicated argument name/)
463    assert_valid_syntax("def foo(_, _: 1) end")
464    (obj = Object.new).instance_eval("def foo(_, x, _: 1) x end")
465    assert_equal(3, obj.foo(2, 3))
466    assert_equal(3, obj.foo(2, 3, _: 42))
467    (obj = Object.new).instance_eval("def foo(x, _, _: 1) x end")
468    assert_equal(2, obj.foo(2, 3))
469    assert_equal(2, obj.foo(2, 3, _: 42))
470  end
471
472  def test_duplicated_rest_kw
473    assert_syntax_error("def foo(*a, a: 1) end", /duplicated argument name/)
474    assert_nothing_raised {def foo(*_, _: 1) end}
475    (obj = Object.new).instance_eval("def foo(*_, x: 42, _: 1) x end")
476    assert_equal(42, obj.foo(42))
477    assert_equal(42, obj.foo(2, _: 0))
478    assert_equal(2, obj.foo(x: 2, _: 0))
479  end
480
481  def test_duplicated_opt_kw
482    assert_syntax_error("def foo(a=1, a: 1) end", /duplicated argument name/)
483    assert_valid_syntax("def foo(_=1, _: 1) end")
484    (obj = Object.new).instance_eval("def foo(_=42, x, _: 1) x end")
485    assert_equal(0, obj.foo(0))
486    assert_equal(0, obj.foo(0, _: 3))
487  end
488
489  def test_duplicated_kw_kwrest
490    assert_syntax_error("def foo(a: 1, **a) end", /duplicated argument name/)
491    assert_valid_syntax("def foo(_: 1, **_) end")
492    (obj = Object.new).instance_eval("def foo(_: 1, x: 42, **_) x end")
493    assert_equal(42, obj.foo())
494    assert_equal(42, obj.foo(a: 0))
495    assert_equal(42, obj.foo(_: 0, a: 0))
496    assert_equal(1, obj.foo(_: 0, x: 1, a: 0))
497  end
498
499  def test_duplicated_rest_kwrest
500    assert_syntax_error("def foo(*a, **a) end", /duplicated argument name/)
501    assert_valid_syntax("def foo(*_, **_) end")
502    (obj = Object.new).instance_eval("def foo(*_, x, **_) x end")
503    assert_equal(1, obj.foo(1))
504    assert_equal(1, obj.foo(1, a: 0))
505    assert_equal(2, obj.foo(1, 2, a: 0))
506  end
507
508  def test_duplicated_opt_kwrest
509    assert_syntax_error("def foo(a=1, **a) end", /duplicated argument name/)
510    assert_valid_syntax("def foo(_=1, **_) end")
511    (obj = Object.new).instance_eval("def foo(_=42, x, **_) x end")
512    assert_equal(1, obj.foo(1))
513    assert_equal(1, obj.foo(1, a: 0))
514    assert_equal(1, obj.foo(0, 1, a: 0))
515  end
516
517  def test_duplicated_when
518    w = 'warning: duplicated when clause is ignored'
519    assert_warning(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){
520      eval %q{
521        case 1
522        when 1, 1
523        when 1, 1
524        when 1, 1
525        end
526      }
527    }
528    assert_warning(/#{w}/){#/3: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){
529      a = a = 1
530      eval %q{
531        case 1
532        when 1, 1
533        when 1, a
534        when 1, 1
535        end
536      }
537    }
538  end
539
540  def test_invalid_break
541    assert_syntax_error("def m; break; end", /Invalid break/)
542    assert_syntax_error('/#{break}/', /Invalid break/)
543    assert_syntax_error('/#{break}/o', /Invalid break/)
544  end
545
546  def test_invalid_next
547    assert_syntax_error("def m; next; end", /Invalid next/)
548    assert_syntax_error('/#{next}/', /Invalid next/)
549    assert_syntax_error('/#{next}/o', /Invalid next/)
550  end
551
552  def test_lambda_with_space
553    feature6390 = '[ruby-dev:45605]'
554    assert_valid_syntax("-> (x, y) {}", __FILE__, feature6390)
555  end
556
557  def test_do_block_in_cmdarg_begin
558    bug6419 = '[ruby-dev:45631]'
559    assert_valid_syntax("p begin 1.times do 1 end end", __FILE__, bug6419)
560  end
561
562  def test_do_block_in_call_args
563    bug9308 = '[ruby-core:59342] [Bug #9308]'
564    assert_valid_syntax("bar def foo; self.each do end end", bug9308)
565  end
566
567  def test_do_block_in_lambda
568    bug11107 = '[ruby-core:69017] [Bug #11107]'
569    assert_valid_syntax('p ->() do a() do end end', bug11107)
570  end
571
572  def test_do_block_after_lambda
573    bug11380 = '[ruby-core:70067] [Bug #11380]'
574    assert_valid_syntax('p -> { :hello }, a: 1 do end', bug11380)
575  end
576
577  def test_reserved_method_no_args
578    bug6403 = '[ruby-dev:45626]'
579    assert_valid_syntax("def self; :foo; end", __FILE__, bug6403)
580  end
581
582  def test_unassignable
583    gvar = global_variables
584    %w[self nil true false __FILE__ __LINE__ __ENCODING__].each do |kwd|
585      assert_raise(SyntaxError) {eval("#{kwd} = nil")}
586      assert_equal(gvar, global_variables)
587    end
588  end
589
590  Bug7559 = '[ruby-dev:46737]'
591
592  def test_lineno_command_call_quote
593    expected = __LINE__ + 1
594    actual = caller_lineno "a
595b
596c
597d
598e"
599    assert_equal(expected, actual, "#{Bug7559}: ")
600  end
601
602  def assert_dedented_heredoc(expect, result, mesg = "")
603    all_assertions(mesg) do |a|
604      %w[eos "eos" 'eos' `eos`].each do |eos|
605        a.for(eos) do
606          assert_equal(eval("<<-#{eos}\n#{expect}eos\n"),
607                       eval("<<~#{eos}\n#{result}eos\n"))
608        end
609      end
610    end
611  end
612
613  def test_dedented_heredoc_without_indentation
614    result = " y\n" \
615             "z\n"
616    expect = result
617    assert_dedented_heredoc(expect, result)
618  end
619
620  def test_dedented_heredoc_with_indentation
621    result = "     a\n" \
622             "    b\n"
623    expect = " a\n" \
624             "b\n"
625    assert_dedented_heredoc(expect, result)
626  end
627
628  def test_dedented_heredoc_with_blank_less_indented_line
629    # the blank line has two leading spaces
630    result = "    a\n" \
631             "  \n" \
632             "    b\n"
633    expect = "a\n" \
634             "\n" \
635             "b\n"
636    assert_dedented_heredoc(expect, result)
637  end
638
639  def test_dedented_heredoc_with_blank_less_indented_line_escaped
640    result = "    a\n" \
641             "\\ \\ \n" \
642             "    b\n"
643    expect = result
644    assert_dedented_heredoc(expect, result)
645  end
646
647  def test_dedented_heredoc_with_blank_more_indented_line
648    # the blank line has six leading spaces
649    result = "    a\n" \
650             "      \n" \
651             "    b\n"
652    expect = "a\n" \
653             "  \n" \
654             "b\n"
655    assert_dedented_heredoc(expect, result)
656  end
657
658  def test_dedented_heredoc_with_blank_more_indented_line_escaped
659    result = "    a\n" \
660             "\\ \\ \\ \\ \\ \\ \n" \
661             "    b\n"
662    expect = result
663    assert_dedented_heredoc(expect, result)
664  end
665
666  def test_dedented_heredoc_with_empty_line
667    result = "      This would contain specially formatted text.\n" \
668             "\n" \
669             "      That might span many lines\n"
670    expect = 'This would contain specially formatted text.'"\n" \
671             ''"\n" \
672             'That might span many lines'"\n"
673    assert_dedented_heredoc(expect, result)
674  end
675
676  def test_dedented_heredoc_with_interpolated_expression
677    result = '  #{1}a'"\n" \
678             " zy\n"
679    expect = ' #{1}a'"\n" \
680             "zy\n"
681    assert_dedented_heredoc(expect, result)
682  end
683
684  def test_dedented_heredoc_with_interpolated_string
685    w = w = ""
686    result = " \#{mesg} a\n" \
687             "  zy\n"
688    expect = '#{mesg} a'"\n" \
689             ' zy'"\n"
690    assert_dedented_heredoc(expect, result)
691  end
692
693  def test_dedented_heredoc_with_newline
694    bug11989 = '[ruby-core:72855] [Bug #11989] after escaped newline should not be dedented'
695    result = '  x\n'"  y\n" \
696             "  z\n"
697    expect = 'x\n'"  y\n" \
698             "z\n"
699    assert_dedented_heredoc(expect, result, bug11989)
700  end
701
702  def test_dedented_heredoc_with_concatenation
703    bug11990 = '[ruby-core:72857] [Bug #11990] concatenated string should not be dedented'
704    %w[eos "eos" 'eos'].each do |eos|
705      assert_equal("x\n  y",
706                   eval("<<~#{eos} '  y'\n  x\neos\n"),
707                   "#{bug11990} with #{eos}")
708    end
709    %w[eos "eos" 'eos' `eos`].each do |eos|
710      _, expect = eval("[<<~#{eos}, '  x']\n""  y\n""eos\n")
711      assert_equal('  x', expect, bug11990)
712    end
713  end
714
715  def test_dedented_heredoc_expr_at_beginning
716    result = "  a\n" \
717             '#{1}'"\n"
718    expected = "  a\n" \
719             '#{1}'"\n"
720    assert_dedented_heredoc(expected, result)
721  end
722
723  def test_dedented_heredoc_expr_string
724    result = '  one#{"  two  "}'"\n"
725    expected = 'one#{"  two  "}'"\n"
726    assert_dedented_heredoc(expected, result)
727  end
728
729  def test_dedented_heredoc_continued_line
730    result = "  1\\\n" "  2\n"
731    expected = "1\\\n" "2\n"
732    assert_dedented_heredoc(expected, result)
733    assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /can't find string "TEXT"/)
734    begin;
735      <<-TEXT
736      \
737      TEXT
738    end;
739    assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /can't find string "TEXT"/)
740    begin;
741      <<~TEXT
742      \
743      TEXT
744    end;
745  end
746
747  def test_lineno_after_heredoc
748    bug7559 = '[ruby-dev:46737]'
749    expected, _, actual = __LINE__, <<eom, __LINE__
750    a
751    b
752    c
753    d
754eom
755    assert_equal(expected, actual, bug7559)
756  end
757
758  def test_dedented_heredoc_invalid_identifer
759    assert_syntax_error('<<~ "#{}"', /unexpected <</)
760  end
761
762  def test_dedented_heredoc_concatenation
763    assert_equal("\n0\n1", eval("<<~0 '1'\n \n0\#{}\n0"))
764  end
765
766  def test_heredoc_mixed_encoding
767    assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source')
768      #encoding: cp932
769      <<-TEXT
770      \xe9\x9d\u1234
771      TEXT
772    HEREDOC
773    assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source')
774      #encoding: cp932
775      <<-TEXT
776      \xe9\x9d
777      \u1234
778      TEXT
779    HEREDOC
780    assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source')
781      #encoding: cp932
782      <<-TEXT
783      \u1234\xe9\x9d
784      TEXT
785    HEREDOC
786    assert_syntax_error(<<-'HEREDOC', 'UTF-8 mixed within Windows-31J source')
787      #encoding: cp932
788      <<-TEXT
789      \u1234
790      \xe9\x9d
791      TEXT
792    HEREDOC
793  end
794
795  def test_lineno_operation_brace_block
796    expected = __LINE__ + 1
797    actual = caller_lineno\
798    {}
799    assert_equal(expected, actual)
800  end
801
802  def assert_constant_reassignment_nested(preset, op, expected, err = [], bug = '[Bug #5449]')
803    [
804     ["p ", ""],                # no-pop
805     ["", "p Foo::Bar"],        # pop
806    ].each do |p1, p2|
807      src = <<-EOM.gsub(/^\s*\n/, '')
808      class Foo
809        #{"Bar = " + preset if preset}
810      end
811      #{p1}Foo::Bar #{op}= 42
812      #{p2}
813      EOM
814      msg = "\# #{bug}\n#{src}"
815      assert_valid_syntax(src, caller_locations(1, 1)[0].path, msg)
816      assert_in_out_err([], src, expected, err, msg)
817    end
818  end
819
820  def test_constant_reassignment_nested
821    already = /already initialized constant Foo::Bar/
822    uninitialized = /uninitialized constant Foo::Bar/
823    assert_constant_reassignment_nested(nil,     "||", %w[42])
824    assert_constant_reassignment_nested("false", "||", %w[42], already)
825    assert_constant_reassignment_nested("true",  "||", %w[true])
826    assert_constant_reassignment_nested(nil,     "&&", [], uninitialized)
827    assert_constant_reassignment_nested("false", "&&", %w[false])
828    assert_constant_reassignment_nested("true",  "&&", %w[42], already)
829    assert_constant_reassignment_nested(nil,     "+",  [], uninitialized)
830    assert_constant_reassignment_nested("false", "+",  [], /undefined method/)
831    assert_constant_reassignment_nested("11",    "+",  %w[53], already)
832  end
833
834  def assert_constant_reassignment_toplevel(preset, op, expected, err = [], bug = '[Bug #5449]')
835    [
836     ["p ", ""],                # no-pop
837     ["", "p ::Bar"],           # pop
838    ].each do |p1, p2|
839      src = <<-EOM.gsub(/^\s*\n/, '')
840      #{"Bar = " + preset if preset}
841      class Foo
842        #{p1}::Bar #{op}= 42
843        #{p2}
844      end
845      EOM
846      msg = "\# #{bug}\n#{src}"
847      assert_valid_syntax(src, caller_locations(1, 1)[0].path, msg)
848      assert_in_out_err([], src, expected, err, msg)
849    end
850  end
851
852  def test_constant_reassignment_toplevel
853    already = /already initialized constant Bar/
854    uninitialized = /uninitialized constant Bar/
855    assert_constant_reassignment_toplevel(nil,     "||", %w[42])
856    assert_constant_reassignment_toplevel("false", "||", %w[42], already)
857    assert_constant_reassignment_toplevel("true",  "||", %w[true])
858    assert_constant_reassignment_toplevel(nil,     "&&", [], uninitialized)
859    assert_constant_reassignment_toplevel("false", "&&", %w[false])
860    assert_constant_reassignment_toplevel("true",  "&&", %w[42], already)
861    assert_constant_reassignment_toplevel(nil,     "+",  [], uninitialized)
862    assert_constant_reassignment_toplevel("false", "+",  [], /undefined method/)
863    assert_constant_reassignment_toplevel("11",    "+",  %w[53], already)
864  end
865
866  def test_integer_suffix
867    ["1if true", "begin 1end"].each do |src|
868      assert_valid_syntax(src)
869      assert_equal(1, eval(src), src)
870    end
871  end
872
873  def test_value_of_def
874    assert_separately [], <<-EOS
875      assert_equal(:foo, (def foo; end))
876      assert_equal(:foo, (def (Object.new).foo; end))
877    EOS
878  end
879
880  def test_heredoc_cr
881    assert_syntax_error("puts <<""EOS\n""ng\n""EOS\r""NO\n", /can't find string "EOS" anywhere before EOF/)
882  end
883
884  def test_heredoc_newline
885    assert_warn(/ends with a newline/) do
886      eval("<<\"EOS\n\"\nEOS\n")
887    end
888  end
889
890  def test__END___cr
891    assert_syntax_error("__END__\r<<<<<\n", /unexpected <</)
892  end
893
894  def test_warning_for_cr
895    feature8699 = '[ruby-core:56240] [Feature #8699]'
896    assert_warning(/encountered \\r/, feature8699) do
897      eval("\r""__id__\r")
898    end
899  end
900
901  def test_unexpected_fraction
902    msg = /unexpected fraction/
903    assert_syntax_error("0x0.0", msg)
904    assert_syntax_error("0b0.0", msg)
905    assert_syntax_error("0d0.0", msg)
906    assert_syntax_error("0o0.0", msg)
907    assert_syntax_error("0.0.0", msg)
908  end
909
910  def test_error_message_encoding
911    bug10114 = '[ruby-core:64228] [Bug #10114]'
912    code = "# -*- coding: utf-8 -*-\n" "def n \"\u{2208}\"; end"
913    assert_syntax_error(code, /def n "\u{2208}"; end/, bug10114)
914  end
915
916  def test_null_range_cmdarg
917    bug10957 = '[ruby-core:68477] [Bug #10957]'
918    assert_ruby_status(['-c', '-e', 'p ()..0'], "", bug10957)
919    assert_ruby_status(['-c', '-e', 'p ()...0'], "", bug10957)
920    assert_syntax_error('0..%w.', /unterminated string/, bug10957)
921    assert_syntax_error('0...%w.', /unterminated string/, bug10957)
922  end
923
924  def test_too_big_nth_ref
925    bug11192 = '[ruby-core:69393] [Bug #11192]'
926    assert_warn(/too big/, bug11192) do
927      eval('$99999999999999999')
928    end
929  end
930
931  def test_invalid_symbol_space
932    assert_syntax_error(": foo", /unexpected ':'/)
933    assert_syntax_error(": #\n foo", /unexpected ':'/)
934    assert_syntax_error(":#\n foo", /unexpected ':'/)
935  end
936
937  def test_fluent_dot
938    assert_valid_syntax("a\n.foo")
939    assert_valid_syntax("a\n&.foo")
940  end
941
942  def test_no_warning_logop_literal
943    assert_warning("") do
944      eval("true||raise;nil")
945    end
946    assert_warning("") do
947      eval("false&&raise;nil")
948    end
949    assert_warning("") do
950      eval("''||raise;nil")
951    end
952  end
953
954  def test_warning_literal_in_condition
955    assert_warn(/literal in condition/) do
956      eval('1 if ""')
957    end
958    assert_warn(/literal in condition/) do
959      eval('1 if //')
960    end
961    assert_warn(/literal in condition/) do
962      eval('1 if true..false')
963    end
964    assert_warning(/literal in condition/) do
965      eval('1 if 1')
966    end
967    assert_warning(/literal in condition/) do
968      eval('1 if :foo')
969    end
970    assert_warning(/literal in condition/) do
971      eval('1 if :"#{"foo".upcase}"')
972    end
973
974    assert_warn('') do
975      eval('1 if !""')
976    end
977    assert_warn('') do
978      eval('1 if !//')
979    end
980    assert_warn('') do
981      eval('1 if !(true..false)')
982    end
983    assert_warning('') do
984      eval('1 if !1')
985    end
986    assert_warning('') do
987      eval('1 if !:foo')
988    end
989    assert_warning('') do
990      eval('1 if !:"#{"foo".upcase}"')
991    end
992  end
993
994  def test_alias_symbol
995    bug8851 = '[ruby-dev:47681] [Bug #8851]'
996    formats = ['%s', ":'%s'", ':"%s"', '%%s(%s)']
997    all_assertions(bug8851) do |all|
998      formats.product(formats) do |form1, form2|
999        all.for(code = "alias #{form1 % 'a'} #{form2 % 'p'}") do
1000          assert_valid_syntax(code)
1001        end
1002      end
1003    end
1004  end
1005
1006  def test_undef_symbol
1007    bug8851 = '[ruby-dev:47681] [Bug #8851]'
1008    formats = ['%s', ":'%s'", ':"%s"', '%%s(%s)']
1009    all_assertions(bug8851) do |all|
1010      formats.product(formats) do |form1, form2|
1011        all.for(code = "undef #{form1 % 'a'}, #{form2 % 'p'}") do
1012          assert_valid_syntax(code)
1013        end
1014      end
1015    end
1016  end
1017
1018  def test_parenthesised_statement_argument
1019    assert_syntax_error("foo(bar rescue nil)", /unexpected rescue \(modifier\)/)
1020    assert_valid_syntax("foo (bar rescue nil)")
1021  end
1022
1023  def test_cmdarg_in_paren
1024    bug11873 = '[ruby-core:72482] [Bug #11873]'
1025    assert_valid_syntax %q{a b{c d}, :e do end}, bug11873
1026    assert_valid_syntax %q{a b(c d), :e do end}, bug11873
1027    assert_valid_syntax %q{a b{c(d)}, :e do end}, bug11873
1028    assert_valid_syntax %q{a b(c(d)), :e do end}, bug11873
1029    assert_valid_syntax %q{a b{c d}, 1 do end}, bug11873
1030    assert_valid_syntax %q{a b(c d), 1 do end}, bug11873
1031    assert_valid_syntax %q{a b{c(d)}, 1 do end}, bug11873
1032    assert_valid_syntax %q{a b(c(d)), 1 do end}, bug11873
1033    assert_valid_syntax %q{a b{c d}, "x" do end}, bug11873
1034    assert_valid_syntax %q{a b(c d), "x" do end}, bug11873
1035    assert_valid_syntax %q{a b{c(d)}, "x" do end}, bug11873
1036    assert_valid_syntax %q{a b(c(d)), "x" do end}, bug11873
1037  end
1038
1039  def test_block_after_cmdarg_in_paren
1040    bug11873 = '[ruby-core:72482] [Bug #11873]'
1041    def bug11873.p(*);end;
1042
1043    assert_raise(LocalJumpError, bug11873) do
1044      bug11873.instance_eval do
1045        p p{p p;p(p)}, tap do
1046          raise SyntaxError, "should not be passed to tap"
1047        end
1048      end
1049    end
1050
1051    assert_raise(LocalJumpError, bug11873) do
1052      bug11873.instance_eval do
1053        p p{p(p);p p}, tap do
1054          raise SyntaxError, "should not be passed to tap"
1055        end
1056      end
1057    end
1058  end
1059
1060  def test_do_block_in_hash_brace
1061    bug13073 = '[ruby-core:78837] [Bug #13073]'
1062    assert_valid_syntax 'p :foo, {a: proc do end, b: proc do end}', bug13073
1063    assert_valid_syntax 'p :foo, {:a => proc do end, b: proc do end}', bug13073
1064    assert_valid_syntax 'p :foo, {"a": proc do end, b: proc do end}', bug13073
1065    assert_valid_syntax 'p :foo, {** proc do end, b: proc do end}', bug13073
1066    assert_valid_syntax 'p :foo, {proc do end => proc do end, b: proc do end}', bug13073
1067  end
1068
1069  def test_do_after_local_variable
1070    obj = Object.new
1071    def obj.m; yield; end
1072    result = assert_nothing_raised(SyntaxError) do
1073      obj.instance_eval("m = 1; m do :ok end")
1074    end
1075    assert_equal(:ok, result)
1076  end
1077
1078  def test_brace_after_local_variable
1079    obj = Object.new
1080    def obj.m; yield; end
1081    result = assert_nothing_raised(SyntaxError) do
1082      obj.instance_eval("m = 1; m {:ok}")
1083    end
1084    assert_equal(:ok, result)
1085  end
1086
1087  def test_brace_after_literal_argument
1088    bug = '[ruby-core:81037] [Bug #13547]'
1089    error = /unexpected '{'/
1090    assert_syntax_error('m "x" {}', error)
1091    assert_syntax_error('m 1 {}', error, bug)
1092    assert_syntax_error('m 1.0 {}', error, bug)
1093    assert_syntax_error('m :m {}', error, bug)
1094    assert_syntax_error('m :"#{m}" {}', error, bug)
1095    assert_syntax_error('m ?x {}', error, bug)
1096    assert_syntax_error('m %[] {}', error, bug)
1097    assert_syntax_error('m 0..1 {}', error, bug)
1098    assert_syntax_error('m [] {}', error, bug)
1099  end
1100
1101  def test_return_toplevel
1102    feature4840 = '[ruby-core:36785] [Feature #4840]'
1103    line = __LINE__+2
1104    code = "#{<<~"begin;"}#{<<~'end;'}"
1105    begin;
1106      return; raise
1107      begin return; rescue SystemExit; exit false; end
1108      begin return; ensure puts "ensured"; end #=> ensured
1109      begin ensure return; end
1110      begin raise; ensure; return; end
1111      begin raise; rescue; return; end
1112      return false; raise
1113      return 1; raise
1114      "#{return}"
1115      raise((return; "should not raise"))
1116      begin raise; ensure return; end; self
1117      begin raise; ensure return; end and self
1118      nil&defined?0--begin e=no_method_error(); return; 0;end
1119      return puts('ignored') #=> ignored
1120    end;
1121      .split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
1122    failed = proc do |n, s|
1123      RubyVM::InstructionSequence.compile(s, __FILE__, nil, n).disasm
1124    end
1125    Tempfile.create(%w"test_return_ .rb") do |lib|
1126      lib.close
1127      args = %W[-W0 -r#{lib.path}]
1128      all_assertions_foreach(feature4840, *[:main, :lib].product([:class, :top], code)) do |main, klass, (n, s, *ex)|
1129        if klass == :class
1130          s = "class X; #{s}; end"
1131          if main == :main
1132            assert_in_out_err(%[-W0], s, [], /return/, proc {failed[n, s]}, success: false)
1133          else
1134            File.write(lib, s)
1135            assert_in_out_err(args, "", [], /return/, proc {failed[n, s]}, success: false)
1136          end
1137        else
1138          if main == :main
1139            assert_in_out_err(%[-W0], s, ex, [], proc {failed[n, s]}, success: true)
1140          else
1141            File.write(lib, s)
1142            assert_in_out_err(args, "", ex, [], proc {failed[n, s]}, success: true)
1143          end
1144        end
1145      end
1146    end
1147  end
1148
1149  def test_syntax_error_in_rescue
1150    bug12613 = '[ruby-core:76531] [Bug #12613]'
1151    assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
1152    begin;
1153      while true
1154        begin
1155          p
1156        rescue
1157          retry
1158        else
1159          retry
1160        end
1161        break
1162      end
1163    end;
1164  end
1165
1166  def test_invalid_jump
1167    assert_in_out_err(%w[-e redo], "", [], /^-e:1: /)
1168  end
1169
1170  def test_keyword_not_parens
1171    assert_valid_syntax("not()")
1172  end
1173
1174  def test_rescue_do_end_raised
1175    result = []
1176    assert_raise(RuntimeError) do
1177      eval("#{<<-"begin;"}\n#{<<-"end;"}")
1178      begin;
1179        tap do
1180          result << :begin
1181          raise "An exception occurred!"
1182        ensure
1183          result << :ensure
1184        end
1185      end;
1186    end
1187    assert_equal([:begin, :ensure], result)
1188  end
1189
1190  def test_rescue_do_end_rescued
1191    result = []
1192    assert_nothing_raised(RuntimeError) do
1193      eval("#{<<-"begin;"}\n#{<<-"end;"}")
1194      begin;
1195        tap do
1196          result << :begin
1197          raise "An exception occurred!"
1198        rescue
1199          result << :rescue
1200        else
1201          result << :else
1202        ensure
1203          result << :ensure
1204        end
1205      end;
1206    end
1207    assert_equal([:begin, :rescue, :ensure], result)
1208  end
1209
1210  def test_rescue_do_end_no_raise
1211    result = []
1212    assert_nothing_raised(RuntimeError) do
1213      eval("#{<<-"begin;"}\n#{<<-"end;"}")
1214      begin;
1215        tap do
1216          result << :begin
1217        rescue
1218          result << :rescue
1219        else
1220          result << :else
1221        ensure
1222          result << :ensure
1223        end
1224      end;
1225    end
1226    assert_equal([:begin, :else, :ensure], result)
1227  end
1228
1229  def test_rescue_do_end_ensure_result
1230    result = eval("#{<<-"begin;"}\n#{<<-"end;"}")
1231    begin;
1232      proc do
1233        :begin
1234      ensure
1235        :ensure
1236      end.call
1237    end;
1238    assert_equal(:begin, result)
1239  end
1240
1241  def test_rescue_do_end_ensure_in_lambda
1242    result = []
1243    eval("#{<<-"begin;"}\n#{<<-"end;"}")
1244    begin;
1245      -> do
1246        result << :begin
1247        raise "An exception occurred!"
1248      rescue
1249        result << :rescue
1250      else
1251        result << :else
1252      ensure
1253        result << :ensure
1254      end.call
1255    end;
1256    assert_equal([:begin, :rescue, :ensure], result)
1257  end
1258
1259  def test_return_in_loop
1260    obj = Object.new
1261    def obj.test
1262      x = nil
1263      return until x unless x
1264    end
1265    assert_nil obj.test
1266  end
1267
1268  def test_assignment_return_in_loop
1269    obj = Object.new
1270    def obj.test
1271      x = nil
1272      _y = (return until x unless x)
1273    end
1274    assert_nil obj.test, "[Bug #16695]"
1275  end
1276
1277  def test_method_call_location
1278    line = __LINE__+5
1279    e = assert_raise(NoMethodError) do
1280      1.upto(0) do
1281      end
1282        .
1283        foo(
1284          1,
1285          2,
1286        )
1287    end
1288    assert_equal(line, e.backtrace_locations[0].lineno)
1289
1290    line = __LINE__+5
1291    e = assert_raise(NoMethodError) do
1292      1.upto 0 do
1293      end
1294        .
1295        foo(
1296          1,
1297          2,
1298        )
1299    end
1300    assert_equal(line, e.backtrace_locations[0].lineno)
1301  end
1302
1303  def test_methoddef_in_cond
1304    assert_valid_syntax('while def foo; tap do end; end; break; end')
1305    assert_valid_syntax('while def foo a = tap do end; end; break; end')
1306  end
1307
1308  def test_classdef_in_cond
1309    assert_valid_syntax('while class Foo; tap do end; end; break; end')
1310    assert_valid_syntax('while class Foo a = tap do end; end; break; end')
1311  end
1312
1313  def test_command_with_cmd_brace_block
1314    assert_valid_syntax('obj.foo (1) {}')
1315    assert_valid_syntax('obj::foo (1) {}')
1316  end
1317
1318  def test_value_expr_in_condition
1319    mesg = /void value expression/
1320    assert_syntax_error("tap {a = (true ? next : break)}", mesg)
1321    assert_valid_syntax("tap {a = (true ? true : break)}")
1322  end
1323
1324  private
1325
1326  def not_label(x) @result = x; @not_label ||= nil end
1327  def assert_not_label(expected, src, message = nil)
1328    @result = nil
1329    assert_nothing_raised(SyntaxError, message) {eval(src)}
1330    assert_equal(expected, @result, message)
1331  end
1332
1333  def make_tmpsrc(f, src)
1334    f.open
1335    f.truncate(0)
1336    f.puts(src)
1337    f.close
1338  end
1339
1340  def with_script_lines
1341    script_lines = nil
1342    debug_lines = {}
1343    Object.class_eval do
1344      if defined?(SCRIPT_LINES__)
1345        script_lines = SCRIPT_LINES__
1346        remove_const :SCRIPT_LINES__
1347      end
1348      const_set(:SCRIPT_LINES__, debug_lines)
1349    end
1350    yield debug_lines
1351  ensure
1352    Object.class_eval do
1353      remove_const :SCRIPT_LINES__
1354      const_set(:SCRIPT_LINES__, script_lines) if script_lines
1355    end
1356  end
1357
1358  def caller_lineno(*)
1359    caller_locations(1, 1)[0].lineno
1360  end
1361end
1362