ruby_parser 3.15.0 → 3.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -34,12 +34,15 @@ module TestRubyParserShared
34
34
  skip "not ready for this yet"
35
35
 
36
36
  rb = "def f; if /(?<foo>bar)/ =~ 'bar' && p(foo); foo; end; end; f"
37
- pt = s(:if,
38
- s(:and,
39
- s(:match2, s(:lit, /(?<foo>bar)/), s(:str, "bar")),
40
- s(:call, nil, :p, s(:lvar, :foo))),
41
- s(:lvar, :foo),
42
- nil)
37
+ pt = s(:block,
38
+ s(:defn, :f, s(:args),
39
+ s(:if,
40
+ s(:and,
41
+ s(:match2, s(:lit, /(?<foo>bar)/), s(:str, "bar")),
42
+ s(:call, nil, :p, s(:lvar, :foo))),
43
+ s(:lvar, :foo),
44
+ nil)),
45
+ s(:call, nil, :f))
43
46
 
44
47
  assert_parse rb, pt
45
48
  end
@@ -179,10 +182,13 @@ module TestRubyParserShared
179
182
  assert_parse rb, pt
180
183
  end
181
184
 
182
- def test_begin_else_return_value
185
+ def test_begin_else_return_value # overridden below, warns < 2.6
183
186
  rb = "begin; else 2; end"
187
+ pt = s(:lit, 2)
184
188
 
185
- assert_syntax_error rb, "else without rescue is useless"
189
+ assert_output "", "else without rescue is useless\n" do
190
+ assert_parse rb, pt
191
+ end
186
192
  end
187
193
 
188
194
  def test_begin_ensure_no_bodies
@@ -322,13 +328,14 @@ module TestRubyParserShared
322
328
  end
323
329
 
324
330
  def test_bug170
325
- skip "not ready for this yet"
326
-
327
- # TODO: needs to fail on 2.1 and up
328
331
  rb = '$-'
329
332
  pt = s(:gvar, :"$-")
330
333
 
331
- assert_parse rb, pt
334
+ if processor.class.version >= 21
335
+ assert_syntax_error rb, /unexpected \$undefined/
336
+ else
337
+ assert_parse rb, pt
338
+ end
332
339
  end
333
340
 
334
341
  def test_bug179
@@ -339,12 +346,9 @@ module TestRubyParserShared
339
346
  end
340
347
 
341
348
  def test_bug190
342
- skip "not ready for this yet"
343
-
344
349
  rb = %{%r'\\\''} # stupid emacs
345
350
 
346
- assert_parse rb, :FUCK
347
- assert_syntax_error rb, "FUCK"
351
+ assert_parse rb, s(:lit, %r%'%)
348
352
 
349
353
  rb = %{%r'\\''}
350
354
  pt = s(:lit, /'/)
@@ -420,10 +424,13 @@ module TestRubyParserShared
420
424
  assert_parse rb, pt
421
425
  end
422
426
 
423
- def test_bug_begin_else
427
+ def test_bug_begin_else # overridden below, warns < 2.6
424
428
  rb = "begin 1; else; 2 end"
429
+ pt = s(:block, s(:lit, 1), s(:lit, 2))
425
430
 
426
- assert_syntax_error rb, "else without rescue is useless"
431
+ assert_output "", "else without rescue is useless\n" do
432
+ assert_parse rb, pt
433
+ end
427
434
  end
428
435
 
429
436
  def test_bug_call_arglist_parens
@@ -881,6 +888,29 @@ module TestRubyParserShared
881
888
  assert_parse rb, pt
882
889
  end
883
890
 
891
+ def test_heredoc_lineno
892
+ rb = "c = <<'CCC'\nline2\nline3\nline4\nCCC\n\nd = 42"
893
+ pt = s(:block,
894
+ s(:lasgn, :c, s(:str, "line2\nline3\nline4\n").line(1)).line(1),
895
+ s(:lasgn, :d, s(:lit, 42).line(7)).line(7)).line(1)
896
+
897
+ assert_parse rb, pt
898
+ end
899
+
900
+ def test_pctW_lineno
901
+ rb = "%W(a\\nb\nc\ d\ne\\\nf\ng\y h\\y i\\\y)"
902
+ pt = s(:array,
903
+ s(:str, "a\nb").line(1),
904
+ s(:str, "c").line(2),
905
+ s(:str, "d").line(2),
906
+ s(:str, "e\nf").line(3),
907
+ s(:str, "gy").line(5),
908
+ s(:str, "hy").line(5),
909
+ s(:str, "iy").line(5)).line(1)
910
+
911
+ assert_parse rb, pt
912
+ end
913
+
884
914
  def test_heredoc_bad_oct_escape
885
915
  rb = "s = <<-EOS\na\\247b\ncöd\nEOS\n"
886
916
  pt = s(:lasgn, :s, s(:str, "a\xa7b\nc\xc3\xb6d\n".b))
@@ -1057,7 +1087,7 @@ module TestRubyParserShared
1057
1087
  s(:array,
1058
1088
  s(:str, "a").line(2),
1059
1089
  s(:str, "b").line(3)).line(1),
1060
- s(:lit, 1).line(5))
1090
+ s(:lit, 1).line(5)).line(1)
1061
1091
  assert_parse rb, pt
1062
1092
  end
1063
1093
 
@@ -1433,7 +1463,7 @@ module TestRubyParserShared
1433
1463
  s(:array,
1434
1464
  s(:str, "a").line(2),
1435
1465
  s(:str, "b").line(3)).line(1),
1436
- s(:lit, 1).line(5))
1466
+ s(:lit, 1).line(5)).line(1)
1437
1467
  assert_parse rb, pt
1438
1468
  end
1439
1469
 
@@ -1635,7 +1665,7 @@ module TestRubyParserShared
1635
1665
 
1636
1666
  def test_parse_line_defn_no_parens_args
1637
1667
  rb = "def f a\nend"
1638
- pt = s(:defn, :f, s(:args, :a).line(1), s(:nil).line(2)).line(1)
1668
+ pt = s(:defn, :f, s(:args, :a).line(1), s(:nil).line(1)).line(1)
1639
1669
 
1640
1670
  assert_parse_line rb, pt, 1
1641
1671
  end
@@ -1656,7 +1686,7 @@ module TestRubyParserShared
1656
1686
  end
1657
1687
 
1658
1688
  def test_parse_line_defn_no_parens
1659
- pt = s(:defn, :f, s(:args).line(1), s(:nil)).line(1)
1689
+ pt = s(:defn, :f, s(:args).line(1), s(:nil).line(1)).line(1)
1660
1690
 
1661
1691
  rb = "def f\nend"
1662
1692
  assert_parse_line rb, pt, 1
@@ -1691,17 +1721,21 @@ module TestRubyParserShared
1691
1721
  assert_parse_line rb, pt, 1
1692
1722
  end
1693
1723
 
1694
- def test_parse_line_dstr_newline
1695
- rb = <<-'CODE'
1696
- "a\n#{
1697
- }"
1698
- true
1699
- CODE
1700
-
1724
+ def test_parse_line_dstr_escaped_newline
1725
+ rb = "\"a\\n\#{\n}\"\ntrue"
1701
1726
  pt = s(:block,
1702
1727
  s(:dstr, "a\n",
1703
- s(:evstr)).line(1),
1704
- s(:true).line(3))
1728
+ s(:evstr).line(1)).line(1),
1729
+ s(:true).line(3)).line(1)
1730
+
1731
+ assert_parse rb, pt
1732
+ end
1733
+
1734
+ def test_parse_line_dstr_soft_newline
1735
+ rb = "\"a\n#\{\n}\"\ntrue"
1736
+ pt = s(:block,
1737
+ s(:dstr, "a\n", s(:evstr).line(2)).line(1),
1738
+ s(:true).line(4)).line(1)
1705
1739
 
1706
1740
  assert_parse rb, pt
1707
1741
  end
@@ -1726,7 +1760,7 @@ module TestRubyParserShared
1726
1760
 
1727
1761
  def test_parse_line_heredoc
1728
1762
  rb = <<-CODE
1729
- string = <<-HEREDOC
1763
+ string = <<-HEREDOC.strip
1730
1764
  very long string
1731
1765
  HEREDOC
1732
1766
  puts string
@@ -1734,20 +1768,23 @@ module TestRubyParserShared
1734
1768
 
