ruby_parser 3.3.0 → 3.4.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.
@@ -59,28 +59,8 @@ class RPStringScanner < StringScanner
59
59
  end
60
60
  end
61
61
 
62
- def current_line # HAHA fuck you (HACK)
63
- string_to_pos[/\A.*__LINE__/m].split(/\n/).size
64
- end
65
-
66
- def extra_lines_added
67
- @extra_lines_added ||= 0
68
- end
69
-
70
- def extra_lines_added= val
71
- @extra_lines_added = val
72
- end
73
-
74
- def lineno
75
- string[0...charpos].count("\n") + 1 - extra_lines_added
76
- end
77
-
78
- # TODO: once we get rid of these, we can make things like
79
- # TODO: current_line and lineno much more accurate and easy to do
80
-
81
62
  def unread_many str # TODO: remove this entirely - we should not need it
82
63
  warn({:unread_many => caller[0]}.inspect) if ENV['TALLY']
83
- self.extra_lines_added += str.count("\n") - 1
84
64
  begin
85
65
  string[charpos, 0] = str
86
66
  rescue IndexError
@@ -111,7 +91,7 @@ class RPStringScanner < StringScanner
111
91
  end
112
92
 
113
93
  module RubyParserStuff
114
- VERSION = "3.3.0" unless constants.include? "VERSION" # SIGH
94
+ VERSION = "3.4.0" unless constants.include? "VERSION" # SIGH
115
95
 
116
96
  attr_accessor :lexer, :in_def, :in_single, :file
117
97
  attr_reader :env, :comments
@@ -148,15 +128,6 @@ module RubyParserStuff
148
128
  raise RubyParser::SyntaxError, msg
149
129
  end
150
130
 
151
- def arg_add(node1, node2) # TODO: nuke
152
- return s(:arglist, node2) unless node1
153
-
154
- node1[0] = :arglist if node1[0] == :array
155
- return node1 << node2 if node1[0] == :arglist
156
-
157
- return s(:arglist, node1, node2)
158
- end
159
-
160
131
  def arg_blk_pass node1, node2 # TODO: nuke
161
132
  node1 = s(:arglist, node1) unless [:arglist, :call_args, :array, :args].include? node1.first
162
133
  node1 << node2 if node2
@@ -391,6 +362,7 @@ module RubyParserStuff
391
362
  end
392
363
 
393
364
  def gettable(id)
365
+ lineno = id.lineno if id.respond_to? :lineno
394
366
  id = id.to_sym if String === id
395
367
 
396
368
  result = case id.to_s
@@ -411,7 +383,7 @@ module RubyParserStuff
411
383
  end
412
384
  end
413
385
 
414
- result.line(result.line - 1) if result.line and lexer.src.bol?
386
+ result.line lineno if lineno
415
387
 
416
388
  raise "identifier #{id.inspect} is not valid" unless result
417
389
 
@@ -457,7 +429,7 @@ module RubyParserStuff
457
429
  list
458
430
  end
459
431
 
460
- def literal_concat head, tail
432
+ def literal_concat head, tail # TODO: ugh. rewrite
461
433
  return tail unless head
462
434
  return head unless tail
463
435
 
@@ -476,8 +448,10 @@ module RubyParserStuff
476
448
  end
477
449
  when :dstr then
478
450
  if htype == :str then
451
+ lineno = head.line
479
452
  tail[1] = head[-1] + tail[1]
480
453
  head = tail
454
+ head.line = lineno
481
455
  else
482
456
  tail[0] = :array
483
457
  tail[1] = s(:str, tail[1])
@@ -563,7 +537,7 @@ module RubyParserStuff
563
537
  end
564
538
 
565
539
  def argl x
566
- x = s(:arglist, x) if x and x[0] != :arglist
540
+ x = s(:arglist, x) if x and x[0] == :array
567
541
  x
568
542
  end
569
543
 
@@ -587,12 +561,13 @@ module RubyParserStuff
587
561
  # TODO: need a test with f(&b) to produce block_pass
588
562
  # TODO: need a test with f(&b) { } to produce warning
589
563
 
