ripper_ruby_parser 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +19 -0
  3. data/README.md +2 -2
  4. data/Rakefile +1 -1
  5. data/lib/ripper_ruby_parser.rb +0 -7
  6. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +112 -34
  7. data/lib/ripper_ruby_parser/parser.rb +26 -12
  8. data/lib/ripper_ruby_parser/sexp_handlers.rb +4 -1
  9. data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +7 -6
  10. data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +4 -2
  11. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +39 -43
  12. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +93 -69
  13. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +30 -24
  14. data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +7 -9
  15. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +51 -71
  16. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +72 -56
  17. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +14 -13
  18. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +19 -13
  19. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +19 -22
  20. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +47 -35
  21. data/lib/ripper_ruby_parser/sexp_processor.rb +72 -85
  22. data/lib/ripper_ruby_parser/version.rb +1 -1
  23. data/test/end_to_end/line_numbering_test.rb +1 -1
  24. data/test/end_to_end/samples_comparison_test.rb +0 -1
  25. data/test/pt_testcase/pt_test.rb +4 -6
  26. data/test/{unit → ripper_ruby_parser}/commenting_ripper_parser_test.rb +82 -25
  27. data/test/{unit → ripper_ruby_parser}/parser_test.rb +37 -170
  28. data/test/{unit/parser_assignment_test.rb → ripper_ruby_parser/sexp_handlers/assignment_test.rb} +1 -1
  29. data/test/{unit/parser_blocks_test.rb → ripper_ruby_parser/sexp_handlers/blocks_test.rb} +267 -2
  30. data/test/{unit/parser_conditionals_test.rb → ripper_ruby_parser/sexp_handlers/conditionals_test.rb} +125 -17
  31. data/test/{unit/parser_literals_test.rb → ripper_ruby_parser/sexp_handlers/literals_test.rb} +10 -12
  32. data/test/{unit/parser_loops_test.rb → ripper_ruby_parser/sexp_handlers/loops_test.rb} +1 -1
  33. data/test/{unit/parser_method_calls_test.rb → ripper_ruby_parser/sexp_handlers/method_calls_test.rb} +10 -10
  34. data/test/{unit/parser_operators_test.rb → ripper_ruby_parser/sexp_handlers/operators_test.rb} +22 -2
  35. data/test/{unit → ripper_ruby_parser}/sexp_processor_test.rb +49 -48
  36. data/test/{unit → ripper_ruby_parser}/version_test.rb +0 -0
  37. data/test/samples/misc.rb +4 -0
  38. data/test/test_helper.rb +4 -4
  39. metadata +28 -42
  40. data/test/end_to_end/error_conditions_test.rb +0 -51
@@ -1,11 +1,12 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for operators
3
4
  module Operators
4
5
  BINARY_OPERATOR_MAP = {
5
- :"&&" => :and,
6
- :"||" => :or,
7
- :and => :and,
8
- :or => :or
6
+ '&&': :and,
7
+ '||': :or,
8
+ and: :and,
9
+ or: :or
9
10
  }.freeze
10
11
 
11
12
  UNARY_OPERATOR_MAP = {
@@ -13,10 +14,12 @@ module RipperRubyParser
13
14
  }.freeze
14
15
 
15
16
  NEGATED_BINARY_OPERATOR_MAP = {
16
- :"!~" => :=~
17
+ '!~': :=~
17
18
  }.freeze
18
19
 
19
- def process_binary exp
20
+ SHIFT_OPERATORS = [:<<, :>>].freeze
21
+
22
+ def process_binary(exp)
20
23
  _, left, op, right = exp.shift 4
21
24
 
22
25
  if op == :=~
@@ -25,37 +28,21 @@ module RipperRubyParser
25
28
  s(:not, make_regexp_match_operator(mapped, left, right))
26
29
  elsif (mapped = BINARY_OPERATOR_MAP[op])
27
30
  make_boolean_operator(mapped, left, right)
28
- else
31
+ elsif SHIFT_OPERATORS.include? op
29
32
  s(:call, process(left), op, process(right))
30
- end
31
- end
32
-
33
- def make_boolean_operator op, left, right
34
- if left.first == :paren
35
- s(op, process(left), process(right))
36
- else
37
- rebalance_binary(s(op, process(left), process(right)))
38
- end
39
- end
40
-
41
- def make_regexp_match_operator op, left, right
42
- if left.sexp_type == :regexp_literal
43
- s(:match2, process(left), process(right))
44
- elsif right.sexp_type == :regexp_literal
45
- s(:match3, process(right), process(left))
46
33
  else
