ripper_ruby_parser 1.7.0 → 1.9.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/README.md +6 -4
  4. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +24 -12
  5. data/lib/ripper_ruby_parser/sexp_handlers.rb +2 -0
  6. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +9 -4
  7. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +40 -52
  8. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
  9. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +35 -2
  10. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
  11. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +9 -5
  12. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +22 -17
  13. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +3 -3
  14. data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +256 -0
  15. data/lib/ripper_ruby_parser/sexp_processor.rb +12 -56
  16. data/lib/ripper_ruby_parser/unescape.rb +89 -43
  17. data/lib/ripper_ruby_parser/version.rb +1 -1
  18. metadata +125 -76
  19. data/Rakefile +0 -33
  20. data/test/end_to_end/comments_test.rb +0 -59
  21. data/test/end_to_end/comparison_test.rb +0 -104
  22. data/test/end_to_end/lib_comparison_test.rb +0 -29
  23. data/test/end_to_end/line_numbering_test.rb +0 -31
  24. data/test/end_to_end/samples_comparison_test.rb +0 -13
  25. data/test/end_to_end/test_comparison_test.rb +0 -32
  26. data/test/pt_testcase/pt_test.rb +0 -44
  27. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -200
  28. data/test/ripper_ruby_parser/parser_test.rb +0 -553
  29. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -613
  30. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -679
  31. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
  32. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -1106
  33. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
  34. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -267
  35. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -421
  36. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -399
  37. data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -303
  38. data/test/ripper_ruby_parser/version_test.rb +0 -7
  39. data/test/samples/assignment.rb +0 -17
  40. data/test/samples/comments.rb +0 -13
  41. data/test/samples/conditionals.rb +0 -23
  42. data/test/samples/lambdas.rb +0 -5
  43. data/test/samples/loops.rb +0 -36
  44. data/test/samples/misc.rb +0 -281
  45. data/test/samples/number.rb +0 -7
  46. data/test/samples/operators.rb +0 -18
  47. data/test/samples/strings.rb +0 -147
  48. data/test/test_helper.rb +0 -107
@@ -41,7 +41,7 @@ module RipperRubyParser
41
41
  end
42
42
 
43
43
  def integer_literal?(exp)
44
- exp.sexp_type == :lit && exp[1].is_a?(Integer)
44
+ exp && exp.sexp_type == :lit && exp[1].is_a?(Integer)
45
45
  end
46
46
 
47
47
  def reject_void_stmt(body)
@@ -81,13 +81,46 @@ module RipperRubyParser
81
81
  end
82
82
 
83
83
  def unwrap_block(exp)
84
- if exp.sexp_type == :block
84
+ case exp.sexp_type
85
+ when :block
85
86
  exp.sexp_body
87
+ when :void_stmt
88
+ [nil]
86
89
  else
87
90
  [exp]
88
91
  end
89
92
  end
90
93
 
94
+ def wrap_in_block(statements, line)
95
+ case statements.length
96
+ when 0
97
+ s(:void_stmt).line(line)
98
+ when 1
99
+ statements.first
100
+ else
101
+ first = statements.shift
102
+ s(:block, *unwrap_block(first), *statements)
103
+ end
104
+ end
105
+
106
+ def convert_void_stmt_to_nil_symbol(block)
107
+ case block.sexp_type
108
+ when :void_stmt
109
+ s(:nil)
110
+ else
111
+ block
112
+ end
113
+ end
114
+
115
+ def convert_empty_to_nil_symbol(block)
116
+ case block.length
117
+ when 0
118
+ s(:nil)
119
+ else
120
+ block
121
+ end
122
+ end
123
+
91
124
  def handle_return_argument_list(arglist)
92
125
  args = process(arglist).sexp_body
93
126
 
@@ -4,134 +4,10 @@ module RipperRubyParser
4
4
  module SexpHandlers
5
5
  # Sexp handlers for literals
6
6
  module Literals