590
- args ||= s(:arglist)
591
- args[0] = :arglist if [:args, :array, :call_args].include? args.first
592
- args = s(:arglist, args) unless args.first == :arglist
593
-
594
- # HACK quick hack to make this work quickly... easy to clean up above
595
- result.concat args[1..-1]
564
+ if args
565
+ if [:arglist, :args, :array, :call_args].include? args.first
566
+ result.concat args.sexp_body
567
+ else
568
+ result << args
569
+ end
570
+ end
596
571
 
597
572
  line = result.grep(Sexp).map(&:line).compact.min
598
573
  result.line = line if line
@@ -600,9 +575,8 @@ module RubyParserStuff
600
575
  result
601
576
  end
602
577
 
603
- def new_case expr, body
578
+ def new_case expr, body, line
604
579
  result = s(:case, expr)
605
- line = (expr || body).line
606
580
 
607
581
  while body and body.node_type == :when
608
582
  result << body
@@ -794,8 +768,14 @@ module RubyParserStuff
794
768
  begin
795
769
  Regexp.new(node[1], o)
796
770
  rescue RegexpError => e
797
- warn "Ignoring: #{e.message}"
798
- Regexp.new(node[1], Regexp::ENC_NONE)
771
+ warn "WA\RNING: #{e.message} for #{node[1].inspect} #{options.inspect}"
772
+ begin
773
+ warn "WA\RNING: trying to recover with ENC_UTF8"
774
+ Regexp.new(node[1], Regexp::ENC_UTF8)
775
+ rescue RegexpError => e
776
+ warn "WA\RNING: trying to recover with ENC_NONE"
777
+ Regexp.new(node[1], Regexp::ENC_NONE)
778
+ end
799
779
  end
800
780
  end
801
781
  when :dstr then
@@ -919,8 +899,10 @@ module RubyParserStuff
919
899
  end
920
900
 
921
901
  def next_token
922
- if self.lexer.advance then
923
- return self.lexer.token, self.lexer.yacc_value
902
+ token = self.lexer.next_token
903
+
904
+ if token and token.first != RubyLexer::EOF then
905
+ return token
924
906
  else
925
907
  return [false, '$end']
926
908
  end
@@ -932,18 +914,13 @@ module RubyParserStuff
932
914
  rhs = value_expr rhs
933
915
 
934
916
  case lhs[0]
935
- when :gasgn, :iasgn, :lasgn, :masgn, :cdecl, :cvdecl, :cvasgn then
936
- lhs << rhs
937
- when :attrasgn then
917
+ when :lasgn, :iasgn, :cdecl, :cvdecl, :gasgn, :cvasgn, :attrasgn then
938
918
  lhs << rhs
939
- when :call then
940
- args = lhs.pop unless Symbol === lhs.last
941
- lhs.concat arg_add(args, rhs)[1..-1]
942
919
  when :const then
943
920
  lhs[0] = :cdecl
944
921
  lhs << rhs
945
922
  else
946
- raise "unknown lhs #{lhs.inspect}"
923
+ raise "unknown lhs #{lhs.inspect} w/ #{rhs.inspect}"
947
924
  end
948
925
 
949
926
  lhs
@@ -1033,10 +1010,12 @@ module RubyParserStuff
1033
1010
  str = handle_encoding str
1034
1011
 
1035
1012
  self.file = file.dup
1036
- self.lexer.src = str
1037
1013
 
1038
1014
  @yydebug = ENV.has_key? 'DEBUG'
1039
1015
 
1016
+ # HACK -- need to get tests passing more than have graceful code
1017
+ self.lexer.ss = RPStringScanner.new str
1018
+
1040
1019
  do_parse
1041
1020
  end
1042
1021
  end
@@ -1086,7 +1065,7 @@ module RubyParserStuff
1086
1065
 
1087
1066
  def s(*args)
1088
1067
  result = Sexp.new(*args)
1089
- result.line ||= lexer.lineno if lexer.src # otherwise...
1068
+ result.line ||= lexer.lineno if lexer.ss # otherwise...
1090
1069
  result.file = self.file
1091
1070
  result
1092
1071
  end
@@ -1369,6 +1348,16 @@ unless "".respond_to?(:grep) then
1369
1348
  end
1370
1349
  end
1371
1350
 