47
- s(:call, process(left), op, process(right))
34
+ s(:call, handle_operator_argument(left), op, handle_operator_argument(right))
48
35
  end
49
36
  end
50
37
 
51
- def process_unary exp
38
+ def process_unary(exp)
52
39
  _, op, arg = exp.shift 3
53
- arg = process(arg)
40
+ arg = handle_operator_argument(arg)
54
41
  op = UNARY_OPERATOR_MAP[op] || op
55
42
  s(:call, arg, op)
56
43
  end
57
44
 
58
- def process_dot2 exp
45
+ def process_dot2(exp)
59
46
  _, left, right = exp.shift 3
60
47
  left = process(left)
61
48
  right = process(right)
@@ -66,7 +53,7 @@ module RipperRubyParser
66
53
  end
67
54
  end
68
55
 
69
- def process_dot3 exp
56
+ def process_dot3(exp)
70
57
  _, left, right = exp.shift 3
71
58
  left = process(left)
72
59
  right = process(right)
@@ -77,20 +64,45 @@ module RipperRubyParser
77
64
  end
78
65
  end
79
66
 
80
- def process_ifop exp
67
+ def process_ifop(exp)
81
68
  _, cond, truepart, falsepart = exp.shift 4
82
- s(:if, process(cond), process(truepart), process(falsepart))
69
+ s(:if,
70
+ handle_operator_argument(cond),
71
+ handle_operator_argument(truepart),
72
+ handle_operator_argument(falsepart))
83
73
  end
84
74
 
85
75
  private
86
76
 
87
- def rebalance_binary exp
88
- op, left, right = exp
77
+ def make_boolean_operator(op, left, right)
78
+ _, left, _, right = rebalance_binary(s(:binary, left, op, right))
79
+ s(op, process(left), handle_operator_argument(right))
80
+ end
81
+
82
+ def make_regexp_match_operator(op, left, right)
83
+ if left.sexp_type == :regexp_literal
84
+ s(:match2, process(left), process(right))
85
+ elsif right.sexp_type == :regexp_literal
86
+ s(:match3, process(right), process(left))
87
+ else
88
+ s(:call, process(left), op, process(right))
89
+ end
90
+ end
91
+
92
+ def rebalance_binary(exp)
93
+ _, left, op, right = exp
94
+ if left.sexp_type == :binary && BINARY_OPERATOR_MAP[op] == BINARY_OPERATOR_MAP[left[2]]
95
+ _, left, _, middle = rebalance_binary(left)
96
+ right = rebalance_binary(s(:binary, middle, op, right))
97
+ end
98
+ s(:binary, left, op, right)
99
+ end
89
100
 
90
- if op == left.sexp_type
91
- s(op, left[1], rebalance_binary(s(op, left[2], right)))
101
+ def handle_operator_argument(exp)
102
+ if exp.sexp_type == :begin
103
+ s(:begin, process(exp))
92
104
  else
93
- s(op, left, right)
105
+ process(exp)
94
106
  end
95
107
  end
96
108
  end
@@ -3,12 +3,13 @@ require 'ripper_ruby_parser/sexp_handlers'
3
3
 
4
4
  module RipperRubyParser
5
5
  # Processes the sexp created by Ripper to what RubyParser would produce.
6
+ #
7
+ # @api private
6
8
  class SexpProcessor < ::SexpProcessor
7
- attr_accessor :filename
8
- attr_accessor :extra_compatible
9
+ attr_reader :filename
9
10
 
10
- def initialize
11
- super
11
+ def initialize(filename: nil)
12
+ super()
12
13
 
13
14
  # TODO: Find these automatically
14
15
 
@@ -28,36 +29,29 @@ module RipperRubyParser
28
29
 
29
30
  @processors[:@tstring_content] = :process_at_tstring_content
30
31
 
32
+ @filename = filename
33
+
31
34
  @errors = []
32
35
 
33
36
  @in_method_body = false
34
37
  end
35
38
 
36
- def process exp
37
- return nil if exp.nil?
38
-
39
- result = super
40
- trickle_up_line_numbers result
41
- trickle_down_line_numbers result
42
- end
43
-
44
39
  include SexpHandlers
45
40
 
46
- def process_program exp
41
+ def process_program(exp)
47
42
  _, content = exp.shift 2
48
43
 
49
- statements = content.map { |sub_exp| process(sub_exp) }
50
- safe_wrap_in_block statements
44
+ process content
51
45
  end
52
46
 