1735
1769
  pt = s(:block,
1736
1770
  s(:lasgn, :string,
1737
- s(:str, " very long string\n").line(1)).line(1),
1738
- s(:call, nil, :puts, s(:lvar, :string).line(4)).line(4)).line(1)
1771
+ s(:call,
1772
+ s(:str, " very long string\n").line(1),
1773
+ :strip).line(1),
1774
+ ).line(1),
1775
+ s(:call, nil, :puts,
1776
+ s(:lvar, :string).line(4)).line(4)
1777
+ ).line(1)
1739
1778
 
1740
1779
  assert_parse rb, pt
1741
1780
  end
1742
1781
 
1743
1782
  def test_parse_line_heredoc_evstr
1744
- skip "heredoc line numbers are just gonna be screwed for a while..."
1745
-
1746
1783
  rb = "<<-A\na\n\#{b}\nA"
1747
- pt = s(:dstr, "a\n",
1748
- s(:evstr,
1749
- s(:call, nil, :b).line(3)),
1750
- s(:str, "\n")).line(1)
1784
+ pt = s(:dstr,
1785
+ "a\n",
1786
+ s(:evstr, s(:call, nil, :b).line(3)).line(3), s(:str, "\n").line(3)
1787
+ ).line(1)
1751
1788
 
1752
1789
  assert_parse rb, pt
1753
1790
  end
@@ -2055,13 +2092,13 @@ module TestRubyParserShared
2055
2092
  assert_parse rb, pt
2056
2093
  end
2057
2094
 
2058
- # def test_str_pct_nested_nested
2059
- # rb = "%{ { #\{ \"#\{1}\" } } }"
2060
- # assert_equal " { 1 } ", eval(rb)
2061
- # pt = s(:dstr, " { ", s(:evstr, s(:lit, 1)), s(:str, " } "))
2062
- #
2063
- # assert_parse rb, pt
2064
- # end
2095
+ def test_str_pct_nested_nested
2096
+ rb = "%{ { #\{ \"#\{1}\" } } }"
2097
+ assert_equal " { 1 } ", eval(rb)
2098
+ pt = s(:dstr, " { ", s(:evstr, s(:lit, 1)), s(:str, " } "))
2099
+
2100
+ assert_parse rb, pt
2101
+ end
2065
2102
 
2066
2103
  def test_str_pct_Q_nested
2067
2104
  rb = "%Q[before [#\{nest}] after]"
@@ -2077,6 +2114,60 @@ module TestRubyParserShared
2077
2114
  assert_parse rb, pt
2078
2115
  end
2079
2116
 
2117
+ def test_str_single_newline
2118
+ rp = "a '\n';b"
2119
+ pt = s(:block,
2120
+ s(:call, nil, :a, s(:str, "\n").line(1)).line(1),
2121
+ s(:call, nil, :b).line(2)).line(1)
2122
+
2123
+ assert_parse rp, pt
2124
+ end
2125
+
2126
+ def test_str_single_escaped_newline
2127
+ rp = "a '\\n';b"
2128
+ pt = s(:block,
2129
+ s(:call, nil, :a, s(:str, "\\n").line(1)).line(1),
2130
+ s(:call, nil, :b).line(1)).line(1)
2131
+
2132
+ assert_parse rp, pt
2133
+ end
2134
+
2135
+ def test_str_single_double_escaped_newline
2136
+ rp = "a '\\\\n';b"
2137
+ pt = s(:block,
2138
+ s(:call, nil, :a, s(:str, "\\n").line(1)).line(1),
2139
+ s(:call, nil, :b).line(1)).line(1)
2140
+
2141
+ assert_parse rp, pt
2142
+ end
2143
+
2144
+ def test_str_double_newline
2145
+ rp = "a \"\n\";b"
2146
+ pt = s(:block,
2147
+ s(:call, nil, :a, s(:str, "\n").line(1)).line(1),
2148
+ s(:call, nil, :b).line(2)).line(1)
2149
+
2150
+ assert_parse rp, pt
2151
+ end
2152
+
2153
+ def test_str_double_escaped_newline
2154
+ rp = "a \"\\n\";b"
2155
+ pt = s(:block,
2156
+ s(:call, nil, :a, s(:str, "\n").line(1)).line(1),
2157
+ s(:call, nil, :b).line(1)).line(1)
2158
+
2159
+ assert_parse rp, pt
2160
+ end
2161
+
2162
+ def test_str_double_double_escaped_newline
2163
+ rp = "a \"\\\\n\";b"
2164
+ pt = s(:block,
2165
+ s(:call, nil, :a, s(:str, "\\n").line(1)).line(1),
2166
+ s(:call, nil, :b).line(1)).line(1)
2167
+
2168
+ assert_parse rp, pt
2169
+ end
2170
+
2080
2171
  def test_str_str
2081
2172
  rb = "\"a #\{'b'}\""
2082
2173
  pt = s(:str, "a b")
@@ -2632,7 +2723,7 @@ module TestRubyParserShared19Plus
2632
2723
  rb = "def m arg = false\nend"
2633
2724
  pt = s(:defn, :m,
2634
2725
  s(:args, s(:lasgn, :arg, s(:false).line(1)).line(1)).line(1),
2635
- s(:nil).line(2)).line(1)
2726
+ s(:nil).line(1)).line(1)
2636
2727
 
2637
2728
  assert_parse rb, pt
2638
2729
  end
@@ -3079,6 +3170,31 @@ module TestRubyParserShared19Plus
3079
3170
  assert_parse rb, pt
3080
3171
  end
3081
3172
 
3173
+ def test_call_leading_dots
3174
+ rb = "a\n.b\n.c"
3175
+ pt = s(:call, s(:call, s(:call, nil, :a), :b), :c)
3176
+
3177
+ assert_parse rb, pt
3178
+ end
3179
+
3180
+ def test_call_leading_dots_comment
3181
+ rb = "a\n.b\n#.c\n.d"
3182
+ pt = s(:call,
3183
+ s(:call,
3184
+ s(:call, nil, :a).line(1),
3185
+ :b).line(1),
3186
+ :d).line(1) # TODO: fix linenos: 1, 2, 4
3187
+
3188
+ assert_parse rb, pt
3189
+ end
3190
+
3191
+ def test_call_trailing_dots
3192
+ rb = "a.\nb.\nc"
3193
+ pt = s(:call, s(:call, s(:call, nil, :a), :b), :c)
3194
+
3195
+ assert_parse rb, pt
3196
+ end
3197
+
3082
3198
  def test_motherfuckin_leading_dots
3083
3199
  rb = "a\n.b"
3084
3200
  pt = s(:call, s(:call, nil, :a), :b)
@@ -3087,9 +3203,15 @@ module TestRubyParserShared19Plus
3087
3203
  end
3088
3204
 
3089
3205
  def test_motherfuckin_leading_dots2
3090
- rb = "a\n..b"
3206
+ rb = "1\n..3"
3207
+ pt = s(:block, s(:lit, 1).line(1),
3208
+ s(:dot2, nil, s(:lit, 3).line(2)).line(2)).line(1)
3091
3209
 
3092
- assert_parse_error rb, '(string):2 :: parse error on value ".." (tDOT2)'
3210
+ if processor.class.version >= 27
3211
+ assert_parse rb, pt
3212
+ else
3213
+ assert_parse_error rb, '(string):2 :: parse error on value ".." (tDOT2)'
3214
+ end
3093
3215
  end
3094
3216
 
3095
3217
  def test_multiline_hash_declaration
@@ -3368,6 +3490,98 @@ end
3368
3490
  module TestRubyParserShared20Plus
3369
3491
  include TestRubyParserShared19Plus
3370
3492
 