1351
+ class String
1352
+ ##
1353
+ # This is a hack used by the lexer to sneak in line numbers at the
1354
+ # identifier level. This should be MUCH smaller than making
1355
+ # process_token return [value, lineno] and modifying EVERYTHING that
1356
+ # reduces tIDENTIFIER.
1357
+
1358
+ attr_accessor :lineno
1359
+ end
1360
+
1372
1361
  class Sexp
1373
1362
  attr_writer :paren
1374
1363
 
@@ -1386,12 +1375,10 @@ class Sexp
1386
1375
  self.value.to_sym
1387
1376
  end
1388
1377
 
1389
- def add x
1390
- concat x
1391
- end
1378
+ alias :add :<<
1392
1379
 
1393
1380
  def add_all x
1394
- raise "no: #{self.inspect}.add_all #{x.inspect}" # TODO: need a test to trigger this
1381
+ self.concat x.sexp_body
1395
1382
  end
1396
1383
 
1397
1384
  def block_pass?
@@ -20,7 +20,7 @@ class TestRubyLexer < Minitest::Test
20
20
 
21
21
  def setup_lexer input, exp_sexp = nil
22
22
  setup_new_parser
23
- lex.src = input
23
+ lex.ss = RPStringScanner.new(input)
24
24
  lex.lex_state = self.lex_state
25
25
  end
26
26
 
@@ -71,11 +71,11 @@ class TestRubyLexer < Minitest::Test
71
71
  end
72
72
 
73
73
  def assert_next_lexeme token=nil, value=nil, state=nil, paren=nil, brace=nil
74
- adv = @lex.advance
74
+ adv = @lex.next_token
75
75
 
76
76
  assert adv, "no more tokens"
77
77
 
78
- act_token, act_value = @lex.token, @lex.yacc_value
78
+ act_token, act_value = adv
79
79
 