53
- def process_module exp
47
+ def process_module(exp)
54
48
  _, const_ref, body = exp.shift 3
55
49
  const, line = const_ref_to_const_with_line_number const_ref
56
50
  with_line_number(line,
57
51
  s(:module, const, *class_or_module_body(body)))
58
52
  end
59
53
 
60
- def process_class exp
54
+ def process_class(exp)
61
55
  _, const_ref, parent, body = exp.shift 4
62
56
  const, line = const_ref_to_const_with_line_number const_ref
63
57
  parent = process(parent)
@@ -65,125 +59,144 @@ module RipperRubyParser
65
59
  s(:class, const, parent, *class_or_module_body(body)))
66
60
  end
67
61
 
68
- def process_sclass exp
62
+ def process_sclass(exp)
69
63
  _, klass, block = exp.shift 3
70
64
  s(:sclass, process(klass), *class_or_module_body(block))
71
65
  end
72
66
 
73
- def process_var_ref exp
67
+ def process_stmts(exp)
68
+ _, *statements = shift_all(exp)
69
+ statements = reject_void_stmt map_process_list statements
70
+ case statements.count
71
+ when 0
72
+ s(:void_stmt)
73
+ when 1
74
+ statements.first
75
+ else
76
+ first = statements.shift
77
+ if first.sexp_type == :block
78
+ first.shift
79
+ s(:block, *first, *statements)
80
+ else
81
+ s(:block, first, *statements)
82
+ end
83
+ end
84
+ end
85
+
86
+ def process_var_ref(exp)
74
87
  _, contents = exp.shift 2
75
88
  process(contents)
76
89
  end
77
90
 
78
- def process_var_field exp
91
+ def process_var_field(exp)
79
92
  _, contents = exp.shift 2
80
93
  process(contents)
81
94
  end
82
95
 
83
- def process_var_alias exp
96
+ def process_var_alias(exp)
84
97
  _, left, right = exp.shift 3
85
98
  s(:valias, left[1].to_sym, right[1].to_sym)
86
99
  end
87
100
 
88
- def process_const_path_ref exp
101
+ def process_const_path_ref(exp)
89
102
  _, left, right = exp.shift 3
90
103
  s(:colon2, process(left), extract_node_symbol(right))
91
104
  end
92
105
 
93
- def process_const_path_field exp
106
+ def process_const_path_field(exp)
94
107
  s(:const, process_const_path_ref(exp))
95
108
  end
96
109
 
97
- def process_const_ref exp
110
+ def process_const_ref(exp)
98
111
  _, ref = exp.shift 3
99
112
  process(ref)
100
113
  end
101
114
 
102
- def process_top_const_ref exp
115
+ def process_top_const_ref(exp)
103
116
  _, ref = exp.shift 2
104
117
  s(:colon3, extract_node_symbol(ref))
105
118
  end
106
119
 
107
- def process_top_const_field exp
120
+ def process_top_const_field(exp)
108
121
  s(:const, process_top_const_ref(exp))
109
122
  end
110
123
 
111
- def process_paren exp
124
+ def process_paren(exp)
112
125
  _, body = exp.shift 2
113
- if body.empty?
114
- s()
115
- elsif body.first.is_a? Symbol
116
- process body
126
+ result = process body
127
+ if result.sexp_type == :void_stmt
128
+ s(:nil)
117
129
  else
118
- body.map! { |it| convert_void_stmt_to_nil process it }
119
- safe_wrap_in_block body
130
+ result
120
131
  end
121
132
  end
122
133
 
123
- def process_comment exp
134
+ def process_comment(exp)
124
135
  _, comment, inner = exp.shift 3
125
136
  sexp = process(inner)
126
137
  sexp.comments = comment
127
138
  sexp
128
139
  end
129
140
 
130
- def process_BEGIN exp
141
+ def process_BEGIN(exp)
131
142
  _, body = exp.shift 2
132
- s(:iter, s(:preexe), s(:args), *map_body(body))
143
+ s(:iter, s(:preexe), s(:args), *map_process_sexp_body_compact(body))
133
144
  end
134
145
 
135
- def process_END exp
146
+ def process_END(exp)
136
147
  _, body = exp.shift 2
137
- s(:iter, s(:postexe), 0, *map_body(body))
148
+ s(:iter, s(:postexe), 0, *map_process_sexp_body_compact(body))
138
149
  end
139
150
 
140
151
  # number literals
141
- def process_at_int exp
152
+ def process_at_int(exp)
142
153
  make_literal(exp) { |val| Integer(val) }
143
154
  end
144
155
 