3493
+ def test_read_escape_unicode_h4
3494
+ rb = '?\u00a0'
3495
+ pt = s(:str, ?\u00a0)
3496
+
3497
+ assert_parse rb, pt
3498
+ end
3499
+
3500
+ def test_read_escape_unicode_curlies
3501
+ rb = '?\u{00a0}'
3502
+ pt = s(:str, ?\u00a0)
3503
+
3504
+ assert_parse rb, pt
3505
+ end
3506
+
3507
+ def test_regexp_unicode_curlies
3508
+ rb = '/\u{df}/'
3509
+ pt = s(:lit, /\u{df}/)
3510
+
3511
+ assert_parse rb, pt
3512
+
3513
+ rb = '/\u{c0de babe}/'
3514
+ pt = s(:lit, /\u{c0de babe}/)
3515
+
3516
+ assert_parse rb, pt
3517
+ end
3518
+
3519
+ def test_qw_escape
3520
+ rb = "%q(\1\\\')"
3521
+ pt = s(:str, "\001\\'")
3522
+
3523
+ assert_parse rb, pt
3524
+ end
3525
+
3526
+ def test_pct_nl
3527
+ rb = "x = %\n\n"
3528
+ pt = s(:lasgn, :x, s(:str, ""))
3529
+
3530
+ assert_parse rb, pt
3531
+ end
3532
+
3533
+ def test_regexp_esc_C_slash
3534
+ rb = "/\\cC\\d/"
3535
+ pt = s(:lit, /\cC\d/)
3536
+
3537
+ assert_parse rb, pt
3538
+ end
3539
+
3540
+ def test_heredoc_wtf_I_hate_you
3541
+ rb = "p <<-END+'b\n a\n END\n c'+'d'"
3542
+ pt = s(:call, nil, :p,
3543
+ s(:call,
3544
+ s(:call, s(:str, " a\n"), :+,
3545
+ s(:str, "b\n c")),
3546
+ :+, s(:str, "d")))
3547
+
3548
+ assert_parse rb, pt
3549
+ end
3550
+
3551
+ def test_heredoc_nested
3552
+ rb = "[<<A,\n\#{<<B}\nb\nB\na\nA\n0]"
3553
+ pt = s(:array, s(:str, "b\n\na\n").line(1),
3554
+ s(:lit, 0).line(7)).line(1)
3555
+
3556
+ assert_parse rb, pt
3557
+ end
3558
+
3559
+ def test_pct_w_heredoc_interp_nested
3560
+ rb = "%W( 1 \#{<<A} 3\n2\nA\n 4 5 )"
3561
+ pt = s(:array,
3562
+ s(:str, "1"),
3563
+ s(:str, "2\n"),
3564
+ s(:str, "3"),
3565
+ s(:str, "4"),
3566
+ s(:str, "5"))
3567
+
3568
+ assert_parse rb, pt
3569
+ end
3570
+
3571
+ def test_regexp_esc_u
3572
+ rb = "/[\\u0021-\\u0027]/"
3573
+ pt = s(:lit, /[\u0021-\u0027]/)
3574
+
3575
+ assert_parse rb, pt
3576
+ end
3577
+
3578
+ def test_qw_escape_term
3579
+ rb = "%q|blah blah \\| blah blah|"
3580
+ pt = s(:str, "blah blah | blah blah")
3581
+
3582
+ assert_parse rb, pt
3583
+ end
3584
+
3371
3585
  def test_args_kw_block
3372
3586
  rb = "def f(a: 1, &b); end"
3373
3587
  pt = s(:defn, :f, s(:args, s(:kwarg, :a, s(:lit, 1)), :"&b"), s(:nil))
@@ -3375,6 +3589,49 @@ module TestRubyParserShared20Plus
3375
3589
  assert_parse rb, pt
3376
3590
  end
3377
3591
 
3592
+ def test_heredoc_backslash_nl
3593
+ rb = %Q(" why would someone do this? \\\n blah\n")
3594
+ pt = s(:str, " why would someone do this? blah\n")
3595
+
3596
+ assert_parse rb, pt
3597
+
3598
+ rb = "<<-DESC\n why would someone do this? \\\n blah\nDESC"
3599
+
3600
+ assert_parse rb, pt
3601
+ end
3602
+
3603
+ def test_heredoc_comma_arg
3604
+ rb = "[\" some text\n\",]"
3605
+ pt = s(:array, s(:str, " some text\n"))
3606
+
3607
+ assert_parse rb, pt
3608
+
3609
+ rb = "[<<-FILE,\n some text\nFILE\n]"
3610
+
3611
+ assert_parse rb, pt
3612
+ end
3613
+
3614
+ def test_heredoc_trailing_slash_continued_call
3615
+ rb = "<<END\\\nblah\nEND\n.strip"
3616
+ pt = s(:call, s(:str, "blah\n"), :strip)
3617
+
3618
+ assert_parse rb, pt
3619
+ end
3620
+
3621
+ def test_pct_q_backslash_nl
3622
+ rb = "%q{ \\\n}"
3623
+ pt = s(:str, " \\\n")
3624
+
3625
+ assert_parse rb, pt
3626
+ end
3627
+
3628
+ def test_pct_Q_backslash_nl
3629
+ rb = "%Q{ \\\n}"
3630
+ pt = s(:str, " ")
3631
+
3632
+ assert_parse rb, pt
3633
+ end
3634
+
3378
3635
  def test_block_arg_kwsplat
3379
3636
  rb = "a { |**b| }"
3380
3637
  pt = s(:iter, s(:call, nil, :a), s(:args, :"**b"))
@@ -3619,19 +3876,22 @@ module TestRubyParserShared20Plus
3619
3876
  s(:array,
3620
3877
  s(:lit, :a).line(2),
3621
3878
  s(:lit, :b).line(3)).line(1),
3622
- s(:lit, 1).line(5))
3879
+ s(:lit, 1).line(5)).line(1)
3623
3880
  assert_parse rb, pt
3624
3881
  end
3625
3882
 
3626
3883
  def test_iter_array_curly
3627
- skip if processor.class.version >= 25
3628
-
3629
3884
  rb = "f :a, [:b] { |c, d| }" # yes, this is bad code... that's their problem
3630
3885
  pt = s(:iter,
3631
3886
  s(:call, nil, :f, s(:lit, :a), s(:array, s(:lit, :b))),
3632
3887
  s(:args, :c, :d))
3633
3888
 
3634
- assert_parse rb, pt
3889
+ if processor.class.version >= 25 then
3890
+ msg = /parse error on value "\{" \(tLCURLY\)/
3891
+ assert_syntax_error rb, msg, Racc::ParseError
3892
+ else
3893
+ assert_parse rb, pt
3894
+ end
3635
3895
  end
3636
3896
 
3637
3897
  def test_iter_kwarg
@@ -3745,6 +4005,17 @@ end
3745
4005
  module TestRubyParserShared21Plus
3746
4006
  include TestRubyParserShared20Plus
3747
4007
 
4008
+ def test_array_lits_trailing_calls
4009
+ rb = "[].b"
4010
+ pt = s(:call, s(:array), :b)
4011
+
4012
+ assert_parse rb, pt
4013
+
4014
+ rb = "%w[].b"
4015
+
4016
+ assert_parse rb, pt
4017
+ end
4018
+
3748
4019
  def test_block_kw
3749
4020
  rb = "blah { |k:42| }"
3750
4021
  pt = s(:iter, s(:call, nil, :blah), s(:args, s(:kwarg, :k, s(:lit, 42))))
@@ -3767,7 +4038,7 @@ module TestRubyParserShared21Plus
3767
4038
 
3768
4039
  def test_bug162__21plus
3769
4040
  rb = %q(<<E\nfoo\nE\rO)
3770
- emsg = "can't match /E(\\r*\\n|\\z)/ anywhere in . near line 1: \"\""
4041
+ emsg = "can't match /E(?=\\r?\\n|\\z)/ anywhere in . near line 1: \"\""
3771
4042
 
3772
4043
  assert_syntax_error rb, emsg
3773
4044
  end
@@ -3963,6 +4234,27 @@ module TestRubyParserShared23Plus
3963
4234
  assert_parse rb, pt
3964
4235
  end
3965
4236
 
4237
+ def test_heredoc_squiggly_blank_lines
4238
+ rb = "a = <<~EOF\n x\n\n z\nEOF\n\n"
4239
+ pt = s(:lasgn, :a, s(:str, "x\n\nz\n"))
4240
+
4241
+ assert_parse rb, pt
4242
+ end
4243
+
4244
+ def test_heredoc_squiggly_visually_blank_lines
4245
+ rb = "a = <<~EOF\n x\n \n z\nEOF\n\n"
4246
+ pt = s(:lasgn, :a, s(:str, "x\n\nz\n"))
4247
+
4248
+ assert_parse rb, pt
4249
+ end
4250
+
4251
+ def test_heredoc_squiggly_empty
4252
+ rb = "<<~A\nA"
4253
+ pt = s(:str, "")
4254
+
4255
+ assert_parse rb, pt
4256
+ end
4257
+
3966
4258
  def test_integer_with_if_modifier
3967
4259
  rb = "1_234if true"
3968
4260
  pt = s(:if, s(:true), s(:lit, 1234), nil)
@@ -4052,7 +4344,7 @@ module TestRubyParserShared23Plus
4052
4344
  end
4053
4345
 
4054
4346
  def test_safe_op_asgn
4055
- rb = "a&.b += x 1\n"
4347
+ rb = "a&.b += x 1"
4056
4348
  pt = s(:safe_op_asgn, s(:call, nil, :a), s(:call, nil, :x, s(:lit, 1)), :b, :+).line(1)
4057
4349
 
