ripper_ruby_parser 1.1.2 → 1.2.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 (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,94 +1,87 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for blocks and related constructs
3
4
  module Blocks
4
- def process_method_add_block exp
5
+ def process_method_add_block(exp)
5
6
  _, call, block = exp.shift 3
6
7
  block = process(block)
7
- args = block[1]
8
- stmt = block[2].first
8
+ _, args, stmt = block
9
9
  call = process(call)
10
- make_iter call, args, stmt
10
+ stmts = stmt.first || s()
11
+ make_iter call, args, stmts
11
12
  end
12
13
 
13
- def process_brace_block exp
14
+ def process_brace_block(exp)
14
15
  handle_generic_block exp
15
16
  end
16
17
 
17
- def process_do_block exp
18
+ def process_do_block(exp)
18
19
  handle_generic_block exp
19
20
  end
20
21
 
21
- def process_params exp
22
- if exp.size == 6
23
- _, normal, defaults, splat, rest, block = exp.shift 6
24
- else
25
- _, normal, defaults, splat, rest, kwargs, doublesplat, block = exp.shift 8
26
- end
22
+ def process_params(exp)
23
+ _, normal, defaults, splat, rest, kwargs, doublesplat, block = exp.shift 8
27
24
 
28
25
  args = []
29
- args += normal.map { |id| process(id) } if normal
30
- args += defaults.map { |sym, val| s(:lasgn, process(sym)[1], process(val)) } if defaults
31
-
32
- args << process(splat) unless splat.nil? || splat == 0
33
- args += rest.map { |it| process(it) } if rest
34
- args += handle_kwargs kwargs if kwargs
35
- args << s(:dsplat, process(doublesplat)) if doublesplat
36
- args << process(block) unless block.nil?
26
+ args += handle_normal_arguments normal
27
+ args += handle_default_arguments defaults
28
+ args += handle_splat splat
29
+ args += handle_normal_arguments rest
30
+ args += handle_kwargs kwargs
31
+ args += handle_double_splat doublesplat
32
+ args += handle_block_argument block
37
33
 
38
34
  s(:args, *args)
39
35
  end
40
36
 
41
- def process_block_var exp
42
- _, args, _ = exp.shift 3
37
+ def process_kwrest_param(exp)
38
+ _, sym, = exp.shift 3
39
+ process(sym)
40
+ end
41
+
42
+ def process_block_var(exp)
43
+ _, args, = exp.shift 3
43
44
 
44
45
  names = process(args)
45
46
 
46
47
  convert_special_args names
47
48
  end
48
49
 
49
- def process_begin exp
50
+ def process_begin(exp)
50
51
  _, body = exp.shift 2
51
52
 
52
53
  body = process(body)
53
- strip_typeless_sexp(body)
54
+ convert_empty_to_nil_symbol(body)
54
55
  end
55
56
 
56
- def process_rescue exp
57
+ def process_rescue(exp)
57
58
  _, eclass, evar, block, after = exp.shift 5
58
- rescue_block = map_body(block)
59
+ rescue_block = map_process_sexp_body_compact(block)
59
60
  rescue_block << nil if rescue_block.empty?
60
61
 
61
62
  arr = []
62
63
  if eclass
63
- eclass = handle_potentially_typeless_sexp eclass
64
64
  if eclass.first.is_a? Symbol
65
- arr += eclass[1..-1]
65
+ arr += process(eclass).sexp_body
66
66
  else
67
- arr << eclass[0]
67
+ arr << process(eclass[0])
68
68
  end
69
69
  end
70
70
 
71
- if evar
72
- arr << create_assignment_sub_type(process(evar), s(:gvar, :$!))
73
- end
71
+ arr << create_assignment_sub_type(process(evar), s(:gvar, :$!)) if evar
74
72
 
75
73
  s(
76
74
  s(:resbody, s(:array, *arr), *rescue_block),
77
75
  *process(after))
78
76
  end
79
77
 
80
- def process_bodystmt exp
81
- _, body, rescue_block, else_block, ensure_block = exp.shift 5
82
-
83
- body = map_body body
78
+ def process_bodystmt(exp)
79
+ _, main, rescue_block, else_block, ensure_block = exp.shift 5
84
80
 
85
- body = wrap_in_block(body)
81
+ body = s()
86
82
 
87
- body = if body.nil?
88
- s()
89
- else
90
- s(body)
91
- end
83
+ main = wrap_in_block map_process_sexp_body_compact(main)
84
+ body << main if main
92
85
 
93
86
  if rescue_block
94
87
  body.push(*process(rescue_block))
@@ -103,65 +96,77 @@ module RipperRubyParser
103
96
  body = s(s(:ensure, *body))
104
97
  end
105
98
 
106
- body = wrap_in_block(body)
107
-
108
- body = if body.nil?
109
- s()
110
- else
111
- s(body)
112
- end
113
-
114
- body
99
+ wrap_in_block(body) || s()
115
100
  end
116
101
 
117
- def process_rescue_mod exp
102
+ def process_rescue_mod(exp)
118
103
  _, scary, safe = exp.shift 3
119
104
  s(:rescue, process(scary), s(:resbody, s(:array), process(safe)))
120
105
  end
121
106
 
122
- def process_ensure exp
107
+ def process_ensure(exp)
123
108
  _, block = exp.shift 2
124
- strip_typeless_sexp safe_wrap_in_block map_body(block)
109
+ convert_empty_to_nil_symbol safe_unwrap_void_stmt process(block)
125
110
  end
126
111
 
127
- def process_next exp
112
+ def process_next(exp)
128
113
  _, args = exp.shift 2
114
+ args = handle_return_argument_list(args)
129
115
  if args.empty?
130
116
  s(:next)
131
117
  else
132
- s(:next, handle_return_argument_list(args))
118
+ s(:next, args)
133
119
  end
134
120
  end
135
121
 
136
- def process_break exp
122
+ def process_break(exp)
137
123
  _, args = exp.shift 2
124
+ args = handle_return_argument_list(args)
138
125
  if args.empty?
139
126
  s(:break)
140
127
  else
141
- s(:break, handle_return_argument_list(args))
128
+ s(:break, args)
142
129
  end
143
130
  end
144
131
 
145
- def process_lambda exp
132
+ def process_lambda(exp)
146
133
  _, args, statements = exp.shift 3
147
134
  old_type = args.sexp_type
148
135
  args = convert_special_args(process(args))
149
136
  args = 0 if args == s(:args) && old_type == :params
150
137
  make_iter(s(:call, nil, :lambda),
151
138
  args,
152
- wrap_in_block(map_body(statements)))
139
+ safe_unwrap_void_stmt(process(statements)))
153
140
  end
