ripper_ruby_parser 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +4 -23
  4. data/Rakefile +12 -12
  5. data/lib/ripper_ruby_parser.rb +2 -2
  6. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +9 -9
  7. data/lib/ripper_ruby_parser/parser.rb +3 -3
  8. data/lib/ripper_ruby_parser/sexp_handlers.rb +9 -9
  9. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +3 -9
  10. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +19 -24
  11. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +14 -18
  12. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +3 -3
  13. data/lib/ripper_ruby_parser/sexp_processor.rb +4 -4
  14. data/lib/ripper_ruby_parser/unescape.rb +11 -11
  15. data/lib/ripper_ruby_parser/version.rb +1 -1
  16. data/test/end_to_end/comments_test.rb +10 -10
  17. data/test/end_to_end/comparison_test.rb +28 -28
  18. data/test/end_to_end/lib_comparison_test.rb +6 -6
  19. data/test/end_to_end/line_numbering_test.rb +10 -10
  20. data/test/end_to_end/samples_comparison_test.rb +5 -5
  21. data/test/end_to_end/test_comparison_test.rb +6 -6
  22. data/test/pt_testcase/pt_test.rb +7 -7
  23. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +163 -169
  24. data/test/ripper_ruby_parser/parser_test.rb +338 -338
  25. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +475 -511
  26. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +582 -564
  27. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +469 -469
  28. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +713 -724
  29. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +155 -155
  30. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +181 -181
  31. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +337 -352
  32. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +298 -298
  33. data/test/ripper_ruby_parser/sexp_processor_test.rb +119 -119
  34. data/test/ripper_ruby_parser/version_test.rb +2 -2
  35. data/test/samples/lambdas.rb +5 -0
  36. data/test/samples/misc.rb +3 -0
  37. data/test/samples/strings.rb +7 -0
  38. data/test/test_helper.rb +8 -6
  39. metadata +12 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20d34b3ba8f1c186e8df1118334a231d2520c9ef51a36b4c7d5b12c33fe9947b
4
- data.tar.gz: 881e3286d632c0189a33a2add98dd43bddda798cf6c7c8f3fa75e1b9dfdda7e3
3
+ metadata.gz: 16ae34997256487e8611f1c1128bfa3f0ededad4befbdcba5cae435e957e4382
4
+ data.tar.gz: 9751a46aeaa42e05bc52587fa0fee46b64e0b45204b9cbf651f7492d7e6bde90
5
5
  SHA512:
6
- metadata.gz: f3a58dd16a10a8c0f64996c753e2da3c02d7b0ec074099795bf240925e388a5edb215edf680df0c70baab82c42ea77d22762d2a2b27a7a9a246aa01bb47753a1
7
- data.tar.gz: 7b360aaea5ba1fe76855a4e534d56aec13b1a470f7cc9e539d4e2c996ef0684848142ea6c4d2e522c439e84d62628ebaf571da5c993e9a44a0f9641d8e3283df
6
+ metadata.gz: c31670a8b6d911f7679096feb5d1b01e2c67a7aec7694eb7f4ac932c2f335f24e5996074bd0857614e8f508c093f639d644f3ab4555de97c68f1ea601f4fd586
7
+ data.tar.gz: 2668135d139b2c4c5cb3da3f036bc7653896239a48846bbae4fe18056bb751f21e00618c8b2d7b90f3de3e504f4dfb959e442f3f302b253bcf777a0232329950
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.7.0 / 2019-11-01
4
+
5
+ * Make results compatible with RubyParser 3.14.0 ([#85])
6
+ - Remove obsolete extra-compatible behavior
7
+ - Parse stabby lambda as :lambda-typed sexp
8
+ - Emit nil argument for block arguments with trailing comma
9
+ * Require Ruby 2.4 or higher ([#86])
10
+
3
11
  ## 1.6.1 / 2019-04-22
4
12
 
5
13
  * Improve line numbering for some block structures ([#82])
data/README.md CHANGED
@@ -10,28 +10,16 @@ Parse with Ripper, produce sexps that are compatible with RubyParser.
10
10
 
11
11
  * Drop-in replacement for RubyParser
12
12
  * Should handle 1.9 and later syntax gracefully
13
- * Requires MRI 2.3 or higher
14
- * Compatible with RubyParser 3.13.1
13
+ * Requires Ruby 2.4 or higher
14
+ * Compatible with RubyParser 3.14.0
15
15
 
16
16
  ## Known incompatibilities
17
17
 
18
- RipperRubyParser has some incompatibilities with RubyParser. For some of these,
19
- the behavior can be changed by turning on extra-compatible mode.
20
-
21
- The following incompatibilities cannot be changed:
18
+ RipperRubyParser has a few incompatibilities with RubyParser.
22
19
 
23
20
  * RipperRubyParser won't handle non-UTF-8 files without an encoding comment,
24
21
  just like regular Ruby
25
- * RipperRubyParser does not match RubyParser's line numbering
26
- * RipperRubyParser correctly dedents heredocs with interpolations
27
-
28
- The following incompatibilities can be made compatible by turning on
29
- extra-compatible mode:
30
-
31
- * Operator assignment of a method call without parentheses to a collection
32
- element uses an `:array` S-expression instead of `:arglist`
33
- * RipperRubyParser keeps carriage return characters in heredocs that include
34
- them
22
+ * RipperRubyParser does not always match RubyParser's line numbering
35
23
 
36
24
  ## Install
37
25
 
@@ -50,13 +38,6 @@ parser.parse "foo[bar] += baz qux"
50
38
  # s(:arglist, s(:call, nil, :bar)),
51
39
  # :+,
52
40
  # s(:call, nil, :baz, s(:call, nil, :qux)))
53
- parser.extra_compatible = true
54
-
55
- parser.parse "foo[bar] += baz qux"
56
- # => s(:op_asgn1, s(:call, nil, :foo),
57
- # s(:array, s(:call, nil, :bar)),
58
- # :+,
59
- # s(:call, nil, :baz, s(:call, nil, :qux)))
60
41
  ```
61
42
 
62
43
  ## Requirements
data/Rakefile CHANGED
@@ -1,33 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rake/clean'
4
- require 'bundler/gem_tasks'
5
- require 'rake/testtask'
3
+ require "rake/clean"
4
+ require "bundler/gem_tasks"
5
+ require "rake/testtask"
6
6
 
7
7
  namespace :test do
8
8
  Rake::TestTask.new(:unit) do |t|
9
- t.libs = ['lib']
10
- t.test_files = FileList['test/ripper_ruby_parser/**/*_test.rb']
9
+ t.libs = ["lib"]
10
+ t.test_files = FileList["test/ripper_ruby_parser/**/*_test.rb"]
11
11
  t.warning = true
12
12
  end
13
13
 
14
14
  Rake::TestTask.new(:end_to_end) do |t|
15
- t.libs = ['lib']
16
- t.test_files = FileList['test/end_to_end/*_test.rb']
15
+ t.libs = ["lib"]
16
+ t.test_files = FileList["test/end_to_end/*_test.rb"]
17
17
  t.warning = true
18
18
  end
19
19
 
20
20
  Rake::TestTask.new(:pt_testcase) do |t|
21
- t.libs = ['lib']
22
- t.test_files = FileList['test/pt_testcase/*_test.rb']
21
+ t.libs = ["lib"]
22
+ t.test_files = FileList["test/pt_testcase/*_test.rb"]
23
23
  t.warning = true
24
24
  end
25
25
 
26
- desc 'Run all three test suites'
26
+ desc "Run all three test suites"
27
27
  task run: [:unit, :end_to_end, :pt_testcase]
28
28
  end
29
29
 
30
- desc 'Alias to test:run'
31
- task test: 'test:run'
30
+ desc "Alias to test:run"
31
+ task test: "test:run"
32
32
 
33
33
  task default: :test
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper_ruby_parser/version'
4
- require 'ripper_ruby_parser/parser'
3
+ require "ripper_ruby_parser/version"
4
+ require "ripper_ruby_parser/parser"
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper'
4
- require 'ripper_ruby_parser/syntax_error'
5
- require 'ripper_ruby_parser/unescape'
3
+ require "ripper"
4
+ require "ripper_ruby_parser/syntax_error"
5
+ require "ripper_ruby_parser/unescape"
6
6
 
7
7
  module RipperRubyParser
8
8
  # Variant of Ripper's SexpBuilder parser class that inserts comments as
@@ -12,7 +12,7 @@ module RipperRubyParser
12
12
  class CommentingRipperParser < Ripper::SexpBuilder
13
13
  def initialize(*args)
14
14
  super
15
- @comment = ''
15
+ @comment = ""
16
16
  @comment_stack = []
17
17
  @delimiter_stack = []
18
18
  @space_before = false
@@ -22,7 +22,7 @@ module RipperRubyParser
22
22
 
23
23
  def parse
24
24
  result = super
25
- raise 'Ripper parse failed.' unless result
25
+ raise "Ripper parse failed." unless result
26
26
 
27
27
  Sexp.from_array(result)
28
28
  end
@@ -60,10 +60,10 @@ module RipperRubyParser
60
60
  def on_kw(tok)
61
61
  result = super
62
62
  case tok
63
- when 'class', 'def', 'module', 'BEGIN', 'begin', 'END'
63
+ when "class", "def", "module", "BEGIN", "begin", "END"
64
64
  unless @in_symbol
65
65
  @comment_stack.push [result, @comment]
66
- @comment = ''
66
+ @comment = ""
67
67
  end
68
68
  end
69
69
  result
@@ -255,7 +255,7 @@ module RipperRubyParser
255
255
  def on_unary(operator, value)
256
256
  if !@space_before && operator == :-@ && NUMBER_LITERAL_TYPES.include?(value.first)
257
257
  type, literal, lines = value
258
- if literal[0] == '-'
258
+ if literal[0] == "-"
259
259
  super
260
260
  else
261
261
  [type, "-#{literal}", lines]
@@ -317,7 +317,7 @@ module RipperRubyParser
317
317
 
318
318
  def commentize(_name, exp)
319
319
  (_, _kw, loc), comment = @comment_stack.pop
320
- @comment = ''
320
+ @comment = ""
321
321
  exp.push loc
322
322
  [:comment, comment, exp]
323
323
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper_ruby_parser/commenting_ripper_parser'
4
- require 'ripper_ruby_parser/sexp_processor'
3
+ require "ripper_ruby_parser/commenting_ripper_parser"
4
+ require "ripper_ruby_parser/sexp_processor"
5
5
 
6
6
  module RipperRubyParser
7
7
  # Main parser class. Brings together Ripper and our
@@ -13,7 +13,7 @@ module RipperRubyParser
13
13
  @extra_compatible = false
14
14
  end
15
15
 
16
- def parse(source, filename = '(string)', lineno = 1)
16
+ def parse(source, filename = "(string)", lineno = 1)
17
17
  parser = CommentingRipperParser.new(source, filename, lineno)
18
18
  exp = parser.parse
19
19
 
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper_ruby_parser/sexp_handlers/helper_methods'
3
+ require "ripper_ruby_parser/sexp_handlers/helper_methods"
4
4
 
5
- require 'ripper_ruby_parser/sexp_handlers/assignment'
6
- require 'ripper_ruby_parser/sexp_handlers/blocks'
7
- require 'ripper_ruby_parser/sexp_handlers/conditionals'
8
- require 'ripper_ruby_parser/sexp_handlers/literals'
9
- require 'ripper_ruby_parser/sexp_handlers/loops'
10
- require 'ripper_ruby_parser/sexp_handlers/method_calls'
11
- require 'ripper_ruby_parser/sexp_handlers/methods'
12
- require 'ripper_ruby_parser/sexp_handlers/operators'
5
+ require "ripper_ruby_parser/sexp_handlers/assignment"
6
+ require "ripper_ruby_parser/sexp_handlers/blocks"
7
+ require "ripper_ruby_parser/sexp_handlers/conditionals"
8
+ require "ripper_ruby_parser/sexp_handlers/literals"
9
+ require "ripper_ruby_parser/sexp_handlers/loops"
10
+ require "ripper_ruby_parser/sexp_handlers/method_calls"
11
+ require "ripper_ruby_parser/sexp_handlers/methods"
12
+ require "ripper_ruby_parser/sexp_handlers/operators"
13
13
 
14
14
  module RipperRubyParser
15
15
  # Umbrella module for handlers of particular sexp types
@@ -96,11 +96,10 @@ module RipperRubyParser
96
96
  _, lvalue, (_, operator,), value = exp.shift 4
97
97
 
98
98
  lvalue = process(lvalue)
99
- original_value_type = value.sexp_type
100
99
  value = process(value)
101
100
  operator = operator.chop.to_sym
102
101
 
103
- create_operator_assignment_sub_type lvalue, value, operator, original_value_type
102
+ create_operator_assignment_sub_type lvalue, value, operator
104
103
  end
105
104
 
106
105
  private
@@ -123,16 +122,11 @@ module RipperRubyParser
123
122
  '&&': :op_asgn_and
124
123
  }.freeze
125
124
 
126
- def create_operator_assignment_sub_type(lvalue, value, operator, original_value_type)
125
+ def create_operator_assignment_sub_type(lvalue, value, operator)
127
126
  case lvalue.sexp_type
128
127
  when :aref_field
129
128
  _, arr, arglist = lvalue
130
- arglist.sexp_type = if extra_compatible &&
131
- [:command, :command_call].include?(original_value_type)
132
- :array
133
- else
134
- :arglist
135
- end
129
+ arglist.sexp_type = :arglist
136
130
  s(:op_asgn1, arr, arglist, operator, value)
137
131
  when :field
138
132
  _, obj, _, (_, field) = lvalue
@@ -58,27 +58,23 @@ module RipperRubyParser
58
58
  rescue_block = map_process_list_compact block.sexp_body
59
59
  rescue_block << nil if rescue_block.empty?
60
60
 
61
- capture = if eclass
62
- if eclass.first.is_a? Symbol
63
- eclass = process(eclass)
64
- body = eclass.sexp_body
65
- if eclass.sexp_type == :mrhs
66
- body.first
67
- else
68
- s(:array, *body)
69
- end
61
+ capture = if eclass.nil?
62
+ s(:array)
63
+ elsif eclass.first.is_a? Symbol
64
+ eclass = process(eclass)
65
+ body = eclass.sexp_body
66
+ if eclass.sexp_type == :mrhs
67
+ body.first
70
68
  else
71
- s(:array, process(eclass.first))
69
+ s(:array, *body)
72
70
  end
73
71
  else
74
- s(:array)
72
+ s(:array, process(eclass.first))
75
73
  end
76
74
 
77
75
  capture << create_assignment_sub_type(process(evar), s(:gvar, :$!)) if evar
78
76
 
79
- s(
80
- s(:resbody, capture, *rescue_block),
81
- *process(after))
77
+ s(s(:resbody, capture, *rescue_block), *process(after))
82
78
  end
83
79
 
84
80
  def process_bodystmt(exp)
@@ -91,13 +87,9 @@ module RipperRubyParser
91
87
  main = wrap_in_block reject_void_stmt main_list
92
88
  body << main if main
93
89
 
94
- if rescue_block
95
- body.push(*process(rescue_block))
96
- body << process(else_block) if else_block
97
- body = s(s(:rescue, *body))
98
- elsif else_block
99
- body << process(else_block)
100
- end
90
+ body.push(*process(rescue_block)) if rescue_block
91
+ body << process(else_block) if else_block
92
+ body = s(s(:rescue, *body)) if rescue_block
101
93
 
102
94
  if ensure_block
103
95
  body << process(ensure_block)
@@ -143,7 +135,7 @@ module RipperRubyParser
143
135
  old_type = args.sexp_type
144
136
  args = convert_arguments(process(args))
145
137
  args = nil if args == s(:args) && old_type == :params
146
- make_iter(s(:call, nil, :lambda),
138
+ make_iter(s(:lambda),
147
139
  args,
148
140
  safe_unwrap_void_stmt(process(statements)))
149
141
  end
@@ -167,7 +159,10 @@ module RipperRubyParser
167
159
  end
168
160
 
169
161
  def handle_splat(splat)
170
- if splat && splat != 0
162
+ if splat == 0
163
+ # Only relevant for Ruby < 2.6
164
+ [s(:excessed_comma)]
165
+ elsif splat
171
166
  [process(splat)]
172
167
  else
173
168
  []
@@ -209,7 +204,7 @@ module RipperRubyParser
209
204
  end
210
205
 
211
206
  def make_iter(call, args, stmt)
212
- args.pop if args && args.last == s(:excessed_comma)
207
+ args[-1] = nil if args && args.last == s(:excessed_comma)
213
208
  args ||= 0
214
209
  if stmt.empty?
215
210
  s(:iter, call, args)
@@ -31,16 +31,16 @@ module RipperRubyParser
31
31
  when :str, :dstr
32
32
  val
33
33
  when :void_stmt
34
- s(:dstr, '', s(:evstr))
34
+ s(:dstr, "", s(:evstr))
35
35
  else
36
- s(:dstr, '', s(:evstr, val))
36
+ s(:dstr, "", s(:evstr, val))
37
37
  end
38
38
  end
39
39
 
40
40
  def process_string_dvar(exp)
41
41
  _, list = exp.shift 2
42
42
  val = process(list)
43
- s(:dstr, '', s(:evstr, val))
43
+ s(:dstr, "", s(:evstr, val))
44
44
  end
45
45
 
46
46
  def process_string_concat(exp)
@@ -81,7 +81,7 @@ module RipperRubyParser
81
81
  return with_line_number(content.line, s(:lit, Regexp.new(content.last, numflags)))
82
82
  end
83
83
 
84
- content.sexp_type = :dregx_once if flags =~ /o/
84
+ content.sexp_type = :dregx_once if /o/.match?(flags)
85
85
  content << numflags unless numflags == 0
86
86
  content
87
87
  end
@@ -121,11 +121,11 @@ module RipperRubyParser
121
121
 
122
122
  INTERPOLATING_HEREDOC = /^<<[-~]?[^-~']/.freeze
123
123
  NON_INTERPOLATING_HEREDOC = /^<<[-~]?'/.freeze
124
- INTERPOLATING_STRINGS = ['"', '`', ':"', /^%Q.$/, /^%.$/].freeze
124
+ INTERPOLATING_STRINGS = ['"', "`", ':"', /^%Q.$/, /^%.$/].freeze
125
125
  NON_INTERPOLATING_STRINGS = ["'", ":'", /^%q.$/].freeze
126
126
  INTERPOLATING_WORD_LIST = /^%[WI].$/.freeze
127
127
  NON_INTERPOLATING_WORD_LIST = /^%[wi].$/.freeze
128
- REGEXP_LITERALS = ['/', /^%r.$/].freeze
128
+ REGEXP_LITERALS = ["/", /^%r.$/].freeze
129
129
 
130
130
  def process_at_tstring_content(exp)
131
131
  _, content, pos, delim = exp.shift 4
@@ -166,7 +166,7 @@ module RipperRubyParser
166
166
  private
167
167
 
168
168
  def extract_string_parts(list)
169
- return nil, '', [] if list.empty?
169
+ return nil, "", [] if list.empty?
170
170
 
171
171
  list = merge_raw_string_literals list
172
172
  list = map_process_list list
@@ -184,7 +184,7 @@ module RipperRubyParser
184
184
  end
185
185
  end
186
186
 
187
- string = ''
187
+ string = ""
188
188
  while parts.first&.sexp_type == :str
189
189
  str = parts.shift
190
190
  line ||= str.line
@@ -210,12 +210,12 @@ module RipperRubyParser
210
210
  def character_flags_to_numerical(flags)
211
211
  numflags = 0
212
212
 
213
- numflags = Regexp::MULTILINE if flags =~ /m/
214
- numflags |= Regexp::EXTENDED if flags =~ /x/
215
- numflags |= Regexp::IGNORECASE if flags =~ /i/
213
+ numflags = Regexp::MULTILINE if /m/.match?(flags)
214
+ numflags |= Regexp::EXTENDED if /x/.match?(flags)
215
+ numflags |= Regexp::IGNORECASE if /i/.match?(flags)
216
216
 
217
- numflags |= Regexp::NOENCODING if flags =~ /n/
218
- numflags |= Regexp::FIXEDENCODING if flags =~ /[ues]/
217
+ numflags |= Regexp::NOENCODING if /n/.match?(flags)
218
+ numflags |= Regexp::FIXEDENCODING if /[ues]/.match?(flags)
219
219
 
220
220
  numflags
221
221
  end
@@ -260,11 +260,7 @@ module RipperRubyParser
260
260
  def handle_string_unescaping(content, delim)
261
261
  case delim
262
262
  when INTERPOLATING_HEREDOC
263
- if extra_compatible
264
- unescape(content).delete("\r")
265
- else
266
- unescape(content)
267
- end
263
+ unescape(content)
268
264
  when *INTERPOLATING_STRINGS
269
265
  unescape(content)
270
266
  when INTERPOLATING_WORD_LIST
@@ -92,9 +92,9 @@ module RipperRubyParser
92
92
  end
93
93
 
94
94
  SPECIAL_ARG_MARKER = {
95
- splat: '*',
96
- dsplat: '**',
97
- blockarg: '&'
95
+ splat: "*",
96
+ dsplat: "**",
97
+ blockarg: "&"
98
98
  }.freeze
99
99
 
100
100
  def convert_arguments(args)