4058
4350
  assert_parse rb, pt
@@ -4115,6 +4407,18 @@ module TestRubyParserShared26Plus
4115
4407
  assert_parse rb, pt
4116
4408
  end
4117
4409
 
4410
+ def test_begin_else_return_value # overrides above, warns < 2.6
4411
+ rb = "begin; else 2; end"
4412
+
4413
+ assert_syntax_error rb, "else without rescue is useless"
4414
+ end
4415
+
4416
+ def test_bug_begin_else # overrides above, warns < 2.6
4417
+ rb = "begin 1; else; 2 end"
4418
+
4419
+ assert_syntax_error rb, "else without rescue is useless"
4420
+ end
4421
+
4118
4422
  def test_dot3_nil__26
4119
4423
  rb = "a..."
4120
4424
  pt = s(:dot3, s(:call, nil, :a), nil)
@@ -4132,57 +4436,900 @@ module TestRubyParserShared26Plus
4132
4436
  end
4133
4437
  end
4134
4438
 
4135
- module TestRubyParserShared27Plus
4136
- include TestRubyParserShared26Plus
4137
- end
4138
-
4139
- class TestRubyParser < Minitest::Test
4140
- def test_cls_version
4141
- assert_equal 23, RubyParser::V23.version
4142
- assert_equal 24, RubyParser::V24.version
4143
- assert_equal 24, Ruby24Parser.version
4144
- refute RubyParser::Parser.version
4439
+ module TestPatternMatching
4440
+ def rip rb
4441
+ require "ripper"
4442
+ puts
4443
+ pp Sexp.from_array Ripper.sexp rb
4145
4444
  end
4146
4445
 
4147
- def test_parse
4148
- processor = RubyParser.new
4446
+ def assert_case_in lit, exp_pt
4447
+ rb = "case :a\nin #{lit}\nend"
4149
4448
 
4150
- rb = "a.()"
4151
- pt = s(:call, s(:call, nil, :a), :call)
4449
+ if ENV["VERBOSE_TEST"] then
4450
+ puts
4451
+ puts rb
4452
+ end
4152
4453
 
4153
- assert_equal pt, processor.parse(rb)
4454
+ pt = s(:case, s(:lit, :a).line(1),
4455
+ s(:in, exp_pt, nil).line(2),
4456
+ nil).line(1)
4154
4457
 
4155
- # bad syntax
4156
- e = assert_raises Racc::ParseError do
4157
- capture_io do
4158
- processor.parse "a.("
4159
- end
4160
- end
4458
+ assert_parse rb, pt
4459
+ end
4161
4460
 
4162
- assert_includes e.message, 'parse error on value false ($end)'
4461
+ def test_case_in_09
4462
+ assert_case_in(":b, [:c]",
4463
+ s(:array_pat, nil,
4464
+ s(:lit, :b).line(2),
4465
+ s(:array_pat, nil, s(:lit, :c).line(2)).line(2)).line(2))
4163
4466
  end
4164
4467
 
4165
- def test_parse_error_from_first
4166
- processor = RubyParser.new
4468
+ def test_case_in_10
4469
+ assert_case_in "nil, nil, nil", s(:array_pat,
4470
+ nil,
4471
+ s(:nil).line(2),
4472
+ s(:nil).line(2),
4473
+ s(:nil).line(2)).line(2)
4474
+ end
4167
4475
 
4168
- e = assert_raises Racc::ParseError do
4169
- capture_io do
4170
- processor.parse "a -> () {"
4171
- end
4172
- end
4476
+ def test_case_in_21
4477
+ assert_case_in "Symbol()", s(:array_pat, s(:const, :Symbol).line(2)).line(2)
4478
+ end
4173
4479
 
4174
- # This is a 2.x error, will fail on 1.8/1.9.
4175
- assert_includes e.message, 'parse error on value false ($end)'
4480
+ def test_case_in_26
4481
+ assert_case_in "(42)", s(:lit, 42).line(2)
4176
4482
  end
4177
- end
4178
4483
 
4179
- class RubyParserTestCase < ParseTreeTestCase
4180
- attr_accessor :result, :processor
4484
+ def test_case_in_27
4485
+ assert_case_in("[A, *, B]",
4486
+ s(:array_pat, nil,
4487
+ s(:const, :A).line(2),
4488
+ :*,
4489
+ s(:const, :B).line(2)).line(2))
4490
+ end
4181
4491
 
4182
- make_my_diffs_pretty!
4492
+ def test_case_in_28_2
4493
+ assert_case_in '{ "b": }', s(:hash_pat, nil, s(:lit, :b).line(2), nil).line(2)
4494
+ end
4183
4495
 
