parser 0.9.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1772 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ # ENV['VERBOSE'] = "1"
5
+
6
+ require 'minitest/autorun'
7
+ require 'ruby_parser'
8
+
9
+ $: << File.expand_path('~/Work/p4/zss/src/sexp_processor/dev/lib')
10
+
11
+ require 'pt_testcase'
12
+
13
+ class Sexp
14
+ alias oldeq2 ==
15
+ def ==(obj) # :nodoc:
16
+ if obj.class == self.class then
17
+ super and
18
+ (self.line.nil? or obj.line.nil? or self.line == obj.line)
19
+ else
20
+ false
21
+ end
22
+ end
23
+ end
24
+
25
+ class RubyParserTestCase < ParseTreeTestCase
26
+ attr_accessor :result, :processor
27
+
28
+ make_my_diffs_pretty!
29
+
30
+ def self.previous key
31
+ "Ruby"
32
+ end
33
+
34
+ def self.generate_test klass, node, data, input_name, output_name
35
+ return if node.to_s =~ /bmethod|dmethod/
36
+ return if Array === data['Ruby']
37
+
38
+ output_name = "ParseTree"
39
+
40
+ super
41
+ end
42
+
43
+ def assert_parse rb, pt
44
+ self.result = processor.parse rb
45
+ assert_equal pt, result
46
+ end
47
+
48
+ def assert_syntax_error rb, emsg
49
+ e = nil
50
+ assert_silent do
51
+ e = assert_raises RubyParser::SyntaxError do
52
+ processor.parse rb
53
+ end
54
+ end
55
+
56
+ assert_equal emsg, e.message
57
+ end
58
+
59
+ def assert_parse_error rb, emsg
60
+ e = nil
61
+ assert_silent do
62
+ e = assert_raises Racc::ParseError do
63
+ processor.parse rb
64
+ end
65
+ end
66
+
67
+ assert_equal emsg, e.message
68
+ end
69
+
70
+ def assert_parse_line rb, pt, line
71
+ assert_parse rb, pt
72
+ assert_equal line, result.line, "call should have line number"
73
+ end
74
+ end
75
+
76
+ module TestRubyParserShared
77
+ def setup
78
+ super
79
+ # p :test => [self.class, __name__]
80
+ end
81
+
82
+ BLOCK_DUP_MSG = "Both block arg and actual block given."
83
+
84
+ def test_double_block_error_01
85
+ assert_syntax_error "a(1, &b) { }", BLOCK_DUP_MSG
86
+ end
87
+
88
+ def test_double_block_error_02
89
+ assert_syntax_error "a(1, &b) do end", BLOCK_DUP_MSG
90
+ end
91
+
92
+ def test_double_block_error_03
93
+ assert_syntax_error "a 1, &b do end", BLOCK_DUP_MSG
94
+ end
95
+
96
+ def test_double_block_error_04
97
+ assert_syntax_error "m.a(1, &b) { }", BLOCK_DUP_MSG
98
+ end
99
+
100
+ def test_double_block_error_05
101
+ assert_syntax_error "m.a(1, &b) do end", BLOCK_DUP_MSG
102
+ end
103
+
104
+ def test_double_block_error_06
105
+ assert_syntax_error "m.a 1, &b do end", BLOCK_DUP_MSG
106
+ end
107
+
108
+ def test_double_block_error_07
109
+ assert_syntax_error "m::a(1, &b) { }", BLOCK_DUP_MSG
110
+ end
111
+
112
+ def test_double_block_error_08
113
+ assert_syntax_error "m::a(1, &b) do end", BLOCK_DUP_MSG
114
+ end
115
+
116
+ def test_double_block_error_09
117
+ assert_syntax_error "m::a 1, &b do end", BLOCK_DUP_MSG
118
+ end
119
+
120
+ def test_wtf_7
121
+ rb = "a.b (1) {c}"
122
+ pt = s(:iter,
123
+ s(:call, s(:call, nil, :a), :b, s(:lit, 1)),
124
+ s(:args),
125
+ s(:call, nil, :c))
126
+
127
+ assert_parse rb, pt
128
+ end
129
+
130
+ def test_wtf_8
131
+ rb = "a::b (1) {c}"
132
+ pt = s(:iter,
133
+ s(:call, s(:call, nil, :a), :b, s(:lit, 1)),
134
+ s(:args),
135
+ s(:call, nil, :c))
136
+
137
+ assert_parse rb, pt
138
+ end
139
+
140
+ def test_attrasgn_array_lhs
141
+ rb = '[1, 2, 3, 4][from .. to] = ["a", "b", "c"]'
142
+ pt = s(:attrasgn,
143
+ s(:array, s(:lit, 1), s(:lit, 2), s(:lit, 3), s(:lit, 4)),
144
+ :[]=,
145
+ s(:dot2,
146
+ s(:call, nil, :from),
147
+ s(:call, nil, :to)),
148
+ s(:array, s(:str, "a"), s(:str, "b"), s(:str, "c")))
149
+
150
+ assert_parse rb, pt
151
+ end
152
+
153
+ def test_block_append
154
+ head = s(:args)
155
+ tail = s(:zsuper)
156
+ expected = s(:block, s(:args), s(:zsuper))
157
+ assert_equal expected, processor.block_append(head, tail)
158
+ end
159
+
160
+ def test_block_append_begin_begin
161
+ head = s(:begin, s(:args))
162
+ tail = s(:begin, s(:args))
163
+ expected = s(:block, s(:args), s(:begin, s(:args)))
164
+ assert_equal expected, processor.block_append(head, tail)
165
+ end
166
+
167
+ def test_block_append_block
168
+ head = s(:block, s(:args))
169
+ tail = s(:zsuper)
170
+ expected = s(:block, s(:args), s(:zsuper))
171
+ assert_equal expected, processor.block_append(head, tail)
172
+ end
173
+
174
+ def test_block_append_nil_head
175
+ head = nil
176
+ tail = s(:zsuper)
177
+ expected = s(:zsuper)
178
+ assert_equal expected, processor.block_append(head, tail)
179
+ end
180
+
181
+ def test_block_append_nil_tail
182
+ head = s(:args)
183
+ tail = nil
184
+ expected = s(:args)
185
+ assert_equal expected, processor.block_append(head, tail)
186
+ end
187
+
188
+ def test_block_append_tail_block
189
+ head = s(:call, nil, :f1)
190
+ tail = s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y)))
191
+ expected = s(:block,
192
+ s(:call, nil, :f1),
193
+ s(:block, s(:undef, s(:lit, :x)), s(:undef, s(:lit, :y))))
194
+ assert_equal expected, processor.block_append(head, tail)
195
+ end
196
+
197
+ def test_call_array_arg
198
+ rb = "1 == [:b, :c]"
199
+ pt = s(:call, s(:lit, 1), :==, s(:array, s(:lit, :b), s(:lit, :c)))
200
+
201
+ assert_parse rb, pt
202
+ end
203
+
204
+ def test_call_env
205
+ processor.env[:a] = :lvar
206
+ rb = "a.happy"
207
+ pt = s(:call, s(:lvar, :a), :happy)
208
+
209
+ assert_parse rb, pt
210
+ end
211
+
212
+ def test_dasgn_icky2
213
+ rb = "a do\n v = nil\n begin\n yield\n rescue Exception => v\n break\n end\nend"
214
+ pt = s(:iter,
215
+ s(:call, nil, :a),
216
+ s(:args),
217
+ s(:block,
218
+ s(:lasgn, :v, s(:nil)),
219
+ s(:rescue,
220
+ s(:yield),
221
+ s(:resbody,
222
+ s(:array, s(:const, :Exception), s(:lasgn, :v, s(:gvar, :$!))),
223
+ s(:break)))))
224
+
225
+ assert_parse rb, pt
226
+ end
227
+
228
+ def test_class_comments
229
+ rb = "# blah 1\n# blah 2\n\nclass X\n # blah 3\n def blah\n # blah 4\n end\nend"
230
+ pt = s(:class, :X, nil,
231
+ s(:defn, :blah, s(:args), s(:nil)))
232
+
233
+ assert_parse rb, pt
234
+
235
+ assert_equal "# blah 1\n# blah 2\n", result.comments
236
+ assert_equal "# blah 3\n", result.defn.comments
237
+ end
238
+
239
+ def test_module_comments
240
+ rb = "# blah 1\n \n # blah 2\n\nmodule X\n # blah 3\n def blah\n # blah 4\n end\nend"
241
+ pt = s(:module, :X,
242
+ s(:defn, :blah, s(:args), s(:nil)))
243
+
244
+ assert_parse rb, pt
245
+ assert_equal "# blah 1\n# blah 2\n", result.comments
246
+ assert_equal "# blah 3\n", result.defn.comments
247
+ end
248
+
249
+ def test_defn_comments
250
+ rb = "# blah 1\n# blah 2\n\ndef blah\nend"
251
+ pt = s(:defn, :blah, s(:args), s(:nil))
252
+
253
+ assert_parse rb, pt
254
+ assert_equal "# blah 1\n# blah 2\n", result.comments
255
+ end
256
+
257
+ def test_defs_comments
258
+ rb = "# blah 1\n# blah 2\n\ndef self.blah\nend"
259
+ pt = s(:defs, s(:self), :blah, s(:args))
260
+
261
+ assert_parse rb, pt
262
+ assert_equal "# blah 1\n# blah 2\n", result.comments
263
+ end
264
+
265
+ def test_do_bug # TODO: rename
266
+ rb = "a 1\na.b do |c|\n # do nothing\nend"
267
+ pt = s(:block,
268
+ s(:call, nil, :a, s(:lit, 1)),
269
+ s(:iter,
270
+ s(:call, s(:call, nil, :a), :b),
271
+ s(:args, :c)))
272
+
273
+ assert_parse rb, pt
274
+ end
275
+
276
+ def test_bug_comment_eq_begin
277
+ rb = "\n\n#\n=begin\nblah\n=end\n\n"
278
+ pt = nil
279
+ exp = rb.strip + "\n"
280
+
281
+ assert_parse rb, pt
282
+ assert_equal exp, processor.lexer.comments
283
+ end
284
+
285
+ def test_bug_call_arglist_parens
286
+ rb = 'g ( 1), 2'
287
+ pt = s(:call, nil, :g, s(:lit, 1), s(:lit, 2))
288
+
289
+ assert_parse rb, pt
290
+
291
+ rb = <<-CODE
292
+ def f
293
+ g ( 1), 2
294
+ end
295
+ CODE
296
+
297
+ pt = s(:defn, :f, s(:args),
298
+ s(:call, nil, :g, s(:lit, 1), s(:lit, 2)))
299
+
300
+ assert_parse rb, pt
301
+
302
+ rb = <<-CODE
303
+ def f()
304
+ g (1), 2
305
+ end
306
+ CODE
307
+
308
+ assert_parse rb, pt
309
+ end
310
+
311
+ def test_dstr_evstr
312
+ rb = "\"#\{'a'}#\{b}\""
313
+ pt = s(:dstr, "a", s(:evstr, s(:call, nil, :b)))
314
+
315
+ assert_parse rb, pt
316
+ end
317
+
318
+ def test_dstr_str
319
+ rb = "\"#\{'a'} b\""
320
+ pt = s(:str, "a b")
321
+
322
+ assert_parse rb, pt
323
+ end
324
+
325
+ def test_empty
326
+ rb = ""
327
+ pt = nil
328
+
329
+ assert_parse rb, pt
330
+ end
331
+
332
+ def test_evstr_evstr
333
+ rb = "\"#\{a}#\{b}\""
334
+ pt = s(:dstr, "", s(:evstr, s(:call, nil, :a)), s(:evstr, s(:call, nil, :b)))
335
+
336
+ assert_parse rb, pt
337
+ end
338
+
339
+ def test_evstr_str
340
+ rb = "\"#\{a} b\""
341
+ pt = s(:dstr, "", s(:evstr, s(:call, nil, :a)), s(:str, " b"))
342
+
343
+ assert_parse rb, pt
344
+ end
345
+
346
+ def test_lasgn_env
347
+ rb = 'a = 42'
348
+ pt = s(:lasgn, :a, s(:lit, 42))
349
+ expected_env = { :a => :lvar }
350
+
351
+ assert_parse rb, pt
352
+ assert_equal expected_env, processor.env.all
353
+ end
354
+
355
+ def test_list_append
356
+ a = s(:lit, 1)
357
+ b = s(:lit, 2)
358
+ c = s(:lit, 3)
359
+
360
+ result = processor.list_append(s(:array, b.dup), c.dup)
361
+
362
+ assert_equal s(:array, b, c), result
363
+
364
+ result = processor.list_append(b.dup, c.dup)
365
+
366
+ assert_equal s(:array, b, c), result
367
+
368
+ result = processor.list_append(result, a.dup)
369
+
370
+ assert_equal s(:array, b, c, a), result
371
+
372
+ lhs, rhs = s(:array, s(:lit, :iter)), s(:when, s(:const, :BRANCHING), nil)
373
+ expected = s(:array, s(:lit, :iter), s(:when, s(:const, :BRANCHING), nil))
374
+
375
+ assert_equal expected, processor.list_append(lhs, rhs)
376
+ end
377
+
378
+ def test_list_prepend
379
+ a = s(:lit, 1)
380
+ b = s(:lit, 2)
381
+ c = s(:lit, 3)
382
+
383
+ result = processor.list_prepend(b.dup, s(:array, c.dup))
384
+
385
+ assert_equal s(:array, b, c), result
386
+
387
+ result = processor.list_prepend(b.dup, c.dup)
388
+
389
+ assert_equal s(:array, b, c), result
390
+
391
+ result = processor.list_prepend(a.dup, result)
392
+
393
+ assert_equal s(:array, a, b, c), result
394
+ end
395
+
396
+ def test_literal_concat_dstr_dstr
397
+ lhs = s(:dstr, "Failed to download spec ",
398
+ s(:evstr, s(:call, nil, :spec_name)),
399
+ s(:str, " from "),
400
+ s(:evstr, s(:call, nil, :source_uri)),
401
+ s(:str, ":\n"))
402
+ rhs = s(:dstr, "\t",
403
+ s(:evstr, s(:call, s(:ivar, :@fetch_error), :message)))
404
+ expected = s(:dstr, "Failed to download spec ",
405
+ s(:evstr, s(:call, nil, :spec_name)),
406
+ s(:str, " from "),
407
+ s(:evstr, s(:call, nil, :source_uri)),
408
+ s(:str, ":\n"),
409
+ s(:str, "\t"),
410
+ s(:evstr, s(:call, s(:ivar, :@fetch_error), :message)))
411
+
412
+ assert_equal expected, processor.literal_concat(lhs, rhs)
413
+ end
414
+
415
+ def test_literal_concat_dstr_evstr
416
+ lhs, rhs = s(:dstr, "a"), s(:evstr, s(:call, nil, :b))
417
+ expected = s(:dstr, "a", s(:evstr, s(:call, nil, :b)))
418
+
419
+ assert_equal expected, processor.literal_concat(lhs, rhs)
420
+ end
421
+
422
+ def test_literal_concat_evstr_evstr
423
+ lhs, rhs = s(:evstr, s(:lit, 1)), s(:evstr, s(:lit, 2))
424
+ expected = s(:dstr, "", s(:evstr, s(:lit, 1)), s(:evstr, s(:lit, 2)))
425
+
426
+ assert_equal expected, processor.literal_concat(lhs, rhs)
427
+ end
428
+
429
+ def test_literal_concat_str_evstr
430
+ lhs, rhs = s(:str, ""), s(:evstr, s(:str, "blah"))
431
+
432
+ assert_equal s(:str, "blah"), processor.literal_concat(lhs, rhs)
433
+ end
434
+
435
+ def test_logop_12
436
+ lhs = s(:lit, 1)
437
+ rhs = s(:lit, 2)
438
+ exp = s(:and, s(:lit, 1), s(:lit, 2))
439
+
440
+ assert_equal exp, processor.logop(:and, lhs, rhs)
441
+ end
442
+
443
+ def test_logop_1234_5
444
+ lhs = s(:and, s(:lit, 1), s(:and, s(:lit, 2), s(:and, s(:lit, 3), s(:lit, 4))))
445
+ rhs = s(:lit, 5)
446
+ exp = s(:and,
447
+ s(:lit, 1),
448
+ s(:and,
449
+ s(:lit, 2),
450
+ s(:and,
451
+ s(:lit, 3),
452
+ s(:and,
453
+ s(:lit, 4),
454
+ s(:lit, 5)))))
455
+
456
+ assert_equal exp, processor.logop(:and, lhs, rhs)
457
+ end
458
+
459
+ def test_logop_123_4
460
+ lhs = s(:and, s(:lit, 1), s(:and, s(:lit, 2), s(:lit, 3)))
461
+ rhs = s(:lit, 4)
462
+ exp = s(:and,
463
+ s(:lit, 1),
464
+ s(:and,
465
+ s(:lit, 2),
466
+ s(:and,
467
+ s(:lit, 3),
468
+ s(:lit, 4))))
469
+
470
+ assert_equal exp, processor.logop(:and, lhs, rhs)
471
+ end
472
+
473
+ def test_logop_12_3
474
+ lhs = s(:and, s(:lit, 1), s(:lit, 2))
475
+ rhs = s(:lit, 3)
476
+ exp = s(:and, s(:lit, 1), s(:and, s(:lit, 2), s(:lit, 3)))
477
+
478
+ assert_equal exp, processor.logop(:and, lhs, rhs)
479
+ end
480
+
481
+ def test_logop_nested_mix
482
+ lhs = s(:or, s(:call, nil, :a), s(:call, nil, :b))
483
+ rhs = s(:and, s(:call, nil, :c), s(:call, nil, :d))
484
+ exp = s(:or,
485
+ s(:or, s(:call, nil, :a), s(:call, nil, :b)),
486
+ s(:and, s(:call, nil, :c), s(:call, nil, :d)))
487
+
488
+ lhs.paren = true
489
+ rhs.paren = true
490
+
491
+ assert_equal exp, processor.logop(:or, lhs, rhs)
492
+ end
493
+
494
+ def test_str_evstr
495
+ rb = "\"a #\{b}\""
496
+ pt = s(:dstr, "a ", s(:evstr, s(:call, nil, :b)))
497
+
498
+ assert_parse rb, pt
499
+ end
500
+
501
+ def test_dsym_to_sym
502
+ pt = s(:alias, s(:lit, :<<), s(:lit, :>>))
503
+
504
+ rb = 'alias :<< :>>'
505
+ assert_parse rb, pt
506
+
507
+ rb = 'alias :"<<" :">>"'
508
+ assert_parse rb, pt
509
+ end
510
+
511
+ def test_regexp
512
+ regexps = {
513
+ "/wtf/" => /wtf/,
514
+ "/wtf/n" => /wtf/n,
515
+ "/wtf/m" => /wtf/m,
516
+ "/wtf/nm" => /wtf/nm,
517
+ "/wtf/nmnmnmnm" => /wtf/nm,
518
+ }
519
+
520
+ regexps.each do |rb, lit|
521
+ assert_parse rb, s(:lit, lit)
522
+ end
523
+
524
+ # TODO: add more including interpolation etc
525
+ end
526
+
527
+ def test_str_pct_Q_nested
528
+ rb = "%Q[before [#\{nest}] after]"
529
+ pt = s(:dstr, "before [", s(:evstr, s(:call, nil, :nest)), s(:str, "] after"))
530
+
531
+ assert_parse rb, pt
532
+ end
533
+
534
+ def test_str_pct_nested_nested
535
+ rb = "%{ { #\{ \"#\{1}\" } } }"
536
+ assert_equal " { 1 } ", eval(rb)
537
+ pt = s(:dstr, " { ", s(:evstr, s(:lit, 1)), s(:str, " } "))
538
+
539
+ assert_parse rb, pt
540
+ end
541
+
542
+ def test_str_str
543
+ rb = "\"a #\{'b'}\""
544
+ pt = s(:str, "a b")
545
+
546
+ assert_parse rb, pt
547
+ end
548
+
549
+ def test_str_str_str
550
+ rb = "\"a #\{'b'} c\""
551
+ pt = s(:str, "a b c")
552
+
553
+ assert_parse rb, pt
554
+ end
555
+
556
+ STARTING_LINE = {
557
+ "case_no_expr" => 2, # TODO this should be 1
558
+ "structure_unused_literal_wwtt" => 3, # yes, 3... odd test
559
+ }
560
+
561
+ def after_process_hook klass, node, data, input_name, output_name
562
+ expected = STARTING_LINE[node] || 1
563
+ assert_equal expected, @result.line, "should have proper line number"
564
+ end
565
+
566
+ def test_parse_line_block
567
+ rb = "a = 42\np a"
568
+ pt = s(:block,
569
+ s(:lasgn, :a, s(:lit, 42)),
570
+ s(:call, nil, :p, s(:lvar, :a)))
571
+
572
+ assert_parse_line rb, pt, 1
573
+ assert_equal 1, result.lasgn.line, "lasgn should have line number"
574
+ assert_equal 2, result.call.line, "call should have line number"
575
+
576
+ expected = "(string)"
577
+ assert_equal expected, result.file
578
+ assert_equal expected, result.lasgn.file
579
+ assert_equal expected, result.call.file
580
+
581
+ assert_same result.file, result.lasgn.file
582
+ assert_same result.file, result.call.file
583
+ end
584
+
585
+ def test_parse_line_call_no_args
586
+ rb = "f do |x, y|\n x + y\nend"
587
+
588
+ pt = s(:iter,
589
+ s(:call, nil, :f),
590
+ s(:args, :x, :y),
591
+ s(:call, s(:lvar, :x), :+, s(:lvar, :y)))
592
+
593
+ assert_parse_line rb, pt, 1
594
+ assert_equal 1, result[1].line, "call should have line number"
595
+ assert_equal 1, result[2].line, "masgn should have line number"
596
+ assert_equal 2, result[3].line, "call should have line number"
597
+ end
598
+
599
+ def test_parse_line_defn_no_parens
600
+ pt = s(:defn, :f, s(:args), s(:nil))
601
+
602
+ rb = "def f\nend"
603
+ assert_parse_line rb, pt, 1
604
+
605
+ rb = "def f\n\nend"
606
+ assert_parse_line rb, pt, 1
607
+ end
608
+
609
+ def test_parse_line_defn_complex
610
+ rb = "def x(y)\n p(y)\n y *= 2\n return y;\nend" # TODO: remove () & ;
611
+ pt = s(:defn, :x, s(:args, :y),
612
+ s(:call, nil, :p, s(:lvar, :y)),
613
+ s(:lasgn, :y, s(:call, s(:lvar, :y), :*, s(:lit, 2))),
614
+ s(:return, s(:lvar, :y)))
615
+
616
+ assert_parse_line rb, pt, 1
617
+
618
+ body = result
619
+ assert_equal 2, body.call.line, "call should have line number"
620
+ assert_equal 3, body.lasgn.line, "lasgn should have line number"
621
+ assert_equal 4, body.return.line, "return should have line number"
622
+ end
623
+
624
+ def test_parse_line_iter_call_parens
625
+ rb = "f(a) do |x, y|\n x + y\nend"
626
+
627
+ pt = s(:iter,
628
+ s(:call, nil, :f, s(:call, nil, :a)),
629
+ s(:args, :x, :y),
630
+ s(:call, s(:lvar, :x), :+, s(:lvar, :y)))
631
+
632
+ assert_parse_line rb, pt, 1
633
+
634
+ assert_equal 1, result[1].line, "call should have line number"
635
+ assert_equal 1, result[2].line, "masgn should have line number"
636
+ assert_equal 2, result[3].line, "call should have line number"
637
+ end
638
+
639
+ def test_parse_line_iter_call_no_parens
640
+ rb = "f a do |x, y|\n x + y\nend"
641
+
642
+ pt = s(:iter,
643
+ s(:call, nil, :f, s(:call, nil, :a)),
644
+ s(:args, :x, :y),
645
+ s(:call, s(:lvar, :x), :+, s(:lvar, :y)))
646
+
647
+ assert_parse_line rb, pt, 1
648
+
649
+ assert_equal 1, result[1].line, "call should have line number"
650
+ assert_equal 1, result[2].line, "masgn should have line number"
651
+ assert_equal 2, result[3].line, "call should have line number"
652
+ end
653
+
654
+ def test_parse_line_heredoc
655
+ rb = <<-CODE
656
+ string = <<-HEREDOC
657
+ very long string
658
+ HEREDOC
659
+ puts string
660
+ CODE
661
+
662
+ pt = s(:block,
663
+ s(:lasgn, :string,
664
+ s(:str, " very long string\n").line(1)).line(1),
665
+ s(:call, nil, :puts, s(:lvar, :string).line(4)).line(4)).line(1)
666
+
667
+ assert_parse rb, pt
668
+ end
669
+
670
+ def test_parse_line_newlines
671
+ rb = "true\n\n"
672
+ pt = s(:true)
673
+
674
+ assert_parse_line rb, pt, 1
675
+ end
676
+
677
+ def test_parse_line_return
678
+ rb = <<-RUBY
679
+ def blah
680
+ if true then
681
+ return 42
682
+ end
683
+ end
684
+ RUBY
685
+
686
+ pt = s(:defn, :blah, s(:args),
687
+ s(:if, s(:true),
688
+ s(:return, s(:lit, 42)),
689
+ nil))
690
+
691
+ assert_parse_line rb, pt, 1
692
+
693
+ assert_equal 3, result.if.return.line
694
+ assert_equal 3, result.if.return.lit.line
695
+ end
696
+
697
+ def test_bug_and
698
+ rb = "true and []"
699
+ pt = s(:and, s(:true), s(:array))
700
+
701
+ assert_parse rb, pt
702
+
703
+ rb = "true and\ntrue"
704
+ pt = s(:and, s(:true), s(:true))
705
+
706
+ assert_parse rb, pt
707
+ end
708
+
709
+ def test_bug_cond_pct
710
+ rb = "case; when %r%blahblah%; end"
711
+ pt = s(:case, nil, s(:when, s(:array, s(:lit, /blahblah/)), nil), nil)
712
+
713
+ assert_parse rb, pt
714
+ end
715
+
716
+ # according to 2.3.1 parser -- added: ON 1.8 only:
717
+ # rp.process("f { |(a,b),c| }") == rp.process("f { |((a,b),c)| }")
718
+
719
+ # ruby18 -e "p lambda { |(a,b)| }.arity" # => 2
720
+ # ruby19 -e "p lambda { |(a,b)| }.arity" # => 1
721
+ # ruby18 -e "p lambda { |(a,b),c| }.arity" # => 2
722
+ # ruby19 -e "p lambda { |(a,b),c| }.arity" # => 2
723
+ # ruby18 -e "p lambda { |((a,b),c)| }.arity" # => 2
724
+ # ruby19 -e "p lambda { |((a,b),c)| }.arity" # => 1
725
+
726
+ def test_bug_args_masgn
727
+ rb = "f { |(a, b), c| }"
728
+ pt = s(:iter,
729
+ s(:call, nil, :f),
730
+ s(:args, s(:masgn, :a, :b), :c))
731
+
732
+ assert_parse rb, pt.dup
733
+ end
734
+
735
+ def test_bug_args_masgn2
736
+ rb = "f { |((a, b), c), d| }"
737
+ pt = s(:iter,
738
+ s(:call, nil, :f),
739
+ s(:args, s(:masgn, s(:masgn, :a, :b), :c), :d))
740
+
741
+ assert_parse rb, pt
742
+ end
743
+
744
+ def ruby18
745
+ Ruby18Parser === self.processor
746
+ end
747
+
748
+ def ruby19
749
+ Ruby19Parser === self.processor
750
+ end
751
+
752
+ def test_bug_comma
753
+ val = if ruby18 then
754
+ s(:lit, 100)
755
+ elsif ruby19 then
756
+ s(:str, "d")
757
+ else
758
+ raise "wtf"
759
+ end
760
+
761
+ rb = "if test ?d, dir then end"
762
+ pt = s(:if,
763
+ s(:call, nil, :test, val, s(:call, nil, :dir)),
764
+ nil,
765
+ nil)
766
+
767
+ assert_parse rb, pt
768
+ end
769
+
770
+ def test_bug_case_when_regexp
771
+ rb = "case :x; when /x/ then end"
772
+ pt = s(:case, s(:lit, :x),
773
+ s(:when, s(:array, s(:lit, /x/)), nil),
774
+ nil)
775
+
776
+ assert_parse rb, pt
777
+ end
778
+
779
+ def test_bug_masgn_right
780
+ rb = "f { |a, (b, c)| }"
781
+ pt = s(:iter,
782
+ s(:call, nil, :f),
783
+ s(:args, :a, s(:masgn, :b, :c)))
784
+
785
+ assert_parse rb, pt
786
+ end
787
+
788
+ def test_when_splat
789
+ rb = "case a; when *b then; end"
790
+ pt = s(:case, s(:call, nil, :a),
791
+ s(:when, s(:array, s(:splat, s(:call, nil, :b))), nil),
792
+ nil)
793
+
794
+ assert_parse rb, pt
795
+ end
796
+
797
+ def test_if_symbol
798
+ rb = "if f :x; end"
799
+ pt = s(:if, s(:call, nil, :f, s(:lit, :x)), nil, nil)
800
+
801
+ assert_parse rb, pt
802
+ end
803
+
804
+
805
+ def test_bug_not_parens
806
+ rb = "not(a)"
807
+ pt = if ruby18 then
808
+ s(:not, s(:call, nil, :a))
809
+ elsif ruby19 then
810
+ s(:call, s(:call, nil, :a), :"!")
811
+ else
812
+ raise "wtf"
813
+ end
814
+
815
+ assert_parse rb, pt
816
+ end
817
+
818
+ def test_pipe_space
819
+ rb = "a.b do | | end"
820
+ pt = s(:iter, s(:call, s(:call, nil, :a), :b), 0)
821
+
822
+ assert_parse rb, pt
823
+ end
824
+
825
+ def test_cond_unary_minus
826
+ rb = "if -1; end"
827
+ pt = s(:if, s(:lit, -1), nil, nil)
828
+
829
+ assert_parse rb, pt
830
+ end
831
+
832
+ def test_bug_op_asgn_rescue
833
+ rb = "a ||= b rescue nil"
834
+ pt = s(:rescue,
835
+ s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, s(:call, nil, :b))),
836
+ s(:resbody, s(:array), s(:nil)))
837
+
838
+ assert_parse rb, pt
839
+ end
840
+
841
+ def test_magic_encoding_comment
842
+ rb = "# encoding: utf-8\nclass ExampleUTF8ClassNameVarietà; def self.è; così = :però; end\nend\n"
843
+
844
+ rb.force_encoding "ASCII-8BIT" if rb.respond_to? :force_encoding
845
+
846
+ # TODO: class vars
847
+ # TODO: odd-ternary: a ?bb : c
848
+ # TODO: globals
849
+
850
+ pt = s(:class, :"ExampleUTF8ClassNameVariet\303\240", nil,
851
+ s(:defs, s(:self), :"\303\250", s(:args),
852
+ s(:lasgn, :"cos\303\254", s(:lit, :"per\303\262"))))
853
+
854
+ err = RUBY_VERSION =~ /^1\.8/ ? "Skipping magic encoding comment\n" : ""
855
+
856
+ assert_output "", err do
857
+ assert_parse rb, pt
858
+ end
859
+ end
860
+
861
+ def test_iter_args_1
862
+ rb = "f { |a,b| }"
863
+ pt = s(:iter, s(:call, nil, :f), s(:args, :a, :b))
864
+
865
+ assert_parse rb, pt
866
+ end
867
+
868
+ def test_iter_args_3
869
+ rb = "f { |a, (b, c), d| }"
870
+ pt = s(:iter, s(:call, nil, :f), s(:args, :a, s(:masgn, :b, :c), :d))
871
+
872
+ assert_parse rb, pt
873
+ end
874
+
875
+ def test_str_heredoc_interp
876
+ rb = "<<\"\"\n\#{x}\nblah2\n\n"
877
+ pt = s(:dstr, "", s(:evstr, s(:call, nil, :x)), s(:str, "\n"), s(:str, "blah2\n"))
878
+
879
+ assert_parse rb, pt
880
+ end
881
+
882
+ def test_i_fucking_hate_line_numbers
883
+ rb = <<-END.gsub(/^ {6}/, '')
884
+ if true
885
+ p 1
886
+ a.b 2
887
+ c.d 3, 4
888
+ e.f 5
889
+ g.h 6, 7
890
+ p(1)
891
+ a.b(2)
892
+ c.d(3, 4)
893
+ e.f(5)
894
+ g.h(6, 7)
895
+ end
896
+ END
897
+
898
+ pt = s(:if, s(:true).line(1),
899
+ s(:block,
900
+ s(:call, nil, :p, s(:lit, 1).line(2)).line(2),
901
+ s(:call, s(:call, nil, :a).line(3), :b,
902
+ s(:lit, 2).line(3)).line(3),
903
+ s(:call, s(:call, nil, :c).line(4), :d,
904
+ s(:lit, 3).line(4), s(:lit, 4).line(4)).line(4),
905
+ s(:call, s(:call, nil, :e).line(5), :f,
906
+ s(:lit, 5).line(5)).line(5),
907
+ s(:call, s(:call, nil, :g).line(6), :h,
908
+ s(:lit, 6).line(6), s(:lit, 7).line(6)).line(6),
909
+ s(:call, nil, :p, s(:lit, 1).line(7)).line(7),
910
+ s(:call, s(:call, nil, :a).line(8), :b,
911
+ s(:lit, 2).line(8)).line(8),
912
+ s(:call, s(:call, nil, :c).line(9), :d,
913
+ s(:lit, 3).line(9), s(:lit, 4).line(9)).line(9),
914
+ s(:call, s(:call, nil, :e).line(10), :f,
915
+ s(:lit, 5).line(10)).line(10),
916
+ s(:call, s(:call, nil, :g).line(11), :h,
917
+ s(:lit, 6).line(11), s(:lit, 7).line(11)).line(11)).line(2),
918
+ nil).line(1)
919
+
920
+ assert_parse rb, pt
921
+ end
922
+
923
+ def test_i_fucking_hate_line_numbers2
924
+ rb = <<-EOM.gsub(/^ {6}/, '')
925
+ if true then
926
+ p('a')
927
+ b = 1
928
+ p b
929
+ c =1
930
+ end
931
+ a
932
+ EOM
933
+
934
+ pt = s(:block,
935
+ s(:if, s(:true).line(1),
936
+ s(:block,
937
+ s(:call, nil, :p, s(:str, "a").line(2)).line(2),
938
+ s(:lasgn, :b, s(:lit, 1).line(3)).line(3),
939
+ s(:call, nil, :p, s(:lvar, :b).line(4)).line(4),
940
+ s(:lasgn, :c, s(:lit, 1).line(5)).line(5)).line(2), # TODO line 2?
941
+ nil).line(1),
942
+ s(:call, nil, :a).line(7)).line(1)
943
+
944
+ assert_parse rb, pt
945
+ end
946
+
947
+ def test_parse_comments
948
+ p = RubyParser.new
949
+ sexp = p.parse <<-CODE
950
+ # class comment
951
+ class Inline
952
+ def show
953
+ # woot
954
+ end
955
+
956
+ # Returns a list of things
957
+ def list
958
+ # woot
959
+ end
960
+ end
961
+ CODE
962
+
963
+ assert_equal "# class comment\n", sexp.comments
964
+ act = sexp.find_nodes(:defn).map(&:comments)
965
+ exp = ["", "# Returns a list of things\n"]
966
+
967
+ assert_equal exp, act
968
+ assert_equal [], processor.comments
969
+ assert_equal "", processor.lexer.comments
970
+ end
971
+ end
972
+
973
+ class TestRubyParser < MiniTest::Unit::TestCase
974
+ def test_parse
975
+ processor = RubyParser.new
976
+
977
+ # 1.8 only syntax
978
+ rb = "while false : 42 end"
979
+ pt = s(:while, s(:false), s(:lit, 42), true)
980
+
981
+ assert_silent do
982
+ assert_equal pt, processor.parse(rb)
983
+ end
984
+
985
+ # 1.9 only syntax
986
+ rb = "a.()"
987
+ pt = s(:call, s(:call, nil, :a), :call)
988
+
989
+ assert_equal pt, processor.parse(rb)
990
+
991
+ # bad syntax
992
+ e = assert_raises Racc::ParseError do
993
+ capture_io do
994
+ processor.parse "a.("
995
+ end
996
+ end
997
+
998
+ msg = "(string):1 :: parse error on value \"(\" (tLPAREN2)"
999
+ assert_equal msg, e.message.strip
1000
+ end
1001
+ end
1002
+
1003
+ class TestRuby18Parser < RubyParserTestCase
1004
+ include TestRubyParserShared
1005
+
1006
+ def setup
1007
+ super
1008
+
1009
+ self.processor = Ruby18Parser.new
1010
+ end
1011
+
1012
+ def test_flip2_env_lvar
1013
+ rb = "if a..b then end"
1014
+ pt = s(:if, s(:flip2, s(:call, nil, :a), s(:call, nil, :b)), nil, nil)
1015
+
1016
+ assert_parse rb, pt
1017
+
1018
+ top_env = processor.env.env.first
1019
+
1020
+ assert_kind_of Hash, top_env
1021
+
1022
+ flip = top_env.find { |k,v| k =~ /^flip/ }
1023
+
1024
+ assert flip
1025
+ assert_equal :lvar, flip.last
1026
+ end
1027
+
1028
+ def test_assoc_list_18
1029
+ rb = "{1, 2, 3, 4}"
1030
+ pt = s(:hash, s(:lit, 1), s(:lit, 2), s(:lit, 3), s(:lit, 4))
1031
+
1032
+ assert_parse rb, pt
1033
+ end
1034
+
1035
+ def test_case_then_colon_18
1036
+ rb = "case x; when Fixnum: 42; end"
1037
+ pt = s(:case,
1038
+ s(:call, nil, :x),
1039
+ s(:when, s(:array, s(:const, :Fixnum)), s(:lit, 42)),
1040
+ nil)
1041
+
1042
+ assert_parse rb, pt
1043
+ end
1044
+
1045
+ def test_do_colon_18
1046
+ rb = "while false : 42 end"
1047
+ pt = s(:while, s(:false), s(:lit, 42), true)
1048
+
1049
+ assert_parse rb, pt
1050
+ end
1051
+
1052
+ def test_parse_until_not_canonical
1053
+ rb = "until not var.nil?\n 'foo'\nend"
1054
+
1055
+ pt = s(:while,
1056
+ s(:call, s(:call, nil, :var), :nil?),
1057
+ s(:str, "foo"), true)
1058
+
1059
+ assert_parse rb, pt
1060
+ end
1061
+
1062
+ def test_parse_until_not_noncanonical
1063
+ rb = "until not var.nil?\n 'foo'\nend"
1064
+ pt = s(:until,
1065
+ s(:not, s(:call, s(:call, nil, :var), :nil?)),
1066
+ s(:str, "foo"), true)
1067
+
1068
+ processor.canonicalize_conditions = false
1069
+
1070
+ assert_parse rb, pt
1071
+ end
1072
+
1073
+ def test_parse_if_not_canonical
1074
+ rb = "if not var.nil? then 'foo' else 'bar'\nend"
1075
+ pt = s(:if,
1076
+ s(:call, s(:call, nil, :var), :nil?),
1077
+ s(:str, "bar"),
1078
+ s(:str, "foo"))
1079
+
1080
+ assert_parse rb, pt
1081
+ end
1082
+
1083
+ def test_parse_if_not_noncanonical
1084
+ rb = "if not var.nil? then 'foo' else 'bar'\nend"
1085
+ pt = s(:if,
1086
+ s(:not, s(:call, s(:call, nil, :var), :nil?)),
1087
+ s(:str, "foo"),
1088
+ s(:str, "bar"))
1089
+
1090
+ processor.canonicalize_conditions = false
1091
+
1092
+ assert_parse rb, pt
1093
+ end
1094
+
1095
+ def test_parse_while_not_canonical
1096
+ rb = "while not var.nil?\n 'foo'\nend"
1097
+ pt = s(:until,
1098
+ s(:call, s(:call, nil, :var), :nil?),
1099
+ s(:str, "foo"), true)
1100
+
1101
+ assert_parse rb, pt
1102
+ end
1103
+
1104
+ def test_parse_while_not_noncanonical
1105
+ rb = "while not var.nil?\n 'foo'\nend"
1106
+ pt = s(:while,
1107
+ s(:not, s(:call, s(:call, nil, :var), :nil?)),
1108
+ s(:str, "foo"), true)
1109
+
1110
+ processor.canonicalize_conditions = false
1111
+
1112
+ assert_parse rb, pt
1113
+ end
1114
+
1115
+ def test_double_block_error_10
1116
+ assert_syntax_error "a.b (&b) {}", BLOCK_DUP_MSG
1117
+ end
1118
+
1119
+ def test_double_block_error_11
1120
+ assert_syntax_error "a (1, &b) { }", BLOCK_DUP_MSG
1121
+ end
1122
+
1123
+ def test_double_block_error_12
1124
+ assert_syntax_error "a (1, &b) do end", BLOCK_DUP_MSG
1125
+ end
1126
+
1127
+ def test_double_block_error_13
1128
+ assert_syntax_error "m.a (1, &b) { }", BLOCK_DUP_MSG
1129
+ end
1130
+
1131
+ def test_double_block_error_14
1132
+ assert_syntax_error "m.a (1, &b) do end", BLOCK_DUP_MSG
1133
+ end
1134
+
1135
+ def test_double_block_error_15
1136
+ assert_syntax_error "m::a (1, &b) { }", BLOCK_DUP_MSG
1137
+ end
1138
+
1139
+ def test_double_block_error_16
1140
+ assert_syntax_error "m::a (1, &b) do end", BLOCK_DUP_MSG
1141
+ end
1142
+
1143
+ # In 1.8, block args with an outer set of parens are superfluous.
1144
+ # In 1.9, outer set of parens are NOT... they are an explicit extra masgn.
1145
+
1146
+ def test_iter_args_2_18
1147
+ rb = "f { |(a, b)| }"
1148
+ pt = s(:iter, s(:call, nil, :f), s(:args, :a, :b))
1149
+
1150
+ assert_parse rb, pt
1151
+ end
1152
+
1153
+ def test_bug_args__18
1154
+ rb = "f { |(a, b)| }"
1155
+ pt = s(:iter, s(:call, nil, :f),
1156
+ s(:args, :a, :b))
1157
+
1158
+ assert_parse rb, pt
1159
+ end
1160
+
1161
+ def test_bug_args_masgn_outer_parens__18
1162
+ rb = "f { |((a, b), c)| }"
1163
+ pt = s(:iter, # NOTE: same sexp as test_bug_args_masgn
1164
+ s(:call, nil, :f),
1165
+ s(:args, s(:masgn, :a, :b), :c))
1166
+
1167
+ assert_parse rb, pt.dup
1168
+ end
1169
+ end
1170
+
1171
+ class TestRuby19Parser < RubyParserTestCase
1172
+ include TestRubyParserShared
1173
+
1174
+ def setup
1175
+ super
1176
+
1177
+ self.processor = Ruby19Parser.new
1178
+ end
1179
+
1180
+ def test_mlhs_back_splat
1181
+ rb = "a, b, c, *s = f"
1182
+ pt = s(:masgn,
1183
+ s(:array,
1184
+ s(:lasgn, :a), s(:lasgn, :b), s(:lasgn, :c),
1185
+ s(:splat, s(:lasgn, :s))),
1186
+ s(:to_ary, s(:call, nil, :f)))
1187
+
1188
+ assert_parse rb, pt
1189
+ end
1190
+
1191
+ def test_mlhs_back_anonsplat
1192
+ rb = "a, b, c, * = f"
1193
+ pt = s(:masgn,
1194
+ s(:array,
1195
+ s(:lasgn, :a), s(:lasgn, :b), s(:lasgn, :c),
1196
+ s(:splat)),
1197
+ s(:to_ary, s(:call, nil, :f)))
1198
+
1199
+ assert_parse rb, pt
1200
+ end
1201
+
1202
+ def test_mlhs_mid_splat
1203
+ rb = "a, b, c, *s, x, y, z = f"
1204
+ pt = s(:masgn,
1205
+ s(:array,
1206
+ s(:lasgn, :a), s(:lasgn, :b), s(:lasgn, :c),
1207
+ s(:splat, s(:lasgn, :s)),
1208
+ s(:lasgn, :x), s(:lasgn, :y), s(:lasgn, :z)),
1209
+ s(:to_ary, s(:call, nil, :f)))
1210
+
1211
+ assert_parse rb, pt
1212
+ end
1213
+
1214
+ def test_mlhs_mid_anonsplat
1215
+ rb = "a, b, c, *, x, y, z = f"
1216
+ pt = s(:masgn,
1217
+ s(:array, s(:lasgn, :a), s(:splat), s(:lasgn, :z)),
1218
+ s(:to_ary, s(:call, nil, :f)))
1219
+ pt = s(:masgn,
1220
+ s(:array,
1221
+ s(:lasgn, :a), s(:lasgn, :b), s(:lasgn, :c),
1222
+ s(:splat),
1223
+ s(:lasgn, :x), s(:lasgn, :y), s(:lasgn, :z)),
1224
+ s(:to_ary, s(:call, nil, :f)))
1225
+
1226
+ assert_parse rb, pt
1227
+ end
1228
+
1229
+ def test_mlhs_front_splat
1230
+ rb = "*s, x, y, z = f"
1231
+ pt = s(:masgn,
1232
+ s(:array, s(:splat, s(:lasgn, :s)), s(:lasgn, :z)),
1233
+ s(:to_ary, s(:call, nil, :f)))
1234
+ pt = s(:masgn,
1235
+ s(:array,
1236
+ s(:splat, s(:lasgn, :s)),
1237
+ s(:lasgn, :x), s(:lasgn, :y), s(:lasgn, :z)),
1238
+ s(:to_ary, s(:call, nil, :f)))
1239
+
1240
+ assert_parse rb, pt
1241
+ end
1242
+
1243
+ def test_mlhs_front_anonsplat
1244
+ rb = "*, x, y, z = f"
1245
+ pt = s(:masgn,
1246
+ s(:array,
1247
+ s(:splat),
1248
+ s(:lasgn, :x), s(:lasgn, :y), s(:lasgn, :z)),
1249
+ s(:to_ary, s(:call, nil, :f)))
1250
+
1251
+ assert_parse rb, pt
1252
+ end
1253
+
1254
+ def test_expr_not_bang
1255
+ rb = "! a b"
1256
+ pt = s(:call, s(:call, nil, :a, s(:call, nil, :b)), :"!")
1257
+
1258
+ assert_parse rb, pt
1259
+ end
1260
+
1261
+ def test_encoding
1262
+ rb = '__ENCODING__'
1263
+ pt = if defined? Encoding then
1264
+ s(:const, Encoding::UTF_8)
1265
+ else
1266
+ s(:str, "Unsupported!")
1267
+ end
1268
+
1269
+ assert_parse rb, pt
1270
+ end
1271
+
1272
+ def test_do_colon_19
1273
+ rb = "while false : 42 end"
1274
+
1275
+ assert_parse_error rb, "(string):1 :: parse error on value \":\" (tCOLON)"
1276
+ end
1277
+
1278
+ def test_assoc_list_19
1279
+ rb = "{1, 2, 3, 4}"
1280
+
1281
+ assert_parse_error rb, "(string):1 :: parse error on value \",\" (tCOMMA)"
1282
+ end
1283
+
1284
+ def test_case_then_colon_19
1285
+ rb = <<-EOM
1286
+ case x
1287
+ when Fixnum : # need the space to not hit new hash arg syntax
1288
+ 42
1289
+ end
1290
+ EOM
1291
+
1292
+ assert_parse_error rb, "(string):2 :: parse error on value \":\" (tCOLON)"
1293
+ end
1294
+
1295
+ def test_parse_def_xxx1
1296
+ rb = 'def f(a, *b, c = nil) end'
1297
+
1298
+ assert_parse_error rb, '(string):1 :: parse error on value "=" (tEQL)'
1299
+ end
1300
+
1301
+ def test_parse_def_xxx2
1302
+ rb = 'def f(a = nil, *b, c = nil) end'
1303
+
1304
+ assert_parse_error rb, '(string):1 :: parse error on value "=" (tEQL)'
1305
+ end
1306
+
1307
+ def test_parse_until_not_canonical
1308
+ rb = "until not var.nil?\n 'foo'\nend"
1309
+ pt = s(:until,
1310
+ s(:call, s(:call, s(:call, nil, :var), :nil?), :"!"),
1311
+ s(:str, "foo"), true)
1312
+
1313
+ assert_parse rb, pt
1314
+ end
1315
+
1316
+ def test_parse_until_not_noncanonical
1317
+ rb = "until not var.nil?\n 'foo'\nend"
1318
+ pt = s(:until,
1319
+ s(:call, s(:call, s(:call, nil, :var), :nil?), :"!"),
1320
+ s(:str, "foo"), true)
1321
+
1322
+ processor.canonicalize_conditions = false
1323
+
1324
+ assert_parse rb, pt
1325
+ end
1326
+
1327
+ def test_parse_if_not_canonical
1328
+ rb = "if not var.nil? then 'foo' else 'bar'\nend"
1329
+ pt = s(:if,
1330
+ s(:call, s(:call, s(:call, nil, :var), :nil?), :"!"),
1331
+ s(:str, "foo"),
1332
+ s(:str, "bar"))
1333
+
1334
+ assert_parse rb, pt
1335
+ end
1336
+
1337
+ def test_parse_if_not_noncanonical
1338
+ rb = "if not var.nil? then 'foo' else 'bar'\nend"
1339
+ pt = s(:if,
1340
+ s(:call, s(:call, s(:call, nil, :var), :nil?), :"!"),
1341
+ s(:str, "foo"),
1342
+ s(:str, "bar"))
1343
+
1344
+ processor.canonicalize_conditions = false
1345
+
1346
+ assert_parse rb, pt
1347
+ end
1348
+
1349
+ def test_parse_while_not_canonical
1350
+ rb = "while not var.nil?\n 'foo'\nend"
1351
+ pt = s(:while,
1352
+ s(:call, s(:call, s(:call, nil, :var), :nil?), :"!"),
1353
+ s(:str, "foo"), true)
1354
+
1355
+ assert_parse rb, pt
1356
+ end
1357
+
1358
+ def test_parse_while_not_noncanonical
1359
+ rb = "while not var.nil?\n 'foo'\nend"
1360
+ pt = s(:while,
1361
+ s(:call, s(:call, s(:call, nil, :var), :nil?), :"!"),
1362
+ s(:str, "foo"), true)
1363
+
1364
+ processor.canonicalize_conditions = false
1365
+
1366
+ assert_parse rb, pt
1367
+ end
1368
+
1369
+ def test_parse_opt_call_args_assocs_comma
1370
+ rb = "1[2=>3,]"
1371
+ pt = s(:call, s(:lit, 1), :[], s(:lit, 2), s(:lit, 3))
1372
+
1373
+ assert_parse rb, pt
1374
+ end
1375
+
1376
+ def test_bug_hash_args
1377
+ rb = "foo(:bar, baz: nil)"
1378
+ pt = s(:call, nil, :foo,
1379
+ s(:lit, :bar),
1380
+ s(:hash, s(:lit, :baz), s(:nil)))
1381
+
1382
+ assert_parse rb, pt
1383
+ end
1384
+
1385
+ def test_bug_hash_args_trailing_comma
1386
+ rb = "foo(:bar, baz: nil,)"
1387
+ pt = s(:call, nil, :foo, # NOTE: same sexp as test_bug_hash_args
1388
+ s(:lit, :bar),
1389
+ s(:hash, s(:lit, :baz), s(:nil)))
1390
+
1391
+ assert_parse rb, pt
1392
+ end
1393
+
1394
+ def test_block_arg_optional
1395
+ rb = "a { |b = 1| }"
1396
+ pt = s(:iter,
1397
+ s(:call, nil, :a),
1398
+ s(:args, s(:lasgn, :b, s(:lit, 1))))
1399
+
1400
+ assert_parse rb, pt
1401
+ end
1402
+
1403
+ def test_zomg_sometimes_i_hate_this_project
1404
+ rb = <<-RUBY
1405
+ {
1406
+ a: lambda { b ? c() : d },
1407
+ e: nil,
1408
+ }
1409
+ RUBY
1410
+
1411
+ pt = s(:hash,
1412
+ s(:lit, :a),
1413
+ s(:iter,
1414
+ s(:call, nil, :lambda),
1415
+ s(:args),
1416
+ s(:if, s(:call, nil, :b), s(:call, nil, :c), s(:call, nil, :d))),
1417
+
1418
+ s(:lit, :e),
1419
+ s(:nil))
1420
+
1421
+ assert_parse rb, pt
1422
+ end
1423
+
1424
+ # def test_pipe_semicolon # HACK
1425
+ # rb = "a.b do | ; c | end"
1426
+ # pt = s(:iter, s(:call, s(:call, nil, :a), :b), 0)
1427
+ #
1428
+ # assert_parse rb, pt
1429
+ # end
1430
+
1431
+ def test_wtf
1432
+ # lambda -> f_larglist lambda_body
1433
+ # f_larglist -> f_args opt_bv_decl
1434
+ # opt_bv_decl
1435
+ # bv_decls
1436
+ # bvar
1437
+
1438
+ rb = "->(a, b=nil) { p [a, b] }"
1439
+ pt = s(:iter,
1440
+ s(:call, nil, :lambda),
1441
+ s(:args, :a, s(:lasgn, :b, s(:nil))),
1442
+ s(:call, nil, :p, s(:array, s(:lvar, :a), s(:lvar, :b))))
1443
+
1444
+ assert_parse rb, pt
1445
+
1446
+ # rb = "->(a; b) { p [a, b] }"
1447
+ #
1448
+ # assert_parse rb, pt
1449
+ end
1450
+
1451
+ def test_block_args_opt1
1452
+ rb = "f { |a, b = 42| [a, b] }"
1453
+ pt = s(:iter,
1454
+ s(:call, nil, :f),
1455
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42))),
1456
+ s(:array, s(:lvar, :a), s(:lvar, :b)))
1457
+
1458
+ assert_parse rb, pt
1459
+ end
1460
+
1461
+ def test_block_args_opt2
1462
+ rb = "f { |a, b = 42, c = 24| [a, b, c] }"
1463
+ pt = s(:iter,
1464
+ s(:call, nil, :f),
1465
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42)), s(:lasgn, :c, s(:lit, 24))),
1466
+ s(:array, s(:lvar, :a), s(:lvar, :b), s(:lvar, :c)))
1467
+
1468
+ assert_parse rb, pt
1469
+ end
1470
+
1471
+ def test_block_args_opt3
1472
+ rb = "f { |a, b = 42, c = 24, &d| [a, b, c, d] }"
1473
+ pt = s(:iter,
1474
+ s(:call, nil, :f),
1475
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42)), s(:lasgn, :c, s(:lit, 24)), :"&d"),
1476
+ s(:array, s(:lvar, :a), s(:lvar, :b), s(:lvar, :c), s(:lvar, :d)))
1477
+
1478
+ assert_parse rb, pt
1479
+ end
1480
+
1481
+ def test_i_have_no_freakin_clue
1482
+ rb = "1 ? b('') : 2\na d: 3"
1483
+ pt = s(:block,
1484
+ s(:if, s(:lit, 1), s(:call, nil, :b, s(:str, "")), s(:lit, 2)),
1485
+ s(:call, nil, :a, s(:hash, s(:lit, :d), s(:lit, 3))))
1486
+
1487
+ assert_parse rb, pt
1488
+ end
1489
+
1490
+ def test_motherfuckin_leading_dots
1491
+ rb = "a\n.b"
1492
+ pt = s(:call, s(:call, nil, :a), :b)
1493
+
1494
+ assert_parse rb, pt
1495
+ end
1496
+
1497
+ def test_motherfuckin_leading_dots2
1498
+ rb = "a\n..b"
1499
+
1500
+ assert_parse_error rb, '(string):2 :: parse error on value ".." (tDOT2)'
1501
+ end
1502
+
1503
+ def test_kill_me
1504
+ rb = "f { |a, (b, *c)| }"
1505
+ pt = s(:iter,
1506
+ s(:call, nil, :f),
1507
+ s(:args, :a, s(:masgn, :b, :"*c")))
1508
+
1509
+ assert_parse rb, pt
1510
+ end
1511
+
1512
+ def test_kill_me2
1513
+ rb = "f { |*a, b| }"
1514
+ pt = s(:iter, s(:call, nil, :f), s(:args, :"*a", :b))
1515
+
1516
+ assert_parse rb, pt
1517
+ end
1518
+
1519
+ def test_kill_me3
1520
+ rb = "f { |*a, b, &c| }"
1521
+ pt = s(:iter, s(:call, nil, :f), s(:args, :"*a", :b, :"&c"))
1522
+
1523
+ assert_parse rb, pt
1524
+ end
1525
+
1526
+ def test_kill_me4
1527
+ rb = "a=b ? true: false"
1528
+ pt = s(:lasgn, :a, s(:if, s(:call, nil, :b), s(:true), s(:false)))
1529
+
1530
+ assert_parse rb, pt
1531
+ end
1532
+
1533
+ # def test_kill_me5
1534
+ # rb = "f ->() { g do end }"
1535
+ # pt = 42
1536
+ #
1537
+ # assert_parse rb, pt
1538
+ # end
1539
+
1540
+ def test_iter_args_4
1541
+ rb = "f { |a, *b, c| }"
1542
+ pt = s(:iter, s(:call, nil, :f), s(:args, :a, :"*b", :c))
1543
+
1544
+ assert_parse rb, pt
1545
+ end
1546
+
1547
+ def test_iter_args_5
1548
+ rb = "f { |a, &b| }"
1549
+ pt = s(:iter, s(:call, nil, :f), s(:args, :a, :"&b"))
1550
+
1551
+ assert_parse rb, pt
1552
+ end
1553
+
1554
+ def test_iter_args_6
1555
+ rb = "f { |a, b=42, c| }"
1556
+ pt = s(:iter, s(:call, nil, :f), s(:args, :a, s(:lasgn, :b, s(:lit, 42)), :c))
1557
+
1558
+ assert_parse rb, pt
1559
+ end
1560
+
1561
+ # In 1.8, block args with an outer set of parens are superfluous.
1562
+ # In 1.9, outer set of parens are NOT... they are an explicit extra masgn.
1563
+
1564
+ def test_iter_args_2__19
1565
+ rb = "f { |(a, b)| }"
1566
+ pt = s(:iter, s(:call, nil, :f), s(:args, s(:masgn, :a, :b)))
1567
+
1568
+ assert_parse rb, pt
1569
+ end
1570
+
1571
+ def test_bug_args__19
1572
+ rb = "f { |(a, b)| d }"
1573
+ pt = s(:iter, s(:call, nil, :f),
1574
+ s(:args, s(:masgn, :a, :b)),
1575
+ s(:call, nil, :d))
1576
+
1577
+ assert_parse rb, pt
1578
+ end
1579
+
1580
+ def test_bug_args_masgn_outer_parens__19
1581
+ rb = "f { |((k, v), i)| }"
1582
+ pt = s(:iter, # NOTE: same sexp as test_bug_args_masgn
1583
+ s(:call, nil, :f),
1584
+ s(:args, s(:masgn, s(:masgn, :k, :v), :i)))
1585
+
1586
+ assert_parse rb, pt.dup
1587
+ end
1588
+
1589
+ def test_iter_args_7_1
1590
+ rb = "f { |a = 42, *b| }"
1591
+ pt = s(:iter, s(:call, nil, :f),
1592
+ s(:args, s(:lasgn, :a, s(:lit, 42)), :"*b"))
1593
+
1594
+ assert_parse rb, pt
1595
+ end
1596
+
1597
+ def test_iter_args_7_2
1598
+ rb = "f { |a = 42, *b, &c| }"
1599
+ pt = s(:iter, s(:call, nil, :f),
1600
+ s(:args, s(:lasgn, :a, s(:lit, 42)), :"*b", :"&c"))
1601
+
1602
+ assert_parse rb, pt
1603
+ end
1604
+
1605
+ def test_iter_args_8_1
1606
+ rb = "f { |a = 42, *b, c| }"
1607
+ pt = s(:iter, s(:call, nil, :f),
1608
+ s(:args, s(:lasgn, :a, s(:lit, 42)), :"*b", :c))
1609
+
1610
+ assert_parse rb, pt
1611
+ end
1612
+
1613
+ def test_iter_args_8_2
1614
+ rb = "f { |a = 42, *b, c, &d| }"
1615
+ pt = s(:iter, s(:call, nil, :f),
1616
+ s(:args, s(:lasgn, :a, s(:lit, 42)), :"*b", :c, :"&d"))
1617
+
1618
+ assert_parse rb, pt
1619
+ end
1620
+
1621
+ def test_iter_args_9_1
1622
+ rb = "f { |a = 42, b| }"
1623
+ pt = s(:iter, s(:call, nil, :f),
1624
+ s(:args, s(:lasgn, :a, s(:lit, 42)), :b))
1625
+
1626
+ assert_parse rb, pt
1627
+ end
1628
+
1629
+ def test_iter_args_9_2
1630
+ rb = "f { |a = 42, b, &c| }"
1631
+ pt = s(:iter, s(:call, nil, :f),
1632
+ s(:args, s(:lasgn, :a, s(:lit, 42)), :b, :"&c"))
1633
+
1634
+ assert_parse rb, pt
1635
+ end
1636
+
1637
+ def test_iter_args_10_1
1638
+ rb = "f { |a, b = 42, *c| }"
1639
+ pt = s(:iter, s(:call, nil, :f),
1640
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42)), :"*c"))
1641
+
1642
+ assert_parse rb, pt
1643
+ end
1644
+
1645
+ def test_iter_args_10_2
1646
+ rb = "f { |a, b = 42, *c, &d| }"
1647
+ pt = s(:iter, s(:call, nil, :f),
1648
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42)), :"*c", :"&d"))
1649
+
1650
+ assert_parse rb, pt
1651
+ end
1652
+
1653
+ def test_iter_args_11_1
1654
+ rb = "f { |a, b = 42, *c, d| }"
1655
+ pt = s(:iter, s(:call, nil, :f),
1656
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42)), :"*c", :d))
1657
+
1658
+ assert_parse rb, pt
1659
+ end
1660
+
1661
+ def test_iter_args_11_2
1662
+ rb = "f { |a, b = 42, *c, d, &e| }"
1663
+ pt = s(:iter, s(:call, nil, :f),
1664
+ s(:args, :a, s(:lasgn, :b, s(:lit, 42)), :"*c", :d, :"&e"))
1665
+
1666
+ assert_parse rb, pt
1667
+ end
1668
+
1669
+ def test_kill_me_6
1670
+ # | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
1671
+ rb = "f { |a, (b, *c, d)| }"
1672
+ pt = s(:iter,
1673
+ s(:call, nil, :f),
1674
+ s(:args, :a, s(:masgn, :b, :"*c", :d)))
1675
+
1676
+ assert_parse rb, pt
1677
+ end
1678
+
1679
+ def test_kill_me_7
1680
+ # | f_marg_list tCOMMA tSTAR
1681
+ rb = "f { |a, (b, *)| }"
1682
+ pt = s(:iter,
1683
+ s(:call, nil, :f),
1684
+ s(:args, :a, s(:masgn, :b, :*)))
1685
+
1686
+ assert_parse rb, pt
1687
+ end
1688
+
1689
+ def test_kill_me_8
1690
+ # | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
1691
+ rb = "f { |a, (b, *, c)| }"
1692
+ pt = s(:iter,
1693
+ s(:call, nil, :f),
1694
+ s(:args, :a, s(:masgn, :b, :*, :c)))
1695
+
1696
+ assert_parse rb, pt
1697
+ end
1698
+
1699
+ def test_kill_me_9
1700
+ # | tSTAR f_norm_arg
1701
+ rb = "f { |a, (*b)| }"
1702
+ pt = s(:iter,
1703
+ s(:call, nil, :f),
1704
+ s(:args, :a, s(:masgn, :"*b")))
1705
+
1706
+ assert_parse rb, pt
1707
+ end
1708
+
1709
+ def test_kill_me_10
1710
+ # | tSTAR f_norm_arg tCOMMA f_marg_list
1711
+ rb = "f { |a, (*b, c)| }"
1712
+ pt = s(:iter,
1713
+ s(:call, nil, :f),
1714
+ s(:args, :a, s(:masgn, :"*b", :c)))
1715
+
1716
+ assert_parse rb, pt
1717
+ end
1718
+
1719
+ def test_kill_me_11
1720
+ # | tSTAR
1721
+ rb = "f { |a, (*)| }"
1722
+ pt = s(:iter,
1723
+ s(:call, nil, :f),
1724
+ s(:args, :a, s(:masgn, :*)))
1725
+
1726
+ assert_parse rb, pt
1727
+ end
1728
+
1729
+ def test_kill_me_12
1730
+ # | tSTAR tCOMMA f_marg_list
1731
+ rb = "f { |a, (*, b)| }"
1732
+ pt = s(:iter,
1733
+ s(:call, nil, :f),
1734
+ s(:args, :a, s(:masgn, :*, :b)))
1735
+
1736
+ assert_parse rb, pt
1737
+ end
1738
+
1739
+ def test_index_0
1740
+ rb = "a[] = b"
1741
+ pt = s(:attrasgn, s(:call, nil, :a), :[]=, s(:call, nil, :b))
1742
+
1743
+ assert_parse rb, pt
1744
+ end
1745
+
1746
+ def test_lambda_do_vs_brace
1747
+ pt = s(:call, nil, :f, s(:iter, s(:call, nil, :lambda), 0))
1748
+
1749
+ rb = "f ->() {}"
1750
+ assert_parse rb, pt
1751
+
1752
+ rb = "f ->() do end"
1753
+ assert_parse rb, pt
1754
+ end
1755
+
1756
+ def test_thingy
1757
+ pt = s(:call, s(:call, nil, :f), :call, s(:lit, 42))
1758
+
1759
+ rb = "f.(42)"
1760
+ assert_parse rb, pt
1761
+
1762
+ rb = "f::(42)"
1763
+ assert_parse rb, pt
1764
+ end
1765
+
1766
+ def test_unary_plus_on_literal
1767
+ rb = "+:a"
1768
+ pt = s(:call, s(:lit, :a), :+@)
1769
+
1770
+ assert_parse rb, pt
1771
+ end
1772
+ end