80
80
  msg = message {
81
81
  act = [act_token, act_value, @lex.lex_state,
@@ -98,20 +98,20 @@ class TestRubyLexer < Minitest::Test
98
98
  end
99
99
 
100
100
  def assert_read_escape expected, input
101
- @lex.src = input
101
+ @lex.ss.string = input
102
102
  assert_equal expected, @lex.read_escape, input
103
103
  end
104
104
 
105
105
  def assert_read_escape_bad input # TODO: rename refute_read_escape
106
- @lex.src = input
106
+ @lex.ss.string = input
107
107
  assert_raises RubyParser::SyntaxError do
108
108
  @lex.read_escape
109
109
  end
110
110
  end
111
111
 
112
112
  def refute_lexeme
113
- x = @lex.advance
114
- y = [@lex.token, @lex.yacc_value]
113
+ x = y = @lex.next_token
114
+
115
115
  refute x, "not empty: #{y.inspect}"
116
116
  end
117
117
 
@@ -146,10 +146,10 @@ class TestRubyLexer < Minitest::Test
146
146
 
147
147
  ## Tests:
148
148
 
149
- def test_advance
150
- assert @lex.advance # blah
151
- assert @lex.advance # blah
152
- refute @lex.advance # nada
149
+ def test_next_token
150
+ assert_equal [:tIDENTIFIER, "blah"], @lex.next_token
151
+ assert_equal [:tIDENTIFIER, "blah"], @lex.next_token
152
+ assert_nil @lex.next_token
153
153
  end
154
154
 
155
155
  def test_unicode_ident
@@ -834,6 +834,14 @@ class TestRubyLexer < Minitest::Test
834
834
  :kEND, "end", :expr_end)
835
835
  end
836
836
 
837
+ def test_yylex_is_your_spacebar_broken?
838
+ assert_lex3(":a!=:b",
839
+ nil,
840
+ :tSYMBOL, "a", :expr_end,
841
+ :tNEQ, "!=", :expr_beg,
842
+ :tSYMBOL, "b", :expr_end)
843
+ end
844
+
837
845
  def test_yylex_do_cond
838
846
  assert_lex3("x do 42 end",
839
847
  nil,
@@ -2538,8 +2546,9 @@ class TestRubyLexer < Minitest::Test
2538
2546
  end
2539
2547
 
2540
2548
  def test_yylex_underscore_end
2541
- @lex.src = "__END__\n"
2542
- refute_lexeme
2549
+ assert_lex3("__END__\n",
2550
+ nil,
2551
+ RubyLexer::EOF, RubyLexer::EOF, nil)
2543
2552
  end
2544
2553
 
2545
2554
  def test_yylex_uplus
@@ -603,14 +603,8 @@ module TestRubyParserShared
603
603
  assert_parse rb, pt
604
604
  end
605
605
 
606
- STARTING_LINE = {
607
- "case_no_expr" => 2, # TODO this should be 1
608
- "structure_unused_literal_wwtt" => 3, # yes, 3... odd test
609
- }
610
-
611
606
  def after_process_hook klass, node, data, input_name, output_name
612
- expected = STARTING_LINE[node] || 1
613
- assert_equal expected, @result.line, "should have proper line number"
607
+ assert_equal 1, @result.line, "should have proper line number"
614
608
  end
615
609
 
616
610
  def test_parse_line_block
@@ -639,13 +633,10 @@ module TestRubyParserShared
639
633
  s(:call, nil, :b).line(2),
640
634
  s(:call, nil, :c).line(3))
641
635
 
642
- # see skipped test: test_parse_line_block_inline_comment2
643
636
  assert_parse rb, pt
644
637
  end
645
638
 
646
- def test_parse_line_block_inline_comment2
647
- skip "I can't fix this yet. Very involved. (process_token to return lineno)"
648
-
639
+ def test_parse_line_block_inline_multiline_comment
649
640
  rb = "a\nb # comment\n# another comment\nc"
650
641
  pt = s(:block,
651
642
  s(:call, nil, :a).line(1),
@@ -655,14 +646,12 @@ module TestRubyParserShared
655
646
  assert_parse rb, pt
656
647
  end
657
648
 
658
- def test_parse_line_block_inline_comment3
659
- skip "not yet"
660
-
649
+ def test_parse_line_block_inline_comment_leading_newlines
661
650
  rb = "\n\n\na\nb # comment\n# another comment\nc"
662
651
  pt = s(:block,
663
652
  s(:call, nil, :a).line(4),
664
- s(:call, nil, :b).line(6),
665
- s(:call, nil, :c).line(8)).line(1)
653
+ s(:call, nil, :b).line(5),
654
+ s(:call, nil, :c).line(7)).line(4)
666
655
 
667
656
  assert_parse rb, pt
668
657
  end
@@ -681,6 +670,20 @@ module TestRubyParserShared
681
670
  assert_equal 2, result[3].line, "call should have line number"
682
671
  end
683
672
 
673
+ def test_parse_line_call_ivar_line_break_paren
674
+ rb = "a(@b\n)"
675
+ pt = s(:call, nil, :a, s(:ivar, :@b).line(1)).line(1)
676
+
677
+ assert_parse rb, pt
678
+ end
679
+
680
+ def test_parse_line_call_ivar_arg_no_parens_line_break
681
+ rb = "a @b\n"
682
+ pt = s(:call, nil, :a, s(:ivar, :@b).line(1)).line(1)
683
+
684
+ assert_parse rb, pt
685
+ end
686
+
684
687
  def test_parse_line_defn_no_parens
685
688
  pt = s(:defn, :f, s(:args), s(:nil))
686
689
 
@@ -708,6 +711,15 @@ module TestRubyParserShared
708
711
  assert_equal 4, body.return.line, "return should have line number"
709
712
  end
710
713
 
714
+ def test_parse_line_evstr_after_break
715
+ rb = "\"a\"\\\n\"\#{b}\""
716
+ pt = s(:dstr, "a",
717
+ s(:evstr,
718
+ s(:call, nil, :b).line(2)).line(2)).line(1)
719
+
720
+ assert_parse rb, pt
721
+ end
722
+
711
723
  def test_parse_line_iter_call_parens
712
724
  rb = "f(a) do |x, y|\n x + y\nend"
713
725
 
@@ -727,15 +739,12 @@ module TestRubyParserShared
727
739
  rb = "f a do |x, y|\n x + y\nend"
728
740
 
729
741
  pt = s(:iter,
730
- s(:call, nil, :f, s(:call, nil, :a)),
731
- s(:args, :x, :y),
732
- s(:call, s(:lvar, :x), :+, s(:lvar, :y)))
742
+ s(:call, nil, :f, s(:call, nil, :a).line(1)).line(1),
743
+ s(:args, :x, :y).line(1),
744
+ s(:call, s(:lvar, :x).line(2), :+,
745
+ s(:lvar, :y).line(2)).line(2)).line(1)
733
746
 