4184
- def self.previous key
4185
- "Ruby"
4496
+ def test_case_in_28
4497
+ assert_case_in "[]", s(:array_pat).line(2)
4498
+ end
4499
+
4500
+ def test_case_in_29
4501
+ assert_case_in "**nil", s(:hash_pat, nil, s(:kwrest, :"**nil").line(2)).line(2)
4502
+ end
4503
+
4504
+ def test_case_in_30
4505
+ assert_case_in "{}", s(:hash_pat, nil).line(2)
4506
+ end
4507
+
4508
+ def test_case_in_31?
4509
+ rb = "case :a\nin [:b, *c]\n :d\nend"
4510
+ pt = s(:case, s(:lit, :a).line(1),
4511
+ s(:in,
4512
+ s(:array_pat, nil, s(:lit, :b).line(2), :"*c").line(2),
4513
+ s(:lit, :d).line(3)).line(2),
4514
+ nil).line(1)
4515
+
4516
+ assert_parse rb, pt
4517
+ end
4518
+
4519
+ def test_case_in_32
4520
+ assert_case_in "(1...3)", s(:dot3, s(:lit, 1).line(2), s(:lit, 3).line(2)).line(2)
4521
+ end
4522
+
4523
+ def test_case_in_33
4524
+ assert_case_in "(1...)", s(:dot3, s(:lit, 1).line(2), nil).line(2)
4525
+ end
4526
+
4527
+ def test_case_in_34
4528
+ assert_case_in "(..10)", s(:dot2, nil, s(:lit, 10).line(2)).line(2)
4529
+ end
4530
+
4531
+ def test_case_in_35
4532
+ assert_case_in "(...10)", s(:dot3, nil, s(:lit, 10).line(2)).line(2)
4533
+ end
4534
+
4535
+ def test_case_in_36
4536
+ rb = "[:a, b, c, [:d, *e, nil]]"
4537
+ pt = s(:array_pat,
4538
+ nil,
4539
+ s(:lit, :a).line(2),
4540
+ s(:lvar, :b).line(2),
4541
+ s(:lvar, :c).line(2),
4542
+ s(:array_pat,
4543
+ nil,
4544
+ s(:lit, :d).line(2),
4545
+ :"*e",
4546
+ s(:nil).line(2)).line(2)).line(2)
4547
+
4548
+ assert_case_in rb, pt
4549
+ end
4550
+
4551
+ def test_case_in_37
4552
+ rb = "case :a\nin { b: [Hash, *] }\n :c\nend"
4553
+ pt = s(:case, s(:lit, :a).line(1),
4554
+ s(:in,
4555
+ s(:hash_pat,
4556
+ nil,
4557
+ s(:lit, :b).line(2),
4558
+ s(:array_pat, nil, s(:const, :Hash).line(2), :"*").line(2)
4559
+ ).line(2),
4560
+ s(:lit, :c).line(3)).line(2),
4561
+ nil).line(1)
4562
+
4563
+ assert_parse rb, pt
4564
+ end
4565
+
4566
+ def test_case_in_42
4567
+ rb = "case :a\nin :b, *_ then nil\nend"
4568
+ pt = s(:case, s(:lit, :a).line(1),
4569
+ s(:in,
4570
+ s(:array_pat,
4571
+ nil,
4572
+ s(:lit, :b).line(2),
4573
+ :"*_",
4574
+ ).line(2),
4575
+ s(:nil).line(2)).line(2),
4576
+ nil).line(1)
4577
+
4578
+ assert_parse rb, pt
4579
+ end
4580
+
4581
+ def test_case_in_42_2
4582
+ rb = "case :a\nin A(*list) then nil\nend"
4583
+ pt = s(:case, s(:lit, :a).line(1),
4584
+ s(:in,
4585
+ s(:array_pat,
4586
+ s(:const, :A).line(2),
4587
+ :"*list").line(2),
4588
+ s(:nil).line(2)).line(2),
4589
+ nil).line(1)
4590
+
4591
+ assert_parse rb, pt
4592
+ end
4593
+
4594
+ def test_case_in_42_3
4595
+ assert_case_in ":b, *_, :c", s(:array_pat, nil,
4596
+ s(:lit, :b).line(2),
4597
+ :"*_",
4598
+ s(:lit, :c).line(2)).line(2)
4599
+ end
4600
+
4601
+
4602
+ def test_case_in_47
4603
+ rb = "case :a\nin [*, :b, :c]\n :d\nend"
4604
+ pt = s(:case, s(:lit, :a).line(1),
4605
+ s(:in,
4606
+ s(:array_pat, nil, :*,
4607
+ s(:lit, :b).line(2), s(:lit, :c).line(2)).line(2),
4608
+ s(:lit, :d).line(3)).line(2),
4609
+ nil).line(1)
4610
+
4611
+ assert_parse rb, pt
4612
+ end
4613
+
4614
+ def test_case_in_67
4615
+ rb = "case :a\nin 1.. then nil\nend"
4616
+ pt = s(:case,
4617
+ s(:lit, :a).line(1),
4618
+ s(:in, s(:dot2, s(:lit, 1).line(2), nil).line(2),
4619
+ s(:nil).line(2)).line(2),
4620
+ nil).line(1)
4621
+
4622
+ assert_parse rb, pt
4623
+ end
4624
+
4625
+ def test_case_in_76
4626
+ assert_case_in "`echo hi`", s(:xstr, "echo hi").line(2)
4627
+ end
4628
+
4629
+ def test_case_in_77
4630
+ assert_case_in "/regexp/", s(:lit, /regexp/).line(2)
4631
+ end
4632
+
4633
+ def test_case_in_78
4634
+ assert_case_in "%W[a b]", s(:array, s(:str, "a").line(2), s(:str, "b").line(2)).line(2)
4635
+ end
4636
+
4637
+ def test_case_in_79
4638
+ assert_case_in "%w[a b]", s(:array, s(:str, "a").line(2), s(:str, "b").line(2)).line(2)
4639
+ end
4640
+
4641
+ def test_case_in_80
4642
+ assert_case_in "%I[a b]", s(:array, s(:lit, :a).line(2), s(:lit, :b).line(2)).line(2)
4643
+ end
4644
+
4645
+ def test_case_in_81
4646
+ assert_case_in "%i[a b]", s(:array, s(:lit, :a).line(2), s(:lit, :b).line(2)).line(2)
4647
+ end
4648
+
4649
+ def test_case_in_83
4650
+ rb = "[->(b) { true }, c]"
4651
+ pt = s(:array_pat, nil,
4652
+ s(:iter, s(:lambda).line(2), s(:args, :b).line(2),
4653
+ s(:true).line(2)).line(2),
4654
+ s(:lvar, :c).line(2)).line(2)
4655
+
4656
+ assert_case_in rb, pt
4657
+ end
4658
+
4659
+ def test_case_in_85
4660
+ rb = "[[:b, c], [:d, ^e]]"
4661
+ pt = s(:array_pat, nil,
4662
+ s(:array_pat, nil,
4663
+ s(:lit, :b).line(2),
4664
+ s(:lvar, :c).line(2)).line(2),
4665
+ s(:array_pat,
4666
+ nil,
4667
+ s(:lit, :d).line(2),
4668
+ s(:lvar, :e).line(2)).line(2),
4669
+ ).line(2)
4670
+
4671
+ assert_case_in rb, pt
4672
+ end
4673
+
4674
+ def test_case_in_86
4675
+ rb = "case [:a, :b]\nin ::NilClass, * then nil\nend"
4676
+ pt = s(:case,
4677
+ s(:array, s(:lit, :a).line(1), s(:lit, :b).line(1)).line(1),
4678
+ s(:in,
4679
+ s(:array_pat,
4680
+ nil,
4681
+ s(:colon3, :NilClass).line(2),
4682
+ :*).line(2),
4683
+ s(:nil).line(2)).line(2),
4684
+ nil).line(1)
4685
+
4686
+ assert_parse rb, pt
4687
+ end
4688
+
4689
+ def test_case_in_86_2
4690
+ rb = "case [:a, :b]\nin *, ::NilClass then nil\nend"
4691
+ pt = s(:case,
4692
+ s(:array, s(:lit, :a).line(1), s(:lit, :b).line(1)).line(1),
4693
+ s(:in,
4694
+ s(:array_pat,
4695
+ nil,
4696
+ :*,
4697
+ s(:colon3, :NilClass).line(2)).line(2),
4698
+ s(:nil).line(2)).line(2),
4699
+ nil).line(1)
4700
+
4701
+ assert_parse rb, pt
4702
+ end
4703
+
4704
+ def test_case_in_array_pat_const
4705
+ rb = "case :a\nin B[c]\n :d\nend"
4706
+ pt = s(:case, s(:lit, :a).line(1),
4707
+ s(:in,
4708
+ s(:array_pat,
4709
+ s(:const, :B).line(2),
4710
+ s(:lvar, :c).line(2)).line(2),
4711
+ s(:lit, :d).line(3)).line(2),
4712
+ nil).line(1)
4713
+
4714
+ assert_parse rb, pt
4715
+ end
4716
+
4717
+ def test_case_in_array_pat_const2
4718
+ rb = "case :a\nin B::C[d]\n :e\nend"
4719
+ pt = s(:case, s(:lit, :a).line(1),
4720
+ s(:in,
4721
+ s(:array_pat,
4722
+ s(:const, s(:colon2, s(:const, :B).line(2), :C).line(2)).line(2),
4723
+ s(:lvar, :d).line(2)).line(2),
4724
+ s(:lit, :e).line(3)).line(2),
4725
+ nil).line(1)
4726
+
4727
+ assert_parse rb, pt
4728
+ end
4729
+
4730
+ def test_case_in_array_pat_paren_assign
4731
+ rb = "case :a\nin B(C => d)\n :d\nend"
4732
+ pt = s(:case, s(:lit, :a).line(1),
4733
+ s(:in,
4734
+ s(:array_pat,
4735
+ s(:const, :B).line(2),
4736
+ s(:lasgn, :d, s(:const, :C).line(2)).line(2)).line(2),
4737
+ s(:lit, :d).line(3)).line(2),
4738
+ nil).line(1)
4739
+
4740
+ assert_parse rb, pt
4741
+ end
4742
+
4743
+ def test_case_in_const
4744
+ rb = "case Array\nin Class\n :b\nend"
4745
+ pt = s(:case, s(:const, :Array).line(1),
4746
+ s(:in, s(:const, :Class).line(2),
4747
+ s(:lit, :b).line(3)).line(2),
4748
+ nil).line 1
4749
+
4750
+ assert_parse rb, pt
4751
+ end
4752
+
4753
+ def test_case_in_else
4754
+ rb = "case Array\nin Class\n :b\nelse\n :c\nend\n"
4755
+ pt = s(:case, s(:const, :Array).line(1),
4756
+ s(:in, s(:const, :Class).line(2),
4757
+ s(:lit, :b).line(3)).line(2),
4758
+ s(:lit, :c).line(5)).line 1
4759
+
4760
+ assert_parse rb, pt
4761
+ end
4762
+
4763
+ def test_case_in_hash_pat
4764
+ rb = "case :a\nin { b: 'c', d: \"e\" } then\n :f\nend\n"
4765
+ pt = s(:case, s(:lit, :a).line(1),
4766
+ s(:in,
4767
+ s(:hash_pat,
4768
+ nil,
4769
+ s(:lit, :b).line(2), s(:str, "c").line(2),
4770
+ s(:lit, :d).line(2), s(:str, "e").line(2)).line(2),
4771
+ s(:lit, :f).line(3)
4772
+ ).line(2),
4773
+ nil).line(1)
4774
+
4775
+ assert_parse rb, pt
4776
+ end
4777
+
4778
+ def test_case_in_hash_pat_assign
4779
+ rb = "case :a\nin { b: Integer => x, d: \"e\", f: } then\n :g\nend"
4780
+ pt = s(:case, s(:lit, :a).line(1),
4781
+ s(:in,
4782
+ s(:hash_pat,
4783
+ nil,
4784
+ s(:lit, :b).line(2), # =>
4785
+ s(:lasgn, :x, s(:const, :Integer).line(2)).line(2),
4786
+ s(:lit, :d).line(2), s(:str, "e").line(2),
4787
+ s(:lit, :f).line(2), nil).line(2),
4788
+ s(:lit, :g).line(3)).line(2),
4789
+ nil).line(1)
4790
+
4791
+ assert_parse rb, pt
4792
+ end
4793
+
4794
+ def test_case_in_hash_pat_paren_assign
4795
+ rb = "case :a\nin B(a: 42)\n :d\nend"
4796
+ pt = s(:case, s(:lit, :a).line(1),
4797
+ s(:in,
4798
+ s(:hash_pat,
4799
+ s(:const, :B).line(2),
4800
+ s(:lit, :a).line(2), s(:lit, 42).line(2)).line(2),
4801
+ s(:lit, :d).line(3)).line(2),
4802
+ nil).line(1)
4803
+
4804
+ assert_parse rb, pt
4805
+ end
4806
+
4807
+ def test_case_in_hash_pat_paren_true
4808
+ rb = "case :a\nin b: true then\n :c\nend\n"
4809
+ pt = s(:case, s(:lit, :a).line(1),
4810
+ s(:in,
4811
+ s(:hash_pat,
4812
+ nil,
4813
+ s(:lit, :b).line(2), s(:true).line(2)).line(2),
4814
+ s(:lit, :c).line(3)).line(2),
4815
+ nil).line(1)
4816
+
4817
+ assert_parse rb, pt
4818
+ end
4819
+
4820
+ def test_case_in_hash_pat_rest
4821
+ rb = "case :a\nin b: c, **rest then :d\nend"
4822
+ pt = s(:case,
4823
+ s(:lit, :a).line(1),
4824
+ s(:in,
4825
+ s(:hash_pat,
4826
+ nil,
4827
+ s(:lit, :b).line(2),
4828
+ s(:lvar, :c).line(2),
4829
+ s(:kwrest, :"**rest").line(2)).line(2),
4830
+ s(:lit, :d).line(2)).line(2),
4831
+ nil).line(1)
4832
+
4833
+ assert_parse rb, pt
4834
+ end
4835
+
4836
+ def test_case_in_hash_pat_rest_solo
4837
+ rb = "case :a\nin **rest then :d\nend"
4838
+ pt = s(:case,
4839
+ s(:lit, :a).line(1),
4840
+ s(:in,
4841
+ s(:hash_pat,
4842
+ nil,
4843
+ s(:kwrest, :"**rest").line(2)).line(2),
4844
+ s(:lit, :d).line(2)).line(2),
4845
+ nil).line(1)
4846
+
4847
+ assert_parse rb, pt
4848
+ end
4849
+
4850
+ def test_case_in_if_unless_post_mod
4851
+ rb = "case :a\nin A if true\n :C\nin D unless false\n :E\nend"
4852
+ pt = s(:case,
4853
+ s(:lit, :a).line(1),
4854
+ s(:in,
4855
+ s(:if, s(:true).line(2), s(:const, :A).line(2), nil).line(2),
4856
+ s(:lit, :C).line(3)).line(2),
4857
+ s(:in,
4858
+ s(:if, s(:false).line(4), nil, s(:const, :D).line(4)).line(4),
4859
+ s(:lit, :E).line(5)).line(4),
4860
+ nil).line(1)
4861
+
4862
+ assert_parse rb, pt
4863
+ end
4864
+
4865
+ def test_case_in_multiple
4866
+ rb = "case :a\nin A::B\n :C\nin D::E\n :F\nend"
4867
+ pt = s(:case,
4868
+ s(:lit, :a).line(1),
4869
+ s(:in,
4870
+ s(:const, s(:colon2, s(:const, :A).line(2), :B).line(2)).line(2),
4871
+ s(:lit, :C).line(3)).line(2),
4872
+ s(:in,
4873
+ s(:const, s(:colon2, s(:const, :D).line(4), :E).line(4)).line(4),
4874
+ s(:lit, :F).line(5)).line(4),
4875
+ nil).line(1)
4876
+
4877
+ assert_parse rb, pt
4878
+ end
4879
+
4880
+ def test_case_in_or
4881
+ rb = "case :a\nin B | C\n :d\nend\n"
4882
+ pt = s(:case, s(:lit, :a).line(1),
4883
+ s(:in,
4884
+ s(:or,
4885
+ s(:const, :B).line(2),
4886
+ s(:const, :C).line(2)).line(2),
4887
+ s(:lit, :d).line(3)).line(2),
4888
+ nil).line(1)
4889
+
4890
+ assert_parse rb, pt
4891
+ end
4892
+
4893
+ def test_in_expr_no_case
4894
+ rb = "'woot' in String"
4895
+ pt = s(:case, s(:str, "woot").line(1),
4896
+ s(:in, s(:const, :String).line(1),
4897
+ nil).line(1),
4898
+ nil).line(1)
4899
+
4900
+ assert_parse rb, pt
4901
+ end
4902
+
4903
+ def test_parse_pattern_019
4904
+ rb = <<~RUBY
4905
+ case 0
4906
+ in -1..1
4907
+ true
4908
+ end
4909
+ RUBY
4910
+
4911
+ pt = s(:case,
4912
+ s(:lit, 0).line(1),
4913
+ s(:in, s(:dot2, s(:lit, -1).line(2), s(:lit, 1).line(2)).line(2),
4914
+ s(:true).line(3)).line(2),
4915
+ nil).line(1)
4916
+
4917
+ assert_parse rb, pt
4918
+ end
4919
+
4920
+ def test_parse_pattern_044
4921
+ rb = <<~RUBY
4922
+ case obj
4923
+ in Object[]
4924
+ true
4925
+ end
4926
+ RUBY
4927
+ pt = s(:case,
4928
+ s(:call, nil, :obj).line(1),
4929
+ s(:in, s(:array_pat, s(:const, :Object).line(2)).line(2),
4930
+ s(:true).line(3)).line(2),
4931
+ nil).line(1)
4932
+
4933
+ assert_parse rb, pt
4934
+ end
4935
+
4936
+ def test_parse_pattern_051
4937
+ rb = <<~RUBY
4938
+ case [0, 1, 2]
4939
+ in [0, 1,]
4940
+ true
4941
+ end
4942
+ RUBY
4943
+ pt = s(:case,
4944
+ s(:array,
4945
+ s(:lit, 0).line(1),
4946
+ s(:lit, 1).line(1),
4947
+ s(:lit, 2).line(1)).line(1),
4948
+ s(:in,
4949
+ s(:array_pat,
4950
+ nil,
4951
+ s(:lit, 0).line(2),
4952
+ s(:lit, 1).line(2),
4953
+ :*).line(666),
4954
+ s(:true).line(3)).line(2),
4955
+ nil).line(1)
4956
+
4957
+ assert_parse rb, pt
4958
+ end
4959
+
4960
+ def test_parse_pattern_058
4961
+ rb = <<~RUBY
4962
+ case {a: 0}
4963
+ in {a:, **rest}
4964
+ [a, rest]
4965
+ end
4966
+ RUBY
4967
+ pt = s(:case,
4968
+ s(:hash,
4969
+ s(:lit, :a).line(1),
4970
+ s(:lit, 0).line(1)).line(1),
4971
+ s(:in,
4972
+ s(:hash_pat, nil, s(:lit, :a).line(2), nil,
4973
+ s(:kwrest, :"**rest").line(2)).line(2),
4974
+ s(:array,
4975
+ s(:lvar, :a).line(3),
4976
+ s(:lvar, :rest).line(3)).line(3)).line(2),
4977
+ nil).line(1)
4978
+
4979
+ assert_parse rb, pt
4980
+ end
4981
+
4982
+ def test_parse_pattern_058_2
4983
+ rb = <<~RUBY
4984
+ case {a: 0}
4985
+ in {a:, **}
4986
+ [a]
4987
+ end
4988
+ RUBY
4989
+ pt = s(:case,
4990
+ s(:hash,
4991
+ s(:lit, :a).line(1),
4992
+ s(:lit, 0).line(1)).line(1),
4993
+ s(:in,
4994
+ s(:hash_pat, nil, s(:lit, :a).line(2), nil,
4995
+ s(:kwrest, :"**").line(2)).line(2),
4996
+ s(:array,
4997
+ s(:lvar, :a).line(3)).line(3)).line(2),
4998
+ nil).line(1)
4999
+
5000
+ assert_parse rb, pt
5001
+ end
5002
+
5003
+ def test_parse_pattern_069
5004
+ rb = <<~RUBY
5005
+ case :a
5006
+ in Object[b: 1]
5007
+ 1
5008
+ end
5009
+ RUBY
5010
+ pt = s(:case,
5011
+ s(:lit, :a).line(1),
5012
+ s(:in,
5013
+ s(:hash_pat, s(:const, :Object).line(2),
5014
+ s(:lit, :b).line(2), s(:lit, 1).line(2)).line(2),
5015
+ s(:lit, 1).line(3)).line(2),
5016
+ nil).line(1)
5017
+
5018
+
5019
+ assert_parse rb, pt
5020
+ end
5021
+
5022
+ def test_parse_pattern_076
5023
+ rb = <<~RUBY
5024
+ case {a: 1}
5025
+ in {a: 1, **nil}
5026
+ true
5027
+ end
5028
+ RUBY
5029
+ pt = s(:case,
5030
+ s(:hash, s(:lit, :a).line(1), s(:lit, 1).line(1)).line(1),
5031
+ s(:in,
5032
+ s(:hash_pat, nil,
5033
+ s(:lit, :a).line(2), s(:lit, 1).line(2),
5034
+ s(:kwrest, :"**nil").line(2)).line(2),
5035
+ s(:true).line(3)).line(2),
5036
+ nil).line(1)
5037
+
5038
+ assert_parse rb, pt
5039
+ end
5040
+
5041
+ # def test_case_in_TEMPLATE
5042
+ # rb = "case :a\nin XXX then\n YYY\nend\n"
5043
+ # pt = s(:case, s(:lit, :a).line(1),
5044
+ # s(:in,
5045
+ # ZZZ,
5046
+ # WWW).line(2),
5047
+ # nil).line(1)
5048
+ #
5049
+ # assert_parse rb, pt
5050
+ # end
5051
+ end
5052
+
5053
+ module TestPatternMatching30
5054
+ def test_case_in_20
5055
+ assert_case_in("Symbol(*lhs, x, *rhs)",
5056
+ s(:find_pat,
5057
+ s(:const, :Symbol).line(2),
5058
+ :"*lhs",
5059
+ s(:array_pat, s(:lvar, :x).line(2)).line(2),
5060
+ :"*rhs").line(2))
5061
+ end
5062
+
5063
+ def test_case_in_22
5064
+ assert_case_in("Symbol[*lhs, x, *rhs]",
5065
+ s(:find_pat, s(:const, :Symbol).line(2),
5066
+ :"*lhs",
5067
+ s(:array_pat, s(:lvar, :x).line(2)).line(2),
5068
+ :"*rhs").line(2))
5069
+ end
5070
+ end
5071
+
5072
+ module TestRubyParserShared27Plus
5073
+ include TestRubyParserShared26Plus
5074
+ include TestPatternMatching
5075
+
5076
+ def test_block_args_kwargs
5077
+ rb = "f { |**kwargs| kwargs }"
5078
+ pt = s(:iter,
5079
+ s(:call, nil, :f),
5080
+ s(:args, :"**kwargs"),
5081
+ s(:lvar, :kwargs))
5082
+
5083
+ assert_parse rb, pt
5084
+ end
5085
+
5086
+ def test_block_args_no_kwargs
5087
+ rb = "f { |**nil| }"
5088
+ pt = s(:iter,
5089
+ s(:call, nil, :f),
5090
+ s(:args, :"**nil"))
5091
+
5092
+ assert_parse_line rb, pt, 1
5093
+ end
5094
+
5095
+ def test_defn_forward_args
5096
+ rb = "def a(...); b(...); end"
5097
+ pt = s(:defn, :a, s(:args, s(:forward_args)),
5098
+ s(:call, nil, :b, s(:forward_args)))
5099
+
5100
+ assert_parse_line rb, pt, 1
5101
+ end
5102
+
5103
+ def test_defn_arg_forward_args
5104
+ rb = "def a(x, ...); b(x, ...); end"
5105
+ pt = s(:defn, :a, s(:args, :x, s(:forward_args)),
5106
+ s(:call, nil, :b, s(:lvar, :x), s(:forward_args)))
5107
+
5108
+ assert_parse_line rb, pt, 1
5109
+ end
5110
+
5111
+ def test_defn_args_forward_args
5112
+ rb = "def a(x, y, z, ...); b(:get, z, ...); end"
5113
+ pt = s(:defn, :a, s(:args, :x, :y, :z, s(:forward_args)),
5114
+ s(:call, nil, :b, s(:lit, :get), s(:lvar, :z),
5115
+ s(:forward_args)))
5116
+
5117
+ assert_parse_line rb, pt, 1
5118
+ end
5119
+
5120
+ def test_defn_no_kwargs
5121
+ # def x(**nil)
5122
+ # end
5123
+ #
5124
+ # def y(**kw)
5125
+ # end
5126
+ #
5127
+ # def z()
5128
+ # end
5129
+ #
5130
+ # x arg: 42 # $!: no keywords accepted (ArgumentError)
5131
+ # y arg: 42 # fine
5132
+ # z arg: 42 # $!: wrong number of arguments (given 1, expected 0) (ArgumentError)
5133
+
5134
+ rb = "def x(**nil); end"
5135
+ pt = s(:defn, :x, s(:args, :"**nil").line(1),
5136
+ s(:nil).line(1)).line(1)
5137
+
5138
+ assert_parse_line rb, pt, 1
5139
+ end
5140
+
5141
+ def test_call_forward_args_outside_method_definition
5142
+ rb = "b(...)"
5143
+
5144
+ assert_syntax_error rb, "Unexpected ..."
5145
+ end
5146
+
5147
+ def test_call_arg_forward_args_outside_method_definition
5148
+ rb = "b(x, ...)"
5149
+
5150
+ assert_syntax_error rb, "Unexpected ..."
5151
+ end
5152
+
5153
+ def test_mlhs_rescue
5154
+ # same:
5155
+ # a = (24 rescue 42)
5156
+ # a = 24 rescue 42
5157
+
5158
+ # same:
5159
+ # a, b = (f rescue 42)
5160
+ # a, b = f rescue 42
5161
+
5162
+ rb = "a, b = f rescue 42"
5163
+ pt = s(:masgn,
5164
+ s(:array, s(:lasgn, :a), s(:lasgn, :b)),
5165
+ s(:to_ary,
5166
+ s(:rescue,
5167
+ s(:call, nil, :f),
5168
+ s(:resbody, s(:array),
5169
+ s(:lit, 42)))))
5170
+
5171
+ assert_parse rb, pt
5172
+ end
5173
+ end
5174
+
5175
+ module TestRubyParserShared30Plus
5176
+ include TestRubyParserShared27Plus
5177
+ include TestPatternMatching30
5178
+
5179
+ def test_rhs_asgn
5180
+ rb = "42 => n"
5181
+ pt = s(:case,
5182
+ s(:lit, 42).line(1),
5183
+ s(:in, s(:lvar, :n).line(1), nil).line(1), nil).line(1)
5184
+
5185
+ assert_parse rb, pt
5186
+ end
5187
+
5188
+ def test_case_in_find
5189
+ rb = "case :a\n in *a, :+, *b\nend"
5190
+ pt = s(:case,
5191
+ s(:lit, :a).line(1),
5192
+ s(:in,
5193
+ s(:find_pat, nil,
5194
+ :"*a",
5195
+ s(:array_pat, s(:lit, :+).line(2)).line(2),
5196
+ :"*b").line(2),
5197
+ nil).line(2),
5198
+ nil).line(1)
5199
+
5200
+ assert_parse rb, pt
5201
+ end
5202
+
5203
+ def test_case_in_find_array
5204
+ rb = "case :a\nin [*, :b, c, *]\nend"
5205
+ pt = s(:case,
5206
+ s(:lit, :a).line(1),
5207
+ s(:in,
5208
+ s(:find_pat, nil,
5209
+ :*,
5210
+ s(:array_pat, s(:lit, :b).line(2), s(:lvar, :c).line(2)).line(2),
5211
+ :*).line(2),
5212
+ nil).line(2),
5213
+ nil).line(1)
5214
+
5215
+ assert_parse rb, pt
5216
+ end
5217
+
5218
+ def test_defn_oneliner
5219
+ rb = "def exec(cmd) = system(cmd)"
5220
+ pt = s(:defn, :exec, s(:args, :cmd).line(1),
5221
+ s(:call, nil, :system, s(:lvar, :cmd).line(1)).line(1)).line(1)
5222
+
5223
+ assert_parse rb, pt
5224
+ end
5225
+
5226
+ def test_defn_oneliner_rescue
5227
+ rb = "def exec(cmd)\n system(cmd)\nrescue\n nil\nend\n"
5228
+ pt = s(:defn, :exec, s(:args, :cmd),
5229
+ s(:rescue,
5230
+ s(:call, nil, :system, s(:lvar, :cmd)),
5231
+ s(:resbody, s(:array), s(:nil))))
5232
+ assert_parse rb, pt
5233
+
5234
+ rb = "def exec(cmd)\n system(cmd) rescue nil\nend\n"
5235
+ assert_parse rb, pt
5236
+
5237
+ rb = "def exec(cmd) = system(cmd) rescue nil"
5238
+ assert_parse rb, pt
5239
+ end
5240
+
5241
+ def test_defs_oneliner
5242
+ rb = "def self.exec(cmd) = system(cmd)"
5243
+ pt = s(:defs,
5244
+ s(:self).line(1),
5245
+ :exec,
5246
+ s(:args, :cmd).line(1),
5247
+ s(:call, nil, :system, s(:lvar, :cmd).line(1)).line(1)).line(1)
5248
+
5249
+ assert_parse rb, pt
5250
+ end
5251
+
5252
+ def test_defs_oneliner_rescue
5253
+ rb = "def self.exec(cmd)\n system(cmd)\nrescue\n nil\nend\n"
5254
+ pt = s(:defs, s(:self), :exec, s(:args, :cmd),
5255
+ s(:rescue,
5256
+ s(:call, nil, :system, s(:lvar, :cmd)),
5257
+ s(:resbody, s(:array), s(:nil))))
5258
+ assert_parse rb, pt
5259
+
5260
+ rb = "def self.exec(cmd)\n system(cmd) rescue nil\nend\n"
5261
+ assert_parse rb, pt
5262
+
5263
+ rb = "def self.exec(cmd) = system(cmd) rescue nil"
5264
+ assert_parse rb, pt
5265
+ end
5266
+
5267
+ def test_defn_oneliner_setter
5268
+ rb = "class X\n def x=(o) = 42\nend"
5269
+
5270
+ assert_syntax_error rb, /setter method cannot be defined/
5271
+ end
5272
+
5273
+ def test_defs_oneliner_setter
5274
+ rb = "class X\n def self.x= = 42\nend"
5275
+
5276
+ assert_syntax_error rb, /setter method cannot be defined/
5277
+ end
5278
+ end
5279
+
5280
+ class Minitest::Test
5281
+ def skip s = "blah"
5282
+ warn "ignoring skip for %s: %s" % [name, s]
5283
+ end
5284
+ end if ENV["NOSKIP"]
5285
+
5286
+ class TestRubyParser < Minitest::Test
5287
+ def test_cls_version
5288
+ assert_equal 23, RubyParser::V23.version
5289
+ assert_equal 24, RubyParser::V24.version
5290
+ assert_equal 24, Ruby24Parser.version
5291
+ refute RubyParser::Parser.version
5292
+ end
5293
+
5294
+ def test_parse
5295
+ processor = RubyParser.new
5296
+
5297
+ rb = "a.()"
5298
+ pt = s(:call, s(:call, nil, :a), :call)
5299
+
5300
+ assert_equal pt, processor.parse(rb)
5301
+
5302
+ # bad syntax
5303
+ e = assert_raises Racc::ParseError do
5304
+ capture_io do
5305
+ processor.parse "a.("
5306
+ end
5307
+ end
5308
+
5309
+ assert_includes e.message, 'parse error on value "$" ($end)'
5310
+ end
5311
+
5312
+ def test_parse_error_from_first
5313
+ processor = RubyParser.new
5314
+
5315
+ e = assert_raises Racc::ParseError do
5316
+ capture_io do
5317
+ processor.parse "a -> () {"
5318
+ end
5319
+ end
5320
+
5321
+ # This is a 2.x error, will fail on 1.8/1.9.
5322
+ assert_includes e.message, 'parse error on value "$" ($end)'
5323
+ end
5324
+ end
5325
+
5326
+ class RubyParserTestCase < ParseTreeTestCase
5327
+ attr_accessor :result, :processor
5328
+
5329
+ make_my_diffs_pretty!
5330
+
5331
+ def self.previous key
5332
+ "Ruby"
4186
5333
  end
