ruby_parser 3.14.2 → 3.17.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  # encoding: ASCII-8BIT
2
+ # TODO: remove
2
3
 
3
4
  require "sexp"
4
5
  require "ruby_lexer"
@@ -28,7 +29,7 @@ class Sexp
28
29
  end
29
30
 
30
31
  module RubyParserStuff
31
- VERSION = "3.14.2"
32
+ VERSION = "3.16.0"
32
33
 
33
34
  attr_accessor :lexer, :in_def, :in_single, :file
34
35
  attr_accessor :in_kwarg
@@ -45,6 +46,11 @@ module RubyParserStuff
45
46
 
46
47
  attr_accessor :canonicalize_conditions
47
48
 
49
+ ##
50
+ # The last token type returned from #next_token
51
+
52
+ attr_accessor :last_token_type
53
+
48
54
  $good20 = []
49
55
 
50
56
  %w[
@@ -109,7 +115,7 @@ module RubyParserStuff
109
115
  def initialize(options = {})
110
116
  super()
111
117
 
112
- v = self.class.name[/2\d/]
118
+ v = self.class.name[/[23]\d/]
113
119
  raise "Bad Class name #{self.class}" unless v
114
120
 
115
121
  self.lexer = RubyLexer.new v && v.to_i
@@ -154,6 +160,12 @@ module RubyParserStuff
154
160
  case arg.sexp_type
155
161
  when :args, :block, :array, :call_args then # HACK call_args mismatch
156
162
  result.concat arg.sexp_body
163
+ when :forward_args then
164
+ self.env[:*] = :lvar # TODO: arg_var(p, idFWD_REST) ?
165
+ self.env[:**] = :lvar
166
+ self.env[:&] = :lvar
167
+
168
+ result << arg
157
169
  when :block_arg then
158
170
  result << :"&#{arg.last}"
159
171
  when :shadow then
@@ -305,7 +317,7 @@ module RubyParserStuff
305
317
  end
306
318
  when Symbol then
307
319
  result << arg
308
- when ",", nil then
320
+ when ",", nil, "(" then
309
321
  # ignore
310
322
  else
311
323
  raise "unhandled: #{arg.inspect} in #{args.inspect}"
@@ -493,6 +505,8 @@ module RubyParserStuff
493
505
  str.encode! Encoding::UTF_8
494
506
  break
495
507
  end
508
+ rescue ArgumentError # unknown encoding name
509
+ # do nothing
496
510
  rescue Encoding::InvalidByteSequenceError
497
511
  # do nothing
498
512
  rescue Encoding::UndefinedConversionError
@@ -532,7 +546,7 @@ module RubyParserStuff
532
546
  header.map! { |s| s.force_encoding "ASCII-8BIT" } if has_enc
533
547
 
534
548
  first = header.first || ""
535
- encoding, str = "utf-8", str[3..-1] if first =~ /\A\xEF\xBB\xBF/
549
+ encoding, str = "utf-8", str.b[3..-1] if first =~ /\A\xEF\xBB\xBF/
536
550
 
537
551
  encoding = $1.strip if header.find { |s|
538
552
  s[/^#.*?-\*-.*?coding:\s*([^ ;]+).*?-\*-/, 1] ||
@@ -592,7 +606,9 @@ module RubyParserStuff
592
606
  case ttype
593
607
  when :str then
594
608
  if htype == :str
595
- head.last << tail.last
609
+ a, b = head.last, tail.last
610
+ b = b.dup.force_encoding a.encoding unless Encoding.compatible?(a, b)
611
+ a << b
596
612
  elsif htype == :dstr and head.size == 2 then
597
613
  head.last << tail.last
598
614
  else
@@ -696,6 +712,15 @@ module RubyParserStuff
696
712
  result
697
713
  end
698
714
 
715
+ def new_begin val
716
+ _, lineno, body, _ = val
717
+
718
+ result = body ? s(:begin, body) : s(:nil)
719
+ result.line lineno
720
+
721
+ result
722
+ end
723
+
699
724
  def new_body val
700
725
  body, resbody, elsebody, ensurebody = val
701
726
 
@@ -723,7 +748,10 @@ module RubyParserStuff
723
748
  result = block_append(result, elsebody)
724
749
  end
725
750
 
726
- result = s(:ensure, result, ensurebody).compact.line result.line if ensurebody
751
+ if ensurebody
752
+ lineno = (result || ensurebody).line
753
+ result = s(:ensure, result, ensurebody).compact.line lineno
754
+ end
727
755
 
728
756
  result
729
757
  end
@@ -843,14 +871,17 @@ module RubyParserStuff
843
871
  end
844
872
 
845
873
  def new_defs val
846
- recv, (name, _line), args, body = val[1], val[4], val[6], val[7]
847
- line, _ = val[5]
874
+ _, recv, _, _, name, (_in_def, line), args, body, _ = val
875
+
848
876
  body ||= s(:nil).line line
849
877
 
850
878
  args.line line
851
879
 
852
880
  result = s(:defs, recv, name.to_sym, args)
853
881
 
882
+ # TODO: remove_begin
883
+ # TODO: reduce_nodes
884
+
854
885
  if body then
855
886
  if body.sexp_type == :block then
856
887
  result.push(*body.sexp_body)
@@ -875,7 +906,9 @@ module RubyParserStuff
875
906
  end
876
907
 
877
908
  def new_hash val
878
- s(:hash, *val[2].values).line(val[1])
909
+ _, line, assocs = val
910
+
911
+ s(:hash).line(line).concat assocs.values
879
912
  end
880
913
 
881
914
  def new_if c, t, f
@@ -1134,6 +1167,7 @@ module RubyParserStuff
1134
1167
  def new_string val
1135
1168
  str, = val
1136
1169
  str.force_encoding("UTF-8")
1170
+ # TODO: remove:
1137
1171
  str.force_encoding("ASCII-8BIT") unless str.valid_encoding?
1138
1172
  result = s(:str, str).line lexer.lineno
1139
1173
  self.lexer.fixup_lineno str.count("\n")
@@ -1228,20 +1262,23 @@ module RubyParserStuff
1228
1262
  result
1229
1263
  end
1230
1264
 
1231
- def new_xstring str
1232
- if str then
1233
- case str.sexp_type
1265
+ def new_xstring val
1266
+ _, node = val
1267
+
1268
+ node ||= s(:str, "").line lexer.lineno
1269
+
1270
+ if node then
1271
+ case node.sexp_type
1234
1272
  when :str
1235
- str.sexp_type = :xstr
1273
+ node.sexp_type = :xstr
1236
1274
  when :dstr
1237
- str.sexp_type = :dxstr
1275
+ node.sexp_type = :dxstr
1238
1276
  else
1239
- str = s(:dxstr, "", str).line str.line
1277
+ node = s(:dxstr, "", node).line node.line
1240
1278
  end
1241
- str
1242
- else
1243
- s(:xstr, "")
1244
1279
  end
1280
+
1281
+ node
1245
1282
  end
1246
1283
 
1247
1284
  def new_yield args = nil
@@ -1262,6 +1299,7 @@ module RubyParserStuff
1262
1299
  token = self.lexer.next_token
1263
1300
 
1264
1301
  if token and token.first != RubyLexer::EOF then
1302
+ self.last_token_type = token
1265
1303
  return token
1266
1304
  else
1267
1305
  return [false, false]
@@ -1320,6 +1358,7 @@ module RubyParserStuff
1320
1358
  self.in_single = 0
1321
1359
  self.env.reset
1322
1360
  self.comments.clear
1361
+ self.last_token_type = nil
1323
1362
  end
1324
1363
 
1325
1364
  def ret_args node
@@ -1,7 +1,3 @@
1
- # encoding: US-ASCII
2
-
3
- # TODO: work this out
4
-
5
1
  require "minitest/autorun"
6
2
  require "ruby_lexer"
7
3
  require "ruby_parser"
@@ -84,10 +80,12 @@ class TestRubyLexer < Minitest::Test
84
80
  assert_in_epsilon value, act_value, 0.001, msg
85
81
  when NilClass then
86
82
  assert_nil act_value, msg
83
+ when String then
84
+ assert_equal value, act_value.b.force_encoding(value.encoding), msg
87
85
  else
88
86
  assert_equal value, act_value, msg
89
87
  end
90
- assert_equal state, @lex.lex_state, msg if state
88
+ assert_match state, @lex.lex_state, msg if state
91
89
  assert_equal paren, @lex.paren_nest, msg if paren
92
90
  assert_equal brace, @lex.brace_nest, msg if brace
93
91
  end
@@ -98,7 +96,8 @@ class TestRubyLexer < Minitest::Test
98
96
 
99
97
  def assert_read_escape expected, input
100
98
  @lex.ss.string = input.dup
101
- assert_equal expected, @lex.read_escape.b, input
99
+ enc = expected.encoding
100
+ assert_equal expected, @lex.read_escape.b.force_encoding(enc), input
102
101
  end
103
102
 
104
103
  def assert_read_escape_bad input # TODO: rename refute_read_escape
@@ -146,7 +145,7 @@ class TestRubyLexer < Minitest::Test
146
145
  yield
147
146
 
148
147
  lexer.lex_state = EXPR_ENDARG
149
- assert_next_lexeme :tSTRING_DEND, "}", EXPR_END, 0
148
+ assert_next_lexeme :tSTRING_DEND, "}", EXPR_END|EXPR_ENDARG, 0
150
149
 
151
150
  lexer.lex_strterm = lex_strterm
152
151
  lexer.lex_state = EXPR_BEG
@@ -479,6 +478,22 @@ class TestRubyLexer < Minitest::Test
479
478
  assert_lex3("!~", nil, :tNMATCH, "!~", EXPR_BEG)
480
479
  end
481
480
 
481
+ def test_yylex_bdot2
482
+ assert_lex3("..42",
483
+ nil, # TODO: s(:dot2, nil, s(:lit, 42)),
484
+
485
+ :tBDOT2, "..", EXPR_BEG,
486
+ :tINTEGER, 42, EXPR_END|EXPR_ENDARG)
487
+ end
488
+
489
+ def test_yylex_bdot3
490
+ assert_lex3("...42",
491
+ nil, # TODO: s(:dot2, nil, s(:lit, 42)),
492
+
493
+ :tBDOT3, "...", EXPR_BEG,
494
+ :tINTEGER, 42, EXPR_END|EXPR_ENDARG)
495
+ end
496
+
482
497
  def test_yylex_block_bug_1
483
498
  assert_lex3("a do end",
484
499
  s(:iter, s(:call, nil, :a), 0),
@@ -720,7 +735,7 @@ class TestRubyLexer < Minitest::Test
720
735
 
721
736
  assert_lex3("do 42 end",
722
737
  nil,
723
- :kDO_BLOCK, "do", EXPR_BEG,
738
+ :kDO, "do", EXPR_BEG,
724
739
  :tINTEGER, 42, EXPR_NUM,
725
740
  :kEND, "end", EXPR_END)
726
741
  end
@@ -750,10 +765,26 @@ class TestRubyLexer < Minitest::Test
750
765
  end
751
766
 
752
767
  def test_yylex_dot2
768
+ assert_lex3("1..2",
769
+ s(:lit, 1..2),
770
+
771
+ :tINTEGER, 1, EXPR_END|EXPR_ENDARG,
772
+ :tDOT2, "..", EXPR_BEG,
773
+ :tINTEGER, 2, EXPR_END|EXPR_ENDARG)
774
+
775
+ self.lex_state = EXPR_END|EXPR_ENDARG
753
776
  assert_lex3("..", nil, :tDOT2, "..", EXPR_BEG)
754
777
  end
755
778
 
756
779
  def test_yylex_dot3
780
+ assert_lex3("1...2",
781
+ s(:lit, 1...2),
782
+
783
+ :tINTEGER, 1, EXPR_END|EXPR_ENDARG,
784
+ :tDOT3, "...", EXPR_BEG,
785
+ :tINTEGER, 2, EXPR_END|EXPR_ENDARG)
786
+
787
+ self.lex_state = EXPR_END|EXPR_ENDARG
757
788
  assert_lex3("...", nil, :tDOT3, "...", EXPR_BEG)
758
789
  end
759
790
 
@@ -926,6 +957,14 @@ class TestRubyLexer < Minitest::Test
926
957
  assert_lex3("$1234", nil, :tGVAR, "$1234", EXPR_END)
927
958
  end
928
959
 
960
+ def test_yylex_global_I_have_no_words
961
+ assert_lex3("$x\xE2\x80\x8B = 42", # zero width space?!?!?
962
+ nil,
963
+ :tGVAR, "$x\xE2\x80\x8B", EXPR_END,
964
+ :tEQL, "=", EXPR_BEG,
965
+ :tINTEGER, 42, EXPR_NUM)
966
+ end
967
+
929
968
  def test_yylex_global_other
930
969
  assert_lex3("[$~, $*, $$, $?, $!, $@, $/, $\\, $;, $,, $., $=, $:, $<, $>, $\"]",
931
970
  nil,
@@ -1109,11 +1148,11 @@ class TestRubyLexer < Minitest::Test
1109
1148
  :tEQL, "=", EXPR_BEG,
1110
1149
  :tSTRING_BEG, "\"", EXPR_BEG,
1111
1150
  :tSTRING_CONTENT, "#x a ", EXPR_BEG,
1112
- :tSTRING_DVAR, "\#@", EXPR_BEG,
1151
+ :tSTRING_DVAR, "#", EXPR_BEG,
1113
1152
  :tSTRING_CONTENT, "@a b ", EXPR_BEG, # HUH?
1114
- :tSTRING_DVAR, "\#$", EXPR_BEG,
1153
+ :tSTRING_DVAR, "#", EXPR_BEG,
1115
1154
  :tSTRING_CONTENT, "$b c ", EXPR_BEG, # HUH?
1116
- :tSTRING_DVAR, "\#@", EXPR_BEG,
1155
+ :tSTRING_DVAR, "#", EXPR_BEG,
1117
1156
  :tSTRING_CONTENT, "@@d ", EXPR_BEG, # HUH?
1118
1157
  :tSTRING_DBEG, "\#{", EXPR_BEG,
1119
1158
  :tSTRING_CONTENT, "3} \n", EXPR_BEG,
@@ -2099,6 +2138,10 @@ class TestRubyLexer < Minitest::Test
2099
2138
  assert_lex3("?\\M-\\C-a", nil, :tSTRING, "\M-\C-a", EXPR_END)
2100
2139
  end
2101
2140
 
2141
+ def test_yylex_question_control_escape
2142
+ assert_lex3('?\C-\]', nil, :tSTRING, ?\C-\], EXPR_END)
2143
+ end
2144
+
2102
2145
  def test_yylex_question_ws
2103
2146
  assert_lex3("? ", nil, :tEH, "?", EXPR_BEG)
2104
2147
  assert_lex3("?\n", nil, :tEH, "?", EXPR_BEG)
@@ -2549,11 +2592,7 @@ class TestRubyLexer < Minitest::Test
2549
2592
  end
2550
2593
 
2551
2594
  def test_yylex_string_double_escape_c_backslash
2552
- assert_lex3("\"\\c\\\"",
2553
- nil,
2554
- :tSTRING_BEG, "\"", EXPR_BEG,
2555
- :tSTRING_CONTENT, "\034", EXPR_BEG,
2556
- :tSTRING_END, "\"", EXPR_LIT)
2595
+ refute_lex("\"\\c\\\"", :tSTRING_BEG, '"')
2557
2596
  end
2558
2597
 
2559
2598
  def test_yylex_string_double_escape_c_escape
@@ -2847,6 +2886,15 @@ class TestRubyLexer < Minitest::Test
2847
2886
  :tSTRING_END, '"')
2848
2887
  end
2849
2888
 
2889
+ def test_yylex_string_utf8_bad_encoding_with_escapes
2890
+ str = "\"\\xBADπ\""
2891
+ exp = "\xBADπ".b
2892
+
2893
+ assert_lex(str,
2894
+ s(:str, exp),
2895
+ :tSTRING, exp, EXPR_END)
2896
+ end
2897
+
2850
2898
  def test_yylex_string_utf8_complex_trailing_hex
2851
2899
  chr = [0x3024].pack("U")
2852
2900
  str = "#{chr}abz"
@@ -185,6 +185,57 @@ module TestRubyParserShared
185
185
  assert_syntax_error rb, "else without rescue is useless"
186
186
  end
187
187
 
188
+ def test_begin_ensure_no_bodies
189
+ rb = "begin\nensure\nend"
190
+ pt = s(:ensure, s(:nil).line(2)).line(2)
191
+
192
+ assert_parse rb, pt
193
+ end
194
+
195
+ def test_begin_rescue_ensure_no_bodies
196
+ rb = "begin\nrescue\nensure\nend"
197
+ pt = s(:ensure,
198
+ s(:rescue,
199
+ s(:resbody, s(:array).line(2),
200
+ nil).line(2)
201
+ ).line(2),
202
+ s(:nil).line(3)
203
+ ).line(2)
204
+
205
+ assert_parse rb, pt
206
+ end
207
+
208
+ def test_begin_rescue_else_ensure_bodies
209
+ rb = "begin\n 1\nrescue\n 2\nelse\n 3\nensure\n 4\nend"
210
+ pt = s(:ensure,
211
+ s(:rescue,
212
+ s(:lit, 1).line(2),
213
+ s(:resbody, s(:array).line(3),
214
+ s(:lit, 2).line(4)).line(3),
215
+ s(:lit, 3).line(6)).line(2),
216
+ s(:lit, 4).line(8)).line(2)
217
+
218
+ s(:ensure, s(:rescue, s(:resbody, s(:array), nil)), s(:nil))
219
+
220
+ assert_parse rb, pt
221
+ end
222
+
223
+ def test_begin_rescue_else_ensure_no_bodies
224
+ rb = "begin\n\nrescue\n\nelse\n\nensure\n\nend"
225
+ pt = s(:ensure,
226
+ s(:rescue,
227
+ s(:resbody, s(:array).line(3),
228
+ # TODO: s(:nil)
229
+ nil
230
+ ).line(3),
231
+ ).line(3),
232
+ s(:nil).line(7)).line(3)
233
+
234
+ s(:ensure, s(:rescue, s(:resbody, s(:array), nil)), s(:nil))
235
+
236
+ assert_parse rb, pt
237
+ end
238
+
188
239
  def test_block_append
189
240
  head = s(:args).line 1
190
241
  tail = s(:zsuper).line 2
@@ -290,7 +341,7 @@ module TestRubyParserShared
290
341
  def test_bug190
291
342
  skip "not ready for this yet"
292
343
 
293
- rb = %{%r'\\''}
344
+ rb = %{%r'\\\''} # stupid emacs
294
345
 
295
346
  assert_parse rb, :FUCK
296
347
  assert_syntax_error rb, "FUCK"
@@ -872,6 +923,13 @@ module TestRubyParserShared
872
923
  assert_parse rb, pt
873
924
  end
874
925
 
926
+ def test_heredoc_with_extra_carriage_horrible_mix?
927
+ rb = "<<'eot'\r\nbody\r\neot\n"
928
+ pt = s(:str, "body\r\n")
929
+
930
+ assert_parse rb, pt
931
+ end
932
+
875
933
  def test_heredoc_with_interpolation_and_carriage_return_escapes
876
934
  rb = "<<EOS\nfoo\\r\#@bar\nEOS\n"
877
935
  pt = s(:dstr, "foo\r", s(:evstr, s(:ivar, :@bar)), s(:str, "\n"))
@@ -900,6 +958,13 @@ module TestRubyParserShared
900
958
  assert_parse rb, pt
901
959
  end
902
960
 
961
+ def test_heredoc_with_not_global_interpolation
962
+ rb = "<<-HEREDOC\n#${\nHEREDOC"
963
+ pt = s(:str, "\#${\n")
964
+
965
+ assert_parse rb, pt
966
+ end
967
+
903
968
  def test_i_fucking_hate_line_numbers
904
969
  rb = <<-END.gsub(/^ {6}/, "")
905
970
  if true
@@ -1252,6 +1317,20 @@ module TestRubyParserShared
1252
1317
  end
1253
1318
  end
1254
1319
 
1320
+ def test_magic_encoding_comment__bad
1321
+ rb = "#encoding: bunk\n0"
1322
+ pt = s(:lit, 0)
1323
+
1324
+ assert_parse rb, pt
1325
+ end
1326
+
1327
+ def test_utf8_bom
1328
+ rb = "\xEF\xBB\xBF#!/usr/bin/env ruby -w\np 0\n"
1329
+ pt = s(:call, nil, :p, s(:lit, 0))
1330
+
1331
+ assert_parse rb, pt
1332
+ end
1333
+
1255
1334
  def test_masgn_arg_colon_arg
1256
1335
  rb = "a, b::c = d"
1257
1336
  pt = s(:masgn,
@@ -1383,13 +1462,43 @@ module TestRubyParserShared
1383
1462
  assert_parse rb, pt
1384
1463
  end
1385
1464
 
1386
- def test_op_asgn_primary_colon_identifier
1465
+ def test_op_asgn_primary_colon_identifier1
1387
1466
  rb = "A::b += 1"
1388
1467
  pt = s(:op_asgn, s(:const, :A), s(:lit, 1), :b, :+) # TODO: check? looks wack
1389
1468
 
1390
1469
  assert_parse rb, pt
1391
1470
  end
1392
1471
 
1472
+ def test_lasgn_middle_splat
1473
+ rb = "a = b, *c, d"
1474
+ pt = s(:lasgn, :a,
1475
+ s(:svalue,
1476
+ s(:array,
1477
+ s(:call, nil, :b),
1478
+ s(:splat, s(:call, nil, :c)),
1479
+ s(:call, nil, :d))))
1480
+
1481
+ assert_parse rb, pt
1482
+ end
1483
+
1484
+ def test_op_asgn_primary_colon_const_command_call
1485
+ rb = "A::B *= c d"
1486
+ pt = s(:op_asgn, s(:const, :A),
1487
+ s(:call, nil, :c, s(:call, nil, :d)),
1488
+ :B, :*)
1489
+
1490
+ assert_parse rb, pt
1491
+ end
1492
+
1493
+ def test_op_asgn_primary_colon_identifier_command_call
1494
+ rb = "A::b *= c d"
1495
+ pt = s(:op_asgn, s(:const, :A),
1496
+ s(:call, nil, :c, s(:call, nil, :d)),
1497
+ :b, :*)
1498
+
1499
+ assert_parse rb, pt
1500
+ end
1501
+
1393
1502
  def test_op_asgn_val_dot_ident_command_call
1394
1503
  rb = "a.b ||= c 1"
1395
1504
  pt = s(:op_asgn, s(:call, nil, :a), s(:call, nil, :c, s(:lit, 1)), :b, :"||")
@@ -2971,6 +3080,8 @@ module TestRubyParserShared19Plus
2971
3080
  end
2972
3081
 
2973
3082
  def test_motherfuckin_leading_dots
3083
+ skip if processor.class.version >= 27
3084
+
2974
3085
  rb = "a\n.b"
2975
3086
  pt = s(:call, s(:call, nil, :a), :b)
2976
3087
 
@@ -2978,6 +3089,8 @@ module TestRubyParserShared19Plus
2978
3089
  end
2979
3090
 
2980
3091
  def test_motherfuckin_leading_dots2
3092
+ skip if processor.class.version >= 27
3093
+
2981
3094
  rb = "a\n..b"
2982
3095
 
2983
3096
  assert_parse_error rb, '(string):2 :: parse error on value ".." (tDOT2)'
@@ -3288,6 +3401,76 @@ module TestRubyParserShared20Plus
3288
3401
  assert_parse rb, pt
3289
3402
  end
3290
3403
 
3404
+ def test_call_array_block_call
3405
+ rb = "a [ nil, b do end ]"
3406
+ pt = s(:call, nil, :a,
3407
+ s(:array,
3408
+ s(:nil),
3409
+ s(:iter, s(:call, nil, :b), 0)))
3410
+
3411
+ assert_parse rb, pt
3412
+ end
3413
+
3414
+ def test_block_call_paren_call_block_call
3415
+ rb = "a (b)\nc.d do end"
3416
+ pt = s(:block,
3417
+ s(:call, nil, :a, s(:call, nil, :b)),
3418
+ s(:iter, s(:call, s(:call, nil, :c), :d), 0))
3419
+
3420
+
3421
+ assert_parse rb, pt
3422
+ end
3423
+
3424
+ def test_block_call_defn_call_block_call
3425
+ rb = "a def b(c)\n d\n end\n e.f do end"
3426
+ pt = s(:block,
3427
+ s(:call, nil, :a,
3428
+ s(:defn, :b, s(:args, :c), s(:call, nil, :d))),
3429
+ s(:iter, s(:call, s(:call, nil, :e), :f), 0))
3430
+
3431
+ assert_parse rb, pt
3432
+ end
3433
+
3434
+ def test_call_array_lambda_block_call
3435
+ rb = "a [->() {}] do\nend"
3436
+ pt = s(:iter,
3437
+ s(:call, nil, :a,
3438
+ s(:array, s(:iter, s(:lambda), s(:args)))),
3439
+ 0)
3440
+
3441
+ assert_parse rb, pt
3442
+ end
3443
+
3444
+ def test_call_begin_call_block_call
3445
+ rb = "a begin\nb.c do end\nend"
3446
+ pt = s(:call, nil, :a,
3447
+ s(:iter, s(:call, s(:call, nil, :b), :c), 0))
3448
+
3449
+ assert_parse rb, pt
3450
+ end
3451
+
3452
+ def test_messy_op_asgn_lineno
3453
+ rb = "a (B::C *= d e)"
3454
+ pt = s(:call, nil, :a,
3455
+ s(:op_asgn, s(:const, :B),
3456
+ s(:call, nil, :d, s(:call, nil, :e)),
3457
+ :C,
3458
+ :*)).line(1)
3459
+
3460
+ assert_parse rb, pt
3461
+ end
3462
+
3463
+ def test_str_lit_concat_bad_encodings
3464
+ rb = '"\xE3\xD3\x8B\xE3\x83\xBC\x83\xE3\x83\xE3\x82\xB3\xA3\x82\x99" \
3465
+ "\xE3\x83\xB3\xE3\x83\x8F\xE3\x82\x9A\xC3\xBD;foo@bar.com"'.b
3466
+ pt = s(:str, "\xE3\xD3\x8B\xE3\x83\xBC\x83\xE3\x83\xE3\x82\xB3\xA3\x82\x99\xE3\x83\xB3\xE3\x83\x8F\xE3\x82\x9A\xC3\xBD;foo@bar.com".b)
3467
+
3468
+ assert_parse rb, pt
3469
+
3470
+ sexp = processor.parse rb
3471
+ assert_equal Encoding::ASCII_8BIT, sexp.last.encoding
3472
+ end
3473
+
3291
3474
  def test_block_call_dot_op2_cmd_args_do_block
3292
3475
  rb = "a.b c() do d end.e f do |g| h end"
3293
3476
  pt = s(:iter,
@@ -3588,7 +3771,7 @@ module TestRubyParserShared21Plus
3588
3771
 
3589
3772
  def test_bug162__21plus
3590
3773
  rb = %q(<<E\nfoo\nE\rO)
3591
- emsg = "can't match /E(\n|\\z)/ anywhere in . near line 1: \"\""
3774
+ emsg = "can't match /E(\\r*\\n|\\z)/ anywhere in . near line 1: \"\""
3592
3775
 
3593
3776
  assert_syntax_error rb, emsg
3594
3777
  end
@@ -3738,6 +3921,13 @@ module TestRubyParserShared23Plus
3738
3921
  assert_parse rb, pt
3739
3922
  end
3740
3923
 
3924
+ def test_heredoc__backslash_dos_format
3925
+ rb = "str = <<-XXX\r\nbefore\\\r\nafter\r\nXXX\r\n"
3926
+ pt = s(:lasgn, :str, s(:str, "before\nafter\n"))
3927
+
3928
+ assert_parse rb, pt
3929
+ end
3930
+
3741
3931
  def test_heredoc_squiggly
3742
3932
  rb = "a = <<~\"EOF\"\n x\n y\n z\n EOF\n\n"
3743
3933
  pt = s(:lasgn, :a, s(:str, "x\ny\nz\n"))
@@ -3946,6 +4136,51 @@ module TestRubyParserShared26Plus
3946
4136
  end
3947
4137
  end
3948
4138
 
4139
+ module TestRubyParserShared27Plus
4140
+ include TestRubyParserShared26Plus
4141
+
4142
+ def test_defn_forward_args
4143
+ rb = "def a(...); b(...); end"
4144
+ pt = s(:defn, :a, s(:args, s(:forward_args)),
4145
+ s(:call, nil, :b, s(:forward_args)))
4146
+
4147
+ assert_parse_line rb, pt, 1
4148
+ end
4149
+
4150
+ def test_defn_arg_forward_args
4151
+ rb = "def a(x, ...); b(x, ...); end"
4152
+ pt = s(:defn, :a, s(:args, :x, s(:forward_args)),
4153
+ s(:call, nil, :b, s(:lvar, :x), s(:forward_args)))
4154
+
4155
+ assert_parse_line rb, pt, 1
4156
+ end
4157
+
4158
+ def test_defn_args_forward_args
4159
+ rb = "def a(x, y, z, ...); b(:get, z, ...); end"
4160
+ pt = s(:defn, :a, s(:args, :x, :y, :z, s(:forward_args)),
4161
+ s(:call, nil, :b, s(:lit, :get), s(:lvar, :z),
4162
+ s(:forward_args)))
4163
+
4164
+ assert_parse_line rb, pt, 1
4165
+ end
4166
+
4167
+ def test_call_forward_args_outside_method_definition
4168
+ rb = "b(...)"
4169
+
4170
+ assert_syntax_error rb, "Unexpected ..."
4171
+ end
4172
+
4173
+ def test_call_arg_forward_args_outside_method_definition
4174
+ rb = "b(x, ...)"
4175
+
4176
+ assert_syntax_error rb, "Unexpected ..."
4177
+ end
4178
+ end
4179
+
4180
+ module TestRubyParserShared30Plus
4181
+ include TestRubyParserShared27Plus
4182
+ end
4183
+
3949
4184
  class TestRubyParser < Minitest::Test
3950
4185
  def test_cls_version
3951
4186
  assert_equal 23, RubyParser::V23.version
@@ -4239,7 +4474,46 @@ class TestRubyParserV26 < RubyParserTestCase
4239
4474
 
4240
4475
  assert_parse_line rb, pt, 1
4241
4476
  end
4477
+ end
4478
+
4479
+ class TestRubyParserV27 < RubyParserTestCase
4480
+ include TestRubyParserShared27Plus
4242
4481
 
4482
+ def setup
4483
+ super
4484
+
4485
+ self.processor = RubyParser::V27.new
4486
+ end
4487
+
4488
+ def test_bdot2
4489
+ rb = "..10\n; ..a\n; c"
4490
+ pt = s(:block,
4491
+ s(:dot2, nil, s(:lit, 10).line(1)).line(1),
4492
+ s(:dot2, nil, s(:call, nil, :a).line(2)).line(2),
4493
+ s(:call, nil, :c).line(3)).line(1)
4494
+
4495
+ assert_parse_line rb, pt, 1
4496
+ end
4497
+
4498
+ def test_bdot3
4499
+ rb = "...10\n; ...a\n; c"
4500
+ pt = s(:block,
4501
+ s(:dot3, nil, s(:lit, 10).line(1)).line(1),
4502
+ s(:dot3, nil, s(:call, nil, :a).line(2)).line(2),
4503
+ s(:call, nil, :c).line(3)).line(1)
4504
+
4505
+ assert_parse_line rb, pt, 1
4506
+ end
4507
+ end
4508
+
4509
+ class TestRubyParserV30 < RubyParserTestCase
4510
+ include TestRubyParserShared30Plus
4511
+
4512
+ def setup
4513
+ super
4514
+
4515
+ self.processor = RubyParser::V30.new
4516
+ end
4243
4517
  end
4244
4518
 
4245
4519
  RubyParser::VERSIONS.each do |klass|