734
- assert_parse_line rb, pt, 1
735
-
736
- assert_equal 1, result[1].line, "call should have line number"
737
- assert_equal 1, result[2].line, "masgn should have line number"
738
- assert_equal 2, result[3].line, "call should have line number"
747
+ assert_parse rb, pt
739
748
  end
740
749
 
741
750
  def test_parse_line_heredoc
@@ -797,6 +806,15 @@ module TestRubyParserShared
797
806
  assert_equal 3, result.if.return.lit.line
798
807
  end
799
808
 
809
+ def test_parse_line_trailing_newlines
810
+ rb = "a \nb"
811
+ pt = s(:block,
812
+ s(:call, nil, :a).line(1),
813
+ s(:call, nil, :b).line(2)).line(1)
814
+
815
+ assert_parse rb, pt
816
+ end
817
+
800
818
  def test_bug_and
801
819
  rb = "true and []"
802
820
  pt = s(:and, s(:true), s(:array))
@@ -1044,7 +1062,7 @@ module TestRubyParserShared
1044
1062
  s(:call, nil, :p, s(:str, "a").line(2)).line(2),
1045
1063
  s(:lasgn, :b, s(:lit, 1).line(3)).line(3),
1046
1064
  s(:call, nil, :p, s(:lvar, :b).line(4)).line(4),
1047
- s(:lasgn, :c, s(:lit, 1).line(5)).line(5)).line(2), # TODO line 2?
1065
+ s(:lasgn, :c, s(:lit, 1).line(5)).line(5)).line(2),
1048
1066
  nil).line(1),
1049
1067
  s(:call, nil, :a).line(7)).line(1)
1050
1068
 
@@ -2051,6 +2069,16 @@ class TestRuby18Parser < RubyParserTestCase
2051
2069
  self.processor = Ruby18Parser.new
2052
2070
  end
2053
2071
 
2072
+ def test_call_space_before_paren_args
2073
+ rb = "a (:b, :c, :d => :e)"
2074
+ pt = s(:call, nil, :a,
2075
+ s(:lit, :b),
2076
+ s(:lit, :c),
2077
+ s(:hash, s(:lit, :d), s(:lit, :e)))
2078
+
2079
+ assert_parse rb, pt
2080
+ end
2081
+
2054
2082
  def test_flip2_env_lvar
2055
2083
  rb = "if a..b then end"
2056
2084
  pt = s(:if, s(:flip2, s(:call, nil, :a), s(:call, nil, :b)), nil, nil)
@@ -2848,6 +2876,38 @@ class TestRuby20Parser < RubyParserTestCase
2848
2876
  self.processor = Ruby20Parser.new
2849
2877
  end
2850
2878
 
2879
+ def test_block_call_dot_op2_brace_block
2880
+ rb = "a.b c() do d end.e do |f| g end"
2881
+ pt = s(:iter,
2882
+ s(:call,
2883
+ s(:iter,
2884
+ s(:call, s(:call, nil, :a), :b, s(:call, nil, :c)),
2885
+ s(:args),
2886
+ s(:call, nil, :d)),
2887
+ :e),
2888
+ s(:args, :f),
2889
+ s(:call, nil, :g))
2890
+
2891
+
2892
+ assert_parse rb, pt
2893
+ end
2894
+
2895
+ def test_block_call_dot_op2_cmd_args_do_block
2896
+ rb = "a.b c() do d end.e f do |g| h end"
2897
+ pt = s(:iter,
2898
+ s(:call,
2899
+ s(:iter,
2900
+ s(:call, s(:call, nil, :a), :b, s(:call, nil, :c)),
2901
+ s(:args),
2902
+ s(:call, nil, :d)),
2903
+ :e,
2904
+ s(:call, nil, :f)),
2905
+ s(:args, :g),
2906
+ s(:call, nil, :h))
2907
+
2908
+ assert_parse rb, pt
2909
+ end
2910
+
2851
2911
  def test_defn_kwarg_val
2852
2912
  rb = "def f(a, b:1) end"
2853
2913
  pt = s(:defn, :f, s(:args, :a, s(:kwarg, :b, s(:lit, 1))), s(:nil))