4187
5334
 
4188
5335
  def self.generate_test klass, node, data, input_name, output_name
@@ -4195,7 +5342,14 @@ class RubyParserTestCase < ParseTreeTestCase
4195
5342
  end
4196
5343
 
4197
5344
  def assert_parse rb, pt
4198
- self.result = processor.parse rb
5345
+ timeout = (ENV["RP_TIMEOUT"] || 10).to_i
5346
+
5347
+ if ENV["RP_LINES"] then # TODO: make default once tests cleaned up
5348
+ pt.deep_each { |s| s.line ||= 1 }
5349
+ pt.line ||= 1
5350
+ end
5351
+
5352
+ self.result = processor.parse rb, "(string)", timeout
4199
5353
  assert_equal pt, result
4200
5354
  end
4201
5355
 
@@ -4224,15 +5378,20 @@ class RubyParserTestCase < ParseTreeTestCase
4224
5378
  ENV["VERBOSE"] = old_env
4225
5379
  end
4226
5380
 
4227
- def assert_syntax_error rb, emsg
5381
+ def assert_syntax_error rb, emsg, klass = RubyParser::SyntaxError
4228
5382
  e = nil
4229
5383
  assert_silent do
4230
- e = assert_raises RubyParser::SyntaxError do
5384
+ e = assert_raises klass do
4231
5385
  processor.parse rb
