ripper_ruby_parser 1.6.0 → 1.8.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -0
  3. data/README.md +8 -25
  4. data/lib/ripper_ruby_parser.rb +2 -2
  5. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +54 -23
  6. data/lib/ripper_ruby_parser/parser.rb +3 -3
  7. data/lib/ripper_ruby_parser/sexp_handlers.rb +11 -9
  8. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +10 -11
  9. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +48 -63
  10. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
  11. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +35 -2
  12. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
  13. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +4 -2
  14. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +1 -1
  15. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +24 -24
  16. data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +266 -0
  17. data/lib/ripper_ruby_parser/sexp_processor.rb +47 -78
  18. data/lib/ripper_ruby_parser/unescape.rb +79 -50
  19. data/lib/ripper_ruby_parser/version.rb +1 -1
  20. metadata +115 -78
  21. data/Rakefile +0 -33
  22. data/test/end_to_end/comments_test.rb +0 -59
  23. data/test/end_to_end/comparison_test.rb +0 -104
  24. data/test/end_to_end/lib_comparison_test.rb +0 -29
  25. data/test/end_to_end/line_numbering_test.rb +0 -64
  26. data/test/end_to_end/samples_comparison_test.rb +0 -13
  27. data/test/end_to_end/test_comparison_test.rb +0 -32
  28. data/test/pt_testcase/pt_test.rb +0 -44
  29. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -190
  30. data/test/ripper_ruby_parser/parser_test.rb +0 -469
  31. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -649
  32. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -661
  33. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
  34. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -1117
  35. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
  36. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -267
  37. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -427
  38. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -399
  39. data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -303
  40. data/test/ripper_ruby_parser/version_test.rb +0 -7
  41. data/test/samples/assignment.rb +0 -17
  42. data/test/samples/comments.rb +0 -13
  43. data/test/samples/conditionals.rb +0 -23
  44. data/test/samples/loops.rb +0 -36
  45. data/test/samples/misc.rb +0 -278
  46. data/test/samples/number.rb +0 -7
  47. data/test/samples/operators.rb +0 -18
  48. data/test/samples/strings.rb +0 -140
  49. data/test/test_helper.rb +0 -79
@@ -47,33 +47,20 @@ module RipperRubyParser
47
47
 
48
48
  def process_case(exp)
49
49
  _, expr, clauses = exp.shift 3
50
- s(:case, process(expr), *process(clauses))
50
+ s(:case, process(expr), *process(clauses).sexp_body)
51
51
  end
52
52
 
53
53
  def process_when(exp)
54
54
  _, values, truepart, falsepart = exp.shift 4
55
55
 
56
- falsepart = process(falsepart)
57
- falsepart = unwrap_nil falsepart if falsepart
58
-
59
- if falsepart.nil?
60
- falsepart = [nil]
61
- elsif falsepart.first.is_a? Symbol
62
- falsepart = s(falsepart)
63
- end
56
+ falsepart ||= s(:void_stmt)
64
57
 
58
+ falsepart = unwrap_case_body process(falsepart)
65
59
  values = process(values).sexp_body
60
+ truepart = unwrap_block process(truepart)
66
61
 
