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,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