4232
5386
  end
4233
5387
  end
4234
5388
 
4235
- assert_equal emsg, e.message
5389
+ case emsg
5390
+ when String
5391
+ assert_equal emsg, e.message
5392
+ else
5393
+ assert_match emsg, e.message
5394
+ end
4236
5395
  end
4237
5396
 
4238
5397
  def refute_parse rb
@@ -4249,17 +5408,6 @@ class TestRubyParserV20 < RubyParserTestCase
4249
5408
 
4250
5409
  self.processor = RubyParser::V20.new
4251
5410
  end
4252
-
4253
- def test_bug162__20
4254
- skip "not ready for this yet"
4255
-
4256
- # Ignore everything after \r in heredoc marker in <= 2.0 #162
4257
-
4258
- rb = %q(<<E\nfoo\nE\rO)
4259
- pt = s(:str, "foo\n")
4260
-
4261
- assert_parse rb, pt
4262
- end
4263
5411
  end
4264
5412
 
4265
5413
  class TestRubyParserV21 < RubyParserTestCase
@@ -4318,7 +5466,7 @@ class TestRubyParserV24 < RubyParserTestCase
4318
5466
 
4319
5467
  assert_parse rb, pt
4320
5468
 
4321
- assert_parse_error "a(b rescue c)", /parse error on value ..rescue/
5469
+ assert_parse_error "a(b rescue c)", /parse error on value .rescue/
4322
5470
  end