154
141
 
155
142
  private
156
143
 
157
- def handle_generic_block exp
158
- _, args, stmts = exp.shift 3
144
+ def handle_generic_block(exp)
145
+ type, args, stmts = exp.shift 3
159
146
  args = process(args)
160
- # FIXME: Symbol :block is irrelevant.
161
- s(:block, args, s(wrap_in_block(map_body(stmts))))
147
+ s(type, args, s(unwrap_nil(process(stmts))))
148
+ end
149
+
150
+ def handle_normal_arguments(normal)
151
+ return [] unless normal
152
+ map_process_list normal
153
+ end
154
+
155
+ def handle_default_arguments(defaults)
156
+ return [] unless defaults
157
+ defaults.map { |sym, val| s(:lasgn, process(sym)[1], process(val)) }
158
+ end
159
+
160
+ def handle_splat(splat)
161
+ if splat && splat != 0
162
+ [process(splat)]
163
+ else
164
+ []
165
+ end
162
166
  end
163
167
 
164
168
  def handle_kwargs(kwargs)
169
+ return [] unless kwargs
165
170
  kwargs.map do |sym, val|
166
171
  symbol = process(sym)[1]
167
172
  if val
@@ -172,25 +177,44 @@ module RipperRubyParser
172
177
  end
173
178
  end
174
179
 
175
- def strip_typeless_sexp block
180
+ def handle_double_splat(doublesplat)
181
+ return [] unless doublesplat
182
+ [s(:dsplat, process(doublesplat))]
183
+ end
184
+
185
+ def handle_block_argument(block)
186
+ return [] unless block
187
+ [process(block)]
188
+ end
189
+
190
+ def convert_empty_to_nil_symbol(block)
176
191
  case block.length
