ripper_ruby_parser 1.6.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
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