7
- def process_string_literal(exp)
8
- _, content = exp.shift 2
9
- process(content)
10
- end
11
-
12
- def process_string_content(exp)
13
- _, *rest = shift_all exp
14
- line, string, rest = extract_string_parts(rest)
15
-
16
- if rest.empty?
17
- with_line_number(line, s(:str, string))
18
- else
19
- s(:dstr, string, *rest)
20
- end
21
- end
22
-
23
- alias process_word process_string_content
24
-
25
- def process_string_embexpr(exp)
26
- _, list = exp.shift 2
27
-
28
- val = process(list.sexp_body.first)
29
-
30
- case val.sexp_type
31
- when :str, :dstr
32
- val
33
- when :void_stmt
34
- s(:dstr, "", s(:evstr))
35
- else
36
- s(:dstr, "", s(:evstr, val))
37
- end
38
- end
39
-
40
- def process_string_dvar(exp)
41
- _, list = exp.shift 2
42
- val = process(list)
43
- s(:dstr, "", s(:evstr, val))
44
- end
45
-
46
- def process_string_concat(exp)
47
- _, left, right = exp.shift 3
48
-
49
- left = process(left)
50
- right = process(right)
51
-
52
- if left.sexp_type == :str
53
- merge_left_into_right(left, right)
54
- else
55
- merge_right_into_left(left, right)
56
- end
57
- end
58
-
59
- def process_xstring_literal(exp)
60
- _, content = exp.shift 2
61
- process(content)
62
- end
63
-
64
- def process_xstring(exp)
65
- _, *rest = shift_all exp
66
- line, string, rest = extract_string_parts(rest)
67
- if rest.empty?
68
- s(:xstr, string).line(line)
69
- else
70
- s(:dxstr, string, *rest)
71
- end
72
- end
73
-
74
- def process_regexp_literal(exp)
75
- _, content, (_, flags,) = exp.shift 3
76
-
77
- content = process(content)
78
- numflags = character_flags_to_numerical flags
79
-
80
- if content.length == 2
81
- return with_line_number(content.line, s(:lit, Regexp.new(content.last, numflags)))
82
- end
83
-
84
- content.sexp_type = :dregx_once if /o/.match?(flags)
85
- content << numflags unless numflags == 0
86
- content
87
- end
88
-
89
- def process_regexp(exp)
90
- _, *rest = shift_all exp
91
- line, string, rest = extract_string_parts(rest)
92
- with_line_number(line, s(:dregx, string, *rest))
93
- end
94
-
95
- def process_symbol_literal(exp)
96
- _, symbol = exp.shift 2
97
- handle_symbol_content(symbol)
98
- end
99
-
100
- def process_symbol(exp)
101
- _, node = exp.shift 2
102
- handle_symbol_content(node)
103
- end
104
-
105
- def process_dyna_symbol(exp)
106
- _, node = exp.shift 2
107
- handle_dyna_symbol_content(node)
108
- end
109
-
110
- def process_qsymbols(exp)
111
- _, *items = shift_all(exp)
112
- items = items.map { |item| handle_symbol_content(item) }
113
- s(:qsymbols, *items)
114
- end
115
-
116
- def process_symbols(exp)
117
- _, *items = shift_all(exp)
118
- items = items.map { |item| handle_dyna_symbol_content(item) }
119
- s(:symbols, *items)
120
- end
121
-
122
- INTERPOLATING_HEREDOC = /^<<[-~]?[^-~']/.freeze
123
- NON_INTERPOLATING_HEREDOC = /^<<[-~]?'/.freeze
124
- INTERPOLATING_STRINGS = ['"', "`", ':"', /^%Q.$/, /^%.$/].freeze
125
- NON_INTERPOLATING_STRINGS = ["'", ":'", /^%q.$/].freeze
126
- INTERPOLATING_WORD_LIST = /^%[WI].$/.freeze
127
- NON_INTERPOLATING_WORD_LIST = /^%[wi].$/.freeze
128
- REGEXP_LITERALS = ["/", /^%r.$/].freeze
129
-
130
- def process_at_tstring_content(exp)
131
- _, content, pos, delim = exp.shift 4
132
- string = handle_string_unescaping(content, delim)
133
- string = handle_string_encoding(string, delim)
134
- with_position(pos, s(:str, string))
7
+ # character literals
8
+ def process_at_CHAR(exp)
9
+ _, val, pos = exp.shift 3
10
+ with_position(pos, s(:str, fix_encoding(unescape(val[1..-1]))))
135
11
  end
136
12
 
137
13
  def process_array(exp)
@@ -163,134 +39,31 @@ module RipperRubyParser
163
39
  s(:kwsplat, process(param))
164
40
  end
165
41
 
166
- private
167
-
168
- def extract_string_parts(list)
169
- return nil, "", [] if list.empty?
170
-
171
- list = merge_raw_string_literals list
172
- list = map_process_list list
173
-
174
- parts = list.flat_map do |item|
175
- type, val, *rest = item
176
- if type == :dstr
177
- if val.empty?
178
- rest
179
- else
180
- [s(:str, val), *rest]
181
- end
182
- else
183
- [item]
184
- end
185
- end
186
-
187
- string = ""
188
- while parts.first&.sexp_type == :str
189
- str = parts.shift
190
- line ||= str.line
191
- string += str.last
192
- end
193
-
194
- return line, string, parts
195
- end
196
-
197
- def merge_raw_string_literals(list)
198
- chunks = list.chunk { |it| it.sexp_type == :@tstring_content }
199
- chunks.flat_map do |is_simple, items|
200
- if is_simple && items.count > 1
201
- head = items.first
202
- contents = items.map { |it| it[1] }.join
203
- [s(:@tstring_content, contents, head[2], head[3])]
204
- else
205
- items
206
- end
207
- end
208
- end
209
-
210
- def character_flags_to_numerical(flags)
211
- numflags = 0
212
-
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
-
217
- numflags |= Regexp::NOENCODING if /n/.match?(flags)
218
- numflags |= Regexp::FIXEDENCODING if /[ues]/.match?(flags)
219
-
220
- numflags
221
- end
222
-
223
- def handle_dyna_symbol_content(node)
224
- type, *body = *process(node)
225
- case type
226
- when :str, :xstr
227
- s(:lit, body.first.to_sym)
228
- when :dstr, :dxstr
229
- s(:dsym, *body)
230
- end
42
+ # number literals
43
+ def process_at_int(exp)
44
+ make_literal(exp) { |val| Integer(val) }
231
45
  end
232
46
 
233
- def handle_symbol_content(node)
234
- if node.sexp_type == :'@kw'
235
- symbol, position = extract_node_symbol_with_position(node)
236
- with_position(position, s(:lit, symbol))
237
- else
238
- processed = process(node)
239
- symbol = processed.last.to_sym
240
- line = processed.line
241
- with_line_number(line, s(:lit, symbol))
242
- end
47
+ def process_at_float(exp)
48
+ make_literal(exp, &:to_f)
243
49
  end
244
50
 
245
- def merge_left_into_right(left, right)
246
- right[1] = left.last + right[1]
247
- right
51
+ def process_at_rational(exp)
52
+ make_literal(exp, &:to_r)
248
53
  end
249
54
 
250
- def merge_right_into_left(left, right)
251
- if right.sexp_type == :str
252
- left.push right
253
- else
254
- _, first, *rest = right
255
- left.push s(:str, first) unless first.empty?
256
- left.push(*rest)
257
- end
55
+ def process_at_imaginary(exp)
56
+ make_literal(exp, &:to_c)
258
57
  end
259
58
 
260
- def handle_string_unescaping(content, delim)
261
- case delim
262
- when INTERPOLATING_HEREDOC
263
- unescape(content)
264
- when *INTERPOLATING_STRINGS
265
- unescape(content)
266
- when INTERPOLATING_WORD_LIST
267
- unescape_wordlist_word(content)
268
- when *NON_INTERPOLATING_STRINGS
269
- simple_unescape(content)
270
- when *REGEXP_LITERALS
271
- unescape_regexp(content)
272
- when NON_INTERPOLATING_WORD_LIST
273
- simple_unescape_wordlist_word(content)
274
- else
275
- content
276
- end
277
- end
278
-
279
- def handle_string_encoding(string, delim)
280
- case delim
281
- when INTERPOLATING_HEREDOC, INTERPOLATING_WORD_LIST, *INTERPOLATING_STRINGS
282
- fix_encoding string
283
- else
284
- string
285
- end
286
- end
59
+ private
287
60
 
288
61
  # Process list of items that can be either :assoc_new or :assoc_splat
289
62
  def make_hash_items(elems)
290
63
  result = s()
291
64
  elems.each do |sub_exp|
292
65
  if sub_exp.sexp_type == :assoc_new
293
- sub_exp.sexp_body.each { |elem| result << process(elem) }
66
+ result += process(sub_exp).sexp_body
294
67
  else # :assoc_splat
295
68
  result << process(sub_exp)
296
69
  end
@@ -17,7 +17,7 @@ module RipperRubyParser
17
17
 
18
18
  def process_arg_paren(exp)
19
19
  _, args = exp.shift 2
20
- return s() if args.nil?
20
+ return s(:arglist) if args.nil?
21
21
 
22
22
  process(args)
23
23
  end
@@ -26,7 +26,11 @@ module RipperRubyParser
26
26
  _, call, parens = exp.shift 3
27
27
  call = process(call)
28
28
  parens = process(parens)
29
- call.push(*parens.sexp_body)
29
+ if parens.sexp_type == :forward_args
30
+ call.push(parens)
31
+ else
32
+ call.push(*parens.sexp_body)
33
+ end
30
34
  end
31
35
 
32
36
  # Handle implied hashes, such as at the end of argument lists.
@@ -36,9 +40,9 @@ module RipperRubyParser
36
40
  end
37
41
 
38
42
  CALL_OP_MAP = {
39
- '.': :call,
40
- '::': :call,
41
- '&.': :safe_call
43
+ ".": :call,
44
+ "::": :call,
45
+ "&.": :safe_call
42
46
  }.freeze
43
47
 
44
48
  def process_call(exp)
@@ -72,6 +72,11 @@ module RipperRubyParser
72
72
  s(:alias, process(left), process(right))
73
73
  end
74
74
 
75
+ def process_args_forward(exp)
76
+ _ = exp.shift
77
+ s(:forward_args)
78
+ end
79
+
75
80
  private
76
81
 
77
82
  def in_method
@@ -83,8 +88,8 @@ module RipperRubyParser
83
88
 
84
89
  def method_body(exp)
85
90
  block = process exp
86
- case block.length
87
- when 0
91
+ case block.sexp_type
92
+ when :void_stmt
88
93
  [s(:nil).line(block.line)]
89
94
  else
90
95
  unwrap_block block
@@ -98,21 +103,21 @@ module RipperRubyParser
98
103
  }.freeze