177
192
  when 0
178
193
  s(:nil)
179
- when 1
180
- block[0]
181
194
  else
182
195
  block
183
196
  end
184
197
  end
185
198
 
186
- def make_iter call, args, stmt
199
+ def make_iter(call, args, stmt)
187
200
  args ||= 0
188
- if stmt.nil?
201
+ if stmt.empty?
189
202
  s(:iter, call, args)
190
203
  else
191
204
  s(:iter, call, args, stmt)
192
205
  end
193
206
  end
207
+
208
+ def wrap_in_block(statements)
209
+ case statements.length
210
+ when 0
211
+ nil
212
+ when 1
213
+ statements.first
214
+ else
215
+ s(:block, *statements)
216
+ end
217
+ end
194
218
  end
195
219
  end
196
220
  end
@@ -1,23 +1,25 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for conditionals
3
4
  module Conditionals
4
- def process_if exp
5
+ def process_if(exp)
5
6
  _, cond, truepart, falsepart = exp.shift 4
6
7
 
7
8
  construct_conditional(handle_condition(cond),
8
- wrap_in_block(map_body(truepart)),
9
- process(falsepart))
9
+ handle_consequent(truepart),
10
+ handle_consequent(falsepart))
10
11
  end
11
12
 
12
- def process_elsif exp
13
+ def process_elsif(exp)
13
14
  _, cond, truepart, falsepart = exp.shift 4
14
15
 
15
- s(:if, process(cond),
16
- wrap_in_block(map_body(truepart)),
17
- process(falsepart))
16
+ s(:if,
17
+ process(cond),
18
+ handle_consequent(truepart),
19
+ handle_consequent(falsepart))
18
20
  end
19
21
 
20
- def process_if_mod exp
22
+ def process_if_mod(exp)
21
23
  _, cond, truepart = exp.shift 3
22
24
 
23
25
  construct_conditional(handle_condition(cond),
@@ -25,15 +27,15 @@ module RipperRubyParser
25
27
  nil)
26
28
  end
27
29
 
28
- def process_unless exp
30
+ def process_unless(exp)
29
31
  _, cond, truepart, falsepart = exp.shift 4
30
32
 
31
33
  construct_conditional(handle_condition(cond),
32
- process(falsepart),
33
- wrap_in_block(map_body(truepart)))
34
+ handle_consequent(falsepart),
35
+ handle_consequent(truepart))
34
36
  end
35
37
 
36
- def process_unless_mod exp
38
+ def process_unless_mod(exp)
37
39
  _, cond, truepart = exp.shift 3
38
40
 
39
41
  construct_conditional(handle_condition(cond),
@@ -41,27 +43,27 @@ module RipperRubyParser
41
43
  process(truepart))
42
44
  end
43
45
 
44
- def process_case exp
46
+ def process_case(exp)
45
47
  _, expr, clauses = exp.shift 3
46
48
  s(:case, process(expr), *process(clauses))
47
49
  end
48
50
 
49
- def process_when exp
51
+ def process_when(exp)
50
52
  _, values, truepart, falsepart = exp.shift 4
51
53
 
54
+ falsepart = process(falsepart)
55
+ falsepart = unwrap_nil falsepart if falsepart
56
+
52
57
  if falsepart.nil?
53
58
  falsepart = [nil]
54
- else
55
- falsepart = process(falsepart)
56
- if falsepart.first.is_a? Symbol
57
- falsepart = s(falsepart)
58
- end
59
+ elsif falsepart.first.is_a? Symbol
60
+ falsepart = s(falsepart)
59
61
  end
60
62
  falsepart = [nil] if falsepart.empty?
61
63
 
62
- values = handle_array_elements values
64
+ values = handle_argument_list values
63
65
 
64
- truepart = map_body(truepart)
66
+ truepart = map_process_sexp_body_compact(truepart)
65
67
  truepart = [nil] if truepart.empty?
66
68
 