67
- truepart = map_process_list_compact truepart.sexp_body
68
- truepart = if truepart.empty?
69
- [nil]
70
- else
71
- unwrap_block(truepart.shift) + truepart
72
- end
73
-
74
- s(s(:when,
75
- s(:array, *values),
76
- *truepart),
62
+ s(:case_body,
63
+ s(:when, s(:array, *values), *truepart),
77
64
  *falsepart)
78
65
  end
79
66
 
@@ -109,6 +96,17 @@ module RipperRubyParser
109
96
  s(:if, cond, truepart, falsepart)
110
97
  end
111
98
  end
99
+
100
+ def unwrap_case_body(exp)
101
+ case exp.sexp_type
102
+ when :case_body
103
+ exp.sexp_body
104
+ when :void_stmt
105
+ [nil]
106
+ else
107
+ [exp]
108
+ end
109
+ end
112
110
  end
113
111
  end
114
112
  end
@@ -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,132 +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
- string, rest = extract_string_parts(rest)
15
-
16
- if rest.empty?
17
- 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
- string, rest = extract_string_parts(rest)
67
- if rest.empty?
68
- s(:xstr, string)
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
- return s(:lit, Regexp.new(content.last, numflags)) if content.length == 2
81
-
82
- content.sexp_type = :dregx_once if flags =~ /o/
83
- content << numflags unless numflags == 0
84
- content
85
- end
86
-
87
- def process_regexp(exp)
88
- _, *rest = shift_all exp
89
- string, rest = extract_string_parts(rest)
90
- s(:dregx, string, *rest)
91
- end
92
-
93
- def process_symbol_literal(exp)
94
- _, symbol = exp.shift 2
95
- handle_symbol_content(symbol)
96
- end
97
-
98
- def process_symbol(exp)
99
- _, node = exp.shift 2
100
- handle_symbol_content(node)
101
- end
102
-
103
- def process_dyna_symbol(exp)
104
- _, node = exp.shift 2
105
- handle_dyna_symbol_content(node)
106
- end
107
-
108
- def process_qsymbols(exp)
109
- _, *items = shift_all(exp)
110
- items = items.map { |item| handle_symbol_content(item) }
111
- s(:qsymbols, *items)
112
- end
113
-
114
- def process_symbols(exp)
115
- _, *items = shift_all(exp)
116
- items = items.map { |item| handle_dyna_symbol_content(item) }
117
- s(:symbols, *items)
118
- end
119
-
120
- INTERPOLATING_HEREDOC = /^<<[-~]?[^-~']/.freeze
121
- NON_INTERPOLATING_HEREDOC = /^<<[-~]?'/.freeze
122
- INTERPOLATING_STRINGS = ['"', '`', ':"', /^%Q.$/, /^%.$/].freeze
123
- NON_INTERPOLATING_STRINGS = ["'", ":'", /^%q.$/].freeze
124
- INTERPOLATING_WORD_LIST = /^%[WI].$/.freeze
125
- NON_INTERPOLATING_WORD_LIST = /^%[wi].$/.freeze
126
- REGEXP_LITERALS = ['/', /^%r.$/].freeze
127
-
128
- def process_at_tstring_content(exp)
129
- _, content, _, delim = exp.shift 4
130
- string = handle_string_unescaping(content, delim)
131
- string = handle_string_encoding(string, delim)
132
- s(:str, string)
7
+ # character literals
8
+ def process_at_CHAR(exp)
9
+ _, val, pos = exp.shift 3
10
+ with_position(pos, s(:str, unescape(val[1..-1])))
133
11
  end
134
12
 
135
13
  def process_array(exp)
@@ -161,136 +39,31 @@ module RipperRubyParser
161
39
  s(:kwsplat, process(param))
162
40
  end
163
41
 
164
- private
165
-
166
- def extract_string_parts(list)
167
- return '', [] if list.empty?
168
-
169
- list = merge_raw_string_literals list
170
- list = map_process_list list
171
-
172
- parts = list.flat_map do |item|
173
- type, val, *rest = item
174
- if type == :dstr
175
- if val.empty?
176
- rest
177
- else
178
- [s(:str, val), *rest]
179
- end
180
- else
181
- [item]
182
- end
183
- end
184
-
185
- string = ''
186
- while parts.first&.sexp_type == :str
187
- str = parts.shift
188
- string += str.last
189
- end
190
-
191
- return string, parts
192
- end
193
-
194
- def merge_raw_string_literals(list)
195
- chunks = list.chunk { |it| it.sexp_type == :@tstring_content }
196
- chunks.flat_map do |is_simple, items|
197
- if is_simple && items.count > 1
198
- head = items.first
199
- contents = items.map { |it| it[1] }.join
200
- [s(:@tstring_content, contents, head[2], head[3])]
201
- else
202
- items
203
- end
204
- end
205
- end
206
-
207
- def character_flags_to_numerical(flags)
208
- numflags = 0
209
-
210
- numflags = Regexp::MULTILINE if flags =~ /m/
211
- numflags |= Regexp::EXTENDED if flags =~ /x/
212
- numflags |= Regexp::IGNORECASE if flags =~ /i/
213
-
214
- numflags |= Regexp::NOENCODING if flags =~ /n/
215
- numflags |= Regexp::FIXEDENCODING if flags =~ /[ues]/
216
-
217
- numflags
218
- end
219
-
220
- def handle_dyna_symbol_content(node)
221
- type, *body = *process(node)
222
- case type
223
- when :str, :xstr
224
- s(:lit, body.first.to_sym)
225
- when :dstr, :dxstr
226
- s(:dsym, *body)
227
- end
228
- end
229
-
230
- def handle_symbol_content(node)
231
- if node.sexp_type == :'@kw'
232
- symbol, position = extract_node_symbol_with_position(node)
233
- else
234
- processed = process(node)
235
- symbol = processed.last.to_sym
236
- position = processed.line
237
- end
238
- with_line_number(position, s(:lit, symbol))
42
+ # number literals
43
+ def process_at_int(exp)
44
+ make_literal(exp) { |val| Integer(val) }
239
45
  end
240
46
 
241
- def merge_left_into_right(left, right)
242
- right[1] = left.last + right[1]
243
- right
47
+ def process_at_float(exp)
48
+ make_literal(exp, &:to_f)
244
49
  end
245
50
 
246
- def merge_right_into_left(left, right)
247
- if right.sexp_type == :str
248
- left.push right
249
- else
250
- _, first, *rest = right
251
- left.push s(:str, first) unless first.empty?
252
- left.push(*rest)
253
- end
51
+ def process_at_rational(exp)
52
+ make_literal(exp, &:to_r)
254
53
  end
255
54
 
256
- def handle_string_unescaping(content, delim)
257
- case delim
258
- when INTERPOLATING_HEREDOC
259
- if extra_compatible
260
- unescape(content).delete("\r")
261
- else
262
- unescape(content)
263
- end
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
55
+ def process_at_imaginary(exp)
56
+ make_literal(exp, &:to_c)
277
57
  end
278
58
 
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
@@ -52,10 +52,12 @@ module RipperRubyParser
52
52
  def handle_conditional_loop_mod(type, negated_type, exp)
53
53
  _, cond, body = exp.shift 3
54
54
 
55
+ cond = process(cond)
56
+ body = process(body)
55
57
  check_at_start = check_at_start?(body)
56
58
  construct_conditional_loop(type, negated_type,
57
- unwrap_begin(process(cond)),
58
- unwrap_begin(process(body)),
59
+ unwrap_begin(cond),
60
+ unwrap_begin(body),
59
61
  check_at_start)
60
62
  end
61
63
 
@@ -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
@@ -5,9 +5,9 @@ module RipperRubyParser
5
5
  # Sexp handers for method definitions and related constructs
6
6
  module Methods
7
7
  def process_def(exp)
8
- _, ident, params, body = exp.shift 4
8
+ _, ident, params, body, pos = exp.shift 5
9
9
 
10
- ident, pos = extract_node_symbol_with_position ident
10
+ ident, = extract_node_symbol_with_position ident
11
11
 
12
12
  in_method do
13
13
  params = convert_arguments(process(params))
@@ -19,7 +19,7 @@ module RipperRubyParser
19
19
  end
20
20
 
21
21
  def process_defs(exp)
22
- _, receiver, _, ident, params, body = exp.shift 6
22
+ _, receiver, _, ident, params, body, = exp.shift 7
23
23
 
24
24
  ident, = extract_node_symbol_with_position ident
25
25
 
@@ -83,36 +83,36 @@ module RipperRubyParser
83
83
 
84
84
  def method_body(exp)
85
85
  block = process exp
86
- case block.length
87
- when 0
88
- [s(:nil)]
86
+ case block.sexp_type
87
+ when :void_stmt
88
+ [s(:nil).line(block.line)]
89
89
  else
90
90
  unwrap_block block
91
91
  end
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)
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
101
+ args.line ||= args.sexp_body.first&.line
102
+ args.sexp_body = args.sexp_body.map { |item| convert_argument item }
103
+ args
104
+ end
105
+
106
+ def convert_argument(item)
107
+ case item.sexp_type
108
+ when :lvar
109
+ item.last
110
+ when *SPECIAL_ARG_MARKER.keys
111
+ convert_marked_argument(item)
112
+ when :masgn
113
+ convert_masgn_argument(item)
114
+ else
115
+ item
116
116
  end
117
117
  end
118
118