99
104
 
100
105
  def convert_arguments(args)
101
- args.map! do |item|
102
- if item.is_a? Symbol
103
- item
104
- else
105
- case item.sexp_type
106
- when :lvar
107
- item.last
108
- when *SPECIAL_ARG_MARKER.keys
109
- convert_marked_argument(item)
110
- when :masgn
111
- convert_masgn_argument(item)
112
- else
113
- item
114
- end
115
- end
106
+ args.line ||= args.sexp_body.first&.line
107
+ args.sexp_body = args.sexp_body.map { |item| convert_argument item }
108
+ args
109
+ end
110
+
111
+ def convert_argument(item)
112
+ case item.sexp_type
113
+ when :lvar
114
+ item.last
115
+ when *SPECIAL_ARG_MARKER.keys
116
+ convert_marked_argument(item)
117
+ when :masgn
118
+ convert_masgn_argument(item)
119
+ else
120
+ item
116
121
  end
117
122
  end
118
123
 
@@ -5,8 +5,8 @@ module RipperRubyParser
5
5
  # Sexp handlers for operators
6
6
  module Operators
7
7
  BINARY_OPERATOR_MAP = {
8
- '&&': :and,
9
- '||': :or,
8
+ "&&": :and,
9
+ "||": :or,
10
10
  and: :and,
11
11
  or: :or
12
12
  }.freeze
@@ -16,7 +16,7 @@ module RipperRubyParser
16
16
  }.freeze
17
17
 
18
18
  NEGATED_BINARY_OPERATOR_MAP = {
19
- '!~': :=~
19
+ "!~": :=~
20
20
  }.freeze
21
21
 
22
22
  SHIFT_OPERATORS = [:<<, :>>].freeze