4323
5471
  end
4324
5472
 
@@ -4429,10 +5577,11 @@ class TestRubyParserV26 < RubyParserTestCase
4429
5577
 
4430
5578
  assert_parse_line rb, pt, 1
4431
5579
  end
4432
-
4433
5580
  end
4434
5581
 
4435
5582
  class TestRubyParserV27 < RubyParserTestCase
5583
+ make_my_diffs_pretty!
5584
+
4436
5585
  include TestRubyParserShared27Plus
4437
5586
 
4438
5587
  def setup
@@ -4440,8 +5589,37 @@ class TestRubyParserV27 < RubyParserTestCase
4440
5589
 
4441
5590
  self.processor = RubyParser::V27.new
4442
5591
  end
5592
+
5593
+ def test_bdot2
5594
+ rb = "..10\n; ..a\n; c"
5595
+ pt = s(:block,
5596
+ s(:dot2, nil, s(:lit, 10).line(1)).line(1),
5597
+ s(:dot2, nil, s(:call, nil, :a).line(2)).line(2),
5598
+ s(:call, nil, :c).line(3)).line(1)
5599
+
5600
+ assert_parse_line rb, pt, 1
5601
+ end
5602
+
5603
+ def test_bdot3
5604
+ rb = "...10\n; ...a\n; c"
5605
+ pt = s(:block,
5606
+ s(:dot3, nil, s(:lit, 10).line(1)).line(1),
5607
+ s(:dot3, nil, s(:call, nil, :a).line(2)).line(2),
5608
+ s(:call, nil, :c).line(3)).line(1)
5609
+
5610
+ assert_parse_line rb, pt, 1
5611
+ end
4443
5612
  end
4444
5613
 
5614
+ class TestRubyParserV30 < RubyParserTestCase
5615
+ include TestRubyParserShared30Plus
5616
+
5617
+ def setup
5618
+ super
5619
+
5620
+ self.processor = RubyParser::V30.new
5621
+ end
5622
+ end
4445
5623
 
4446
5624
  RubyParser::VERSIONS.each do |klass|
4447
5625
  v = klass.version