145
- def process_at_float exp
156
+ def process_at_float(exp)
146
157
  make_literal(exp, &:to_f)
147
158
  end
148
159
 
149
160
  # character literals
150
- def process_at_CHAR exp
161
+ def process_at_CHAR(exp)
151
162
  _, val, pos = exp.shift 3
152
163
  with_position(pos, s(:str, unescape(val[1..-1])))
153
164
  end
154
165
 
155
- def process_at_label exp
166
+ def process_at_label(exp)
156
167
  make_literal(exp) { |val| val.chop.to_sym }
157
168
  end
158
169
 
159
170
  # symbol-like sexps
160
- def process_at_const exp
171
+ def process_at_const(exp)
161
172
  make_identifier(:const, exp)
162
173
  end
163
174
 
164
- def process_at_cvar exp
175
+ def process_at_cvar(exp)
165
176
  make_identifier(:cvar, exp)
166
177
  end
167
178
 
168
- def process_at_gvar exp
179
+ def process_at_gvar(exp)
169
180
  make_identifier(:gvar, exp)
170
181
  end
171
182
 
172
- def process_at_ivar exp
183
+ def process_at_ivar(exp)
173
184
  make_identifier(:ivar, exp)
174
185
  end
175
186
 
176
- def process_at_ident exp
187
+ def process_at_ident(exp)
177
188
  make_identifier(:lvar, exp)
178
189
  end
179
190
 
180
- def process_at_op exp
191
+ def process_at_op(exp)
181
192
  make_identifier(:op, exp)
182
193
  end
183
194
 
184
- def process_at_kw exp
195
+ def process_at_kw(exp)
185
196
  sym, pos = extract_node_symbol_with_position(exp)
186
197
  result = case sym
198
+ when :__ENCODING__
199
+ s(:colon2, s(:const, :Encoding), :UTF_8)
187
200
  when :__FILE__
188
201
  s(:str, @filename)
189
202
  when :__LINE__
@@ -194,7 +207,7 @@ module RipperRubyParser
194
207
  with_position(pos, result)
195
208
  end
196
209
 
197
- def process_at_backref exp
210
+ def process_at_backref(exp)
198
211
  _, str, pos = exp.shift 3
199
212
  name = str[1..-1]
200
213
  with_position pos do
@@ -208,59 +221,33 @@ module RipperRubyParser
208
221
 
209
222
  private
210
223
 
211
- def const_ref_to_const_with_line_number const_ref
224
+ def const_ref_to_const_with_line_number(const_ref)
212
225
  const = process(const_ref)
213
226
  line = const.line
214
227
  const = const[1] if const.sexp_type == :const
215
228
  return const, line
216
229
  end
217
230
 
218
- def class_or_module_body exp
231
+ def class_or_module_body(exp)
219
232
  body = process(exp)
220
233
 
221
- if body.length == 1 && body.first.sexp_type == :block
222
- body = body.first
223
- body.shift
234
+ return body if body.empty?
235
+ if body.sexp_type == :block
236
+ body.sexp_body
237
+ else
238
+ [body]
224
239
  end
225
-
226
- body
227
240
  end
228
241
 
229
- def make_identifier type, exp
242
+ def make_identifier(type, exp)
230
243
  with_position_from_node_symbol(exp) do |ident|
231
244
  s(type, ident)
232
245
  end
233
246
  end
234
247
 
235
- def make_literal exp
248
+ def make_literal(exp)
236
249
  _, val, pos = exp.shift 3
237
250
  with_position(pos, s(:lit, yield(val)))
238
251
  end
239
-
240
- def trickle_up_line_numbers exp
241
- exp.each do |sub_exp|
242
- if sub_exp.is_a? Sexp
243
- trickle_up_line_numbers sub_exp
244
- exp.line ||= sub_exp.line
245
- end
246
- end
247
- end
248
-
249
- def trickle_down_line_numbers exp
250
- exp.each do |sub_exp|
251
- if sub_exp.is_a? Sexp
252
- sub_exp.line ||= exp.line
253
- trickle_down_line_numbers sub_exp
254
- end
255
- end
256
- end
257
-
258
- def convert_void_stmt_to_nil sexp
259
- if sexp == s(:void_stmt)
260
- s(:nil)
261
- else
262
- sexp
263
- end
264
- end
265
252
  end
266
253
  end
@@ -1,3 +1,3 @@
1
1
  module RipperRubyParser
2
- VERSION = '1.1.2'.freeze
2
+ VERSION = '1.2.0'.freeze
3
3
  end