67
69
  s(s(:when,
@@ -70,14 +72,14 @@ module RipperRubyParser
70
72
  *falsepart)
71
73
  end
72
74
 
73
- def process_else exp
75
+ def process_else(exp)
74
76
  _, body = exp.shift 2
75
- safe_wrap_in_block(map_body(body))
77
+ process(body)
76
78
  end
77
79
 
78
80
  private
79
81
 
80
- def handle_condition cond
82
+ def handle_condition(cond)
81
83
  cond = process(cond)
82
84
  if (cond.sexp_type == :lit) && cond[1].is_a?(Regexp)
83
85
  s(:match, cond)
@@ -90,6 +92,10 @@ module RipperRubyParser
90
92
  end
91
93
  end
92
94
 
95
+ def handle_consequent(exp)
96
+ unwrap_nil process(exp) if exp
97
+ end
98
+
93
99
  def construct_conditional(cond, truepart, falsepart)
94
100
  if cond.sexp_type == :not
95
101
  _, inner = cond
@@ -1,5 +1,6 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for hash literals
3
4
  module Hashes
4
5
  # Handle hash literals sexps. These can be either empty, or contain a
5
6
  # nested :assoclist_from_args Sexp.
@@ -8,7 +9,7 @@ module RipperRubyParser
8
9
  # s(:hash, nil)
9
10
  # @example Hash with contents
10
11
  # s(:hash, s(:assoclist_from_args, ...))
11
- def process_hash exp
12
+ def process_hash(exp)
12
13
  _, body = exp.shift 2
13
14
  return s(:hash) unless body
14
15
  _, elems = body
@@ -17,13 +18,13 @@ module RipperRubyParser
17
18
 
18
19
  # @example
19
20
  # s(:assoc_splat, s(:vcall, s(:@ident, "bar")))
20
- def process_assoc_splat exp
21
+ def process_assoc_splat(exp)
21
22
  _, param = exp.shift 2
22
23
  s(:kwsplat, process(param))
23
24
  end
24
25
 
25
26
  # Handle implied hashes, such as at the end of argument lists.
26
- def process_bare_assoc_hash exp
27
+ def process_bare_assoc_hash(exp)
27
28
  _, elems = exp.shift 2
28
29
  s(:hash, *make_hash_items(elems))
29
30
  end
@@ -31,16 +32,13 @@ module RipperRubyParser
31
32
  private
32
33
 
33
34
  # Process list of items that can be either :assoc_new or :assoc_splat
34
- def make_hash_items elems
35
+ def make_hash_items(elems)
35
36
  result = s()
36
37
  elems.each do |sub_exp|
37
- case sub_exp.sexp_type
38
- when :assoc_new
38
+ if sub_exp.sexp_type == :assoc_new
39
39
  sub_exp.sexp_body.each { |elem| result << process(elem) }
40
- when :assoc_splat
40
+ else # :assoc_splat
41
41
  result << process(sub_exp)
42
- else
43
- raise ArgumentError
44
42
  end
45
43
  end
46
44
  result
@@ -1,104 +1,85 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Utility methods used in several of the sexp handler modules
3
4
  module HelperMethods
4
- def handle_potentially_typeless_sexp exp
5
- if exp.nil?
6
- s()
7
- elsif exp.first.is_a? Symbol
8
- process(exp)
9
- else
10
- exp.map! { |sub_exp| handle_potentially_typeless_sexp(sub_exp) }
11
- end
12
- end
13
-
14
- def handle_argument_list exp
15
- if exp.nil?
16
- s()
17
- elsif exp.first.is_a? Symbol
18
- process(exp).tap(&:shift)
19
- else
20
- exp.map! { |sub_exp| process(sub_exp) }
21
- end
22
- end
23
-
24
- def extract_node_symbol_with_position exp
25
- return nil if exp.nil?
26
- return exp if exp.is_a? Symbol
27
-
5
+ def extract_node_symbol_with_position(exp)
28
6
  _, ident, pos = exp.shift 3
29
7
  return ident.to_sym, pos
30
8
  end
31
9
 
32
- def extract_node_symbol exp
10
+ def extract_node_symbol(exp)
33
11
  return nil if exp.nil?
34
- _, ident, _ = exp.shift 3
12
+ _, ident, = exp.shift 3
35
13
  ident.to_sym
36
14
  end
37
15
 
38
- def with_position pos, exp = nil
39
- (line, _) = pos
16
+ def with_position(pos, exp = nil)
17
+ (line,) = pos
40
18
  exp = yield if exp.nil?
41
19
  with_line_number line, exp
42
20
  end
43
21
 
44
- def with_line_number line, exp
22
+ def with_line_number(line, exp)
45
23
  exp.line = line
46
24
  exp
47
25
  end
48
26
 
49
- def with_position_from_node_symbol exp
27
+ def with_position_from_node_symbol(exp)
50
28
  sym, pos = extract_node_symbol_with_position exp
51
29
  with_position(pos, yield(sym))
52
30
  end
53
31
 
54
- def generic_add_star exp
55
- _, args, splatarg = exp.shift 3
56
- items = handle_potentially_typeless_sexp args
57
- items << s(:splat, process(splatarg))
58
- items << process(exp.shift) until exp.empty?
59
- items
32
+ def generic_add_star(exp)
33
+ _, args, splatarg, *rest = shift_all exp
34
+ items = process args
35
+ items.push s(:splat, process(splatarg))
36
+ items.push(*map_process_list(rest))
60
37
  end
61
38
 
62
- def literal? exp
39
+ def literal?(exp)
63
40
  exp.sexp_type == :lit
64
41
  end
65
42
 
66
- def map_body body
67
- body.
68
- map { |sub_exp| process(sub_exp) }.
69
- reject { |sub_exp| sub_exp.sexp_type == :void_stmt }
43
+ def reject_void_stmt(body)
44
+ body.reject { |sub_exp| sub_exp.sexp_type == :void_stmt }
70
45
  end
71
46
 
72
- def wrap_in_block statements
73
- case statements.length
74
- when 0
47
+ def map_process_sexp_body_compact(list)
48
+ reject_void_stmt map_process_sexp_body list
49
+ end
50
+
51
+ def map_process_sexp_body(list)
52
+ map_process_list(list.sexp_body)
53
+ end
54
+
55
+ def map_process_list(list)
56
+ list.map { |exp| process(exp) }
57
+ end
58
+
59
+ def unwrap_nil(exp)
60
+ if exp.sexp_type == :void_stmt
75
61
  nil
76
- when 1
77
- statements.first
78
62
  else
79
- first = statements.shift
80
- if first.sexp_type == :block
81
- first.shift
82
- s(:block, *first, *statements)
83
- else
84
- s(:block, first, *statements)
85
- end
63
+ exp
86
64
  end
87
65
  end
88
66
 
89
- def safe_wrap_in_block statements
90
- result = wrap_in_block statements
91
- result ? result : s()
67
+ def safe_unwrap_void_stmt(exp)
68
+ unwrap_nil(exp) || s()
92
69
  end
93
70
 
94
- def handle_return_argument_list arglist
95
- args = handle_potentially_typeless_sexp(arglist)
96
- if args.sexp_type == :arglist
97
- args = args[1..-1]
98
- end
71
+ def handle_argument_list(exp)
72
+ process(exp).tap(&:shift)
73
+ end
99
74
 
100
- if args.length == 1
101
- arg = args[0]
75
+ def handle_return_argument_list(arglist)
76
+ args = handle_argument_list(arglist)
77
+
78
+ case args.length
79
+ when 0
80
+ args
81
+ when 1
82
+ arg = args.first
102
83
  if arg.sexp_type == :splat
103
84
  s(:svalue, arg)
104
85
  else
@@ -109,14 +90,13 @@ module RipperRubyParser
109
90
  end
110
91
  end
111
92
 
112
- def handle_array_elements elems
113
- elems = handle_potentially_typeless_sexp(elems)
114
- elems.map do |elem|
115
- if elem.first.is_a? Symbol
116
- elem
117
- else
118
- elem.first
119
- end
93
+ def handle_array_elements(elems)
94
+ process(elems).sexp_body
95
+ end
96
+
97
+ def shift_all(exp)
98
+ [].tap do |result|
99
+ result << exp.shift until exp.empty?
120
100
  end
121
101
  end
122
102
  end