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,14 +1,13 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for literals, except hash and array literals
3
4
  module Literals
4
- def process_string_literal exp
5
+ def process_string_literal(exp)
5
6
  _, content = exp.shift 2
6
7
  process(content)
7
8
  end
8
9
 
9
- def process_string_content exp
10
- exp.shift
11
-
10
+ def process_string_content(exp)
12
11
  string, rest = extract_unescaped_string_parts exp
13
12
 
14
13
  if rest.empty?
@@ -18,9 +17,13 @@ module RipperRubyParser
18
17
  end
19
18
  end
20
19
 
21
- def process_string_embexpr exp
20
+ alias process_word process_string_content
21
+
22
+ def process_string_embexpr(exp)
22
23
  _, list = exp.shift 2
23
- val = process(list.first)
24
+
25
+ val = process(list.sexp_body.first)
26
+
24
27
  case val.sexp_type
25
28
  when :str
26
29
  val
@@ -31,30 +34,26 @@ module RipperRubyParser
31
34
  end
32
35
  end
33
36
 
34
- def process_string_dvar exp
37
+ def process_string_dvar(exp)
35
38
  _, list = exp.shift 2
36
39
  val = process(list)
37
40
  s(:dstr, '', s(:evstr, val))
38
41
  end
39
42
 
40
- def process_string_concat exp
43
+ def process_string_concat(exp)
41
44
  _, left, right = exp.shift 3
42
45
 
43
46
  left = process(left)
44
47
  right = process(right)
45
48
 
46
49
  if left.sexp_type == :str
47
- right[1] = left[1] + right[1]
48
- right
49
- else # Expecting left.sexp_type == :dstr
50
- _, first, *rest = right
51
- left.push s(:str, first) if !first.empty? || rest.empty?
52
- left.push(*rest)
53
- left
50
+ merge_left_into_right(left, right)
51
+ else
52
+ merge_right_into_left(left, right)
54
53
  end
55
54
  end
56
55
 
57
- def process_xstring_literal exp
56
+ def process_xstring_literal(exp)
58
57
  _, content = exp.shift 2
59
58
  string, rest = extract_unescaped_string_parts content
60
59
  if rest.empty?
@@ -64,8 +63,8 @@ module RipperRubyParser
64
63
  end
65
64
  end
66
65
 
67
- def process_regexp_literal exp
68
- _, content, (_, flags, _) = exp.shift 3
66
+ def process_regexp_literal(exp)
67
+ _, content, (_, flags,) = exp.shift 3
69
68
 
70
69
  string, rest = extract_string_parts content
71
70
  numflags = character_flags_to_numerical flags
@@ -83,39 +82,41 @@ module RipperRubyParser
83
82
  end
84
83
  end
85
84
 
86
- def process_symbol_literal exp
85
+ def process_symbol_literal(exp)
87
86
  _, symbol = exp.shift 2
88
87
  process(symbol)
89
88
  end
90
89
 
91
- def process_symbol exp
90
+ def process_symbol(exp)
92
91
  _, node = exp.shift 2
93
- with_position_from_node_symbol(node) { |sym| s(:lit, sym) }
92
+ handle_symbol_content(node)
94
93
  end
95
94
 
96
- def process_dyna_symbol exp
97
- _, list = exp.shift 2
95
+ def process_dyna_symbol(exp)
96
+ _, node = exp.shift 2
97
+ handle_dyna_symbol_content(node)
98
+ end
98
99
 
99
- if list.sexp_type == :string_content
100
- string, rest = extract_unescaped_string_parts list.sexp_body
101
- else
102
- string, rest = extract_unescaped_string_parts list
103
- end
104
- if rest.empty?
105
- s(:lit, string.to_sym)
106
- else
107
- s(:dsym, string, *rest)
108
- end
100
+ def process_qsymbols(exp)
101
+ _, *items = shift_all(exp)
102
+ items = items.map { |item| handle_symbol_content(item) }
103
+ s(:qsymbols, *items)
109
104
  end
110
105
 
111
- def process_at_tstring_content exp
112
- _, string, _ = exp.shift 3
106
+ def process_symbols(exp)
107
+ _, *items = shift_all(exp)
108
+ items = items.map { |item| handle_dyna_symbol_content(item) }
109
+ s(:symbols, *items)
110
+ end
111
+
112
+ def process_at_tstring_content(exp)
113
+ _, string, = exp.shift 3
113
114
  s(:str, string)
114
115
  end
115
116
 
116
117
  private
117
118
 
118
- def extract_string_parts exp
119
+ def extract_string_parts(exp)
119
120
  parts = internal_process_string_parts(exp)
120
121
 
121
122
  string = ''
@@ -129,31 +130,18 @@ module RipperRubyParser
129
130
  return string, rest
130
131
  end
131
132
 
132
- def internal_process_string_parts exp
133
- rest = []
134
-
135
- until exp.empty?
136
- part = exp.shift
137
- result = if part.is_a? String
138
- # FIXME: Extract escaping into separate method
139
- s(:str, part.inspect[1..-2])
140
- else
141
- process(part)
142
- end
143
- rest << result
144
- end
145
- rest
133
+ def internal_process_string_parts(exp)
134
+ _, *rest = shift_all exp
135
+ map_process_list rest
146
136
  end
147
137
 
148
- def extract_unescaped_string_parts exp
138
+ def extract_unescaped_string_parts(exp)
149
139
  string, rest = extract_string_parts exp
150
140
 
151
141
  string = unescape(string)
152
142
 
153
143
  rest.each do |sub_exp|
154
- if sub_exp.sexp_type == :str
155
- sub_exp[1] = unescape(sub_exp[1])
156
- end
144
+ sub_exp[1] = unescape(sub_exp[1]) if sub_exp.sexp_type == :str
157
145
  end
158
146
 
159
147
  return string, rest
@@ -174,7 +162,7 @@ module RipperRubyParser
174
162
  SINGLE_LETTER_ESCAPES_REGEXP =
175
163
  Regexp.new("^[#{SINGLE_LETTER_ESCAPES.keys.join}]$")
176
164
 
177
- def unescape string
165
+ def unescape(string)
178
166
  string.gsub(/\\(
179
167
  [0-7]{1,3} | # octal character
180
168
  x[0-9a-fA-F]{1,2} | # hex byte
@@ -210,7 +198,7 @@ module RipperRubyParser
210
198
  end
211
199
  end
212
200
 
213
- def character_flags_to_numerical flags
201
+ def character_flags_to_numerical(flags)
214
202
  numflags = 0
215
203
 
216
204
  flags =~ /m/ and numflags |= Regexp::MULTILINE
@@ -222,6 +210,34 @@ module RipperRubyParser
222
210
 
223
211
  numflags
224
212
  end
213
+
214
+ def handle_dyna_symbol_content(list)
215
+ string, rest = extract_unescaped_string_parts list
216
+ if rest.empty?
217
+ s(:lit, string.to_sym)
218
+ else
219
+ s(:dsym, string, *rest)
220
+ end
221
+ end
222
+
223
+ def handle_symbol_content(node)
224
+ with_position_from_node_symbol(node) { |sym| s(:lit, sym) }
225
+ end
226
+
227
+ def merge_left_into_right(left, right)
228
+ right[1] = left[1] + right[1]
229
+ right
230
+ end
231
+
232
+ def merge_right_into_left(left, right)
233
+ if right.sexp_type == :str
234
+ left.push right
235
+ else
236
+ _, first, *rest = right
237
+ left.push s(:str, first) unless first.empty?
238
+ left.push(*rest)
239
+ end
240
+ end
225
241
  end
226
242
  end
227
243
  end
@@ -1,50 +1,51 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for loops
3
4
  module Loops
4
- def process_until exp
5
+ def process_until(exp)
5
6
  handle_conditional_loop :until, :while, exp
6
7
  end
7
8
 
8
- def process_until_mod exp
9
+ def process_until_mod(exp)
9
10
  handle_conditional_loop_mod :until, :while, exp
10
11
  end
11
12
 
12
- def process_while exp
13
+ def process_while(exp)
13
14
  handle_conditional_loop :while, :until, exp
14
15
  end
15
16
 
16
- def process_while_mod exp
17
+ def process_while_mod(exp)
17
18
  handle_conditional_loop_mod :while, :until, exp
18
19
  end
19
20
 
20
- def process_for exp
21
+ def process_for(exp)
21
22
  _, var, coll, block = exp.shift 4
22
23
  coll = process(coll)
23
24
  assgn = s(:lasgn, process(var)[1])
24
- block = wrap_in_block(map_body(block))
25
- if block.nil?
26
- s(:for, coll, assgn)
27
- else
25
+ block = unwrap_nil process(block)
26
+ if block
28
27
  s(:for, coll, assgn, block)
28
+ else
29
+ s(:for, coll, assgn)
29
30
  end
30
31
  end
31
32
 
32
33
  private
33
34
 
34
- def check_at_start? block
35
+ def check_at_start?(block)
35
36
  block.sexp_type != :begin
36
37
  end
37
38
 
38
- def handle_conditional_loop type, negated_type, exp
39
+ def handle_conditional_loop(type, negated_type, exp)
39
40
  _, cond, body = exp.shift 3
40
41
 
41
42
  construct_conditional_loop(type, negated_type,
42
43
  process(cond),
43
- wrap_in_block(map_body(body)),
44
+ unwrap_nil(process(body)),
44
45
  true)
45
46
  end
46
47
 
47
- def handle_conditional_loop_mod type, negated_type, exp
48
+ def handle_conditional_loop_mod(type, negated_type, exp)
48
49
  _, cond, body = exp.shift 3
49
50
 
50
51
  check_at_start = check_at_start?(body)
@@ -1,7 +1,8 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handlers for method calls
3
4
  module MethodCalls
4
- def process_method_add_arg exp
5
+ def process_method_add_arg(exp)
5
6
  _, call, parens = exp.shift 3
6
7
  call = process(call)
7
8
  unless parens.empty?
@@ -15,20 +16,25 @@ module RipperRubyParser
15
16
  end
16
17
 
17
18
  CALL_OP_MAP = {
18
- :'.' => :call,
19
- :'::' => :call,
20
- :'&.' => :safe_call
21
- }
19
+ '.': :call,
20
+ '::': :call,
21
+ '&.': :safe_call
22
+ }.freeze
22
23
 
23
- def process_call exp
24
+ def process_call(exp)
24
25
  _, receiver, op, ident = exp.shift 4
25
26
  type = CALL_OP_MAP.fetch op
26
- with_position_from_node_symbol(ident) do |method|
27
- s(type, process(receiver), method)
27
+ case ident
28
+ when :call
29
+ s(type, process(receiver), :call)
30
+ else
31
+ with_position_from_node_symbol(ident) do |method|
32
+ s(type, process(receiver), method)
33
+ end
28
34
  end
29
35
  end
30
36
 
31
- def process_command exp
37
+ def process_command(exp)
32
38
  _, ident, arglist = exp.shift 3
33
39
  with_position_from_node_symbol(ident) do |method|
34
40
  args = handle_argument_list(arglist)
@@ -36,7 +42,7 @@ module RipperRubyParser
36
42
  end
37
43
  end
38
44
 
39
- def process_command_call exp
45
+ def process_command_call(exp)
40
46
  _, receiver, op, ident, arguments = exp.shift 5
41
47
  type = CALL_OP_MAP.fetch op
42
48
  with_position_from_node_symbol(ident) do |method|
@@ -45,21 +51,21 @@ module RipperRubyParser
45
51
  end
46
52
  end
47
53
 
48
- def process_vcall exp
54
+ def process_vcall(exp)
49
55
  _, ident = exp.shift 2
50
56
  with_position_from_node_symbol(ident) do |method|
51
57
  s(:call, nil, method)
52
58
  end
53
59
  end
54
60
 
55
- def process_fcall exp
61
+ def process_fcall(exp)
56
62
  _, ident = exp.shift 2
57
63
  with_position_from_node_symbol(ident) do |method|
58
64
  s(:call, nil, method)
59
65
  end
60
66
  end
61
67
 
62
- def process_super exp
68
+ def process_super(exp)
63
69
  _, args = exp.shift 2
64
70
  args = process(args)
65
71
  args.shift
@@ -1,7 +1,8 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
+ # Sexp handers for method definitions and related constructs
3
4
  module Methods
4
- def process_def exp
5
+ def process_def(exp)
5
6
  _, ident, params, body = exp.shift 4
6
7
  ident, pos = extract_node_symbol_with_position ident
7
8
  params = convert_special_args(process(params))
@@ -9,7 +10,7 @@ module RipperRubyParser
9
10
  s(:defn, ident, params, *method_body(body)))
10
11
  end
11
12
 
12
- def process_defs exp
13
+ def process_defs(exp)
13
14
  _, receiver, _, method, params, body = exp.shift 6
14
15
  params = convert_special_args(process(params))
15
16
 
@@ -19,31 +20,27 @@ module RipperRubyParser
19
20
  params, *method_body(body))
20
21
  end
21
22
 
22
- def process_return exp
23
+ def process_return(exp)
23
24
  _, arglist = exp.shift 2
24
25
  s(:return, handle_return_argument_list(arglist))
25
26
  end
26
27
 
27
- def process_return0 exp
28
+ def process_return0(exp)
28
29
  _ = exp.shift
29
30
  s(:return)
30
31
  end
31
32
 
32
- def process_yield exp
33
+ def process_yield(exp)
33
34
  _, arglist = exp.shift 2
34
- args = handle_potentially_typeless_sexp(arglist)
35
- if args.sexp_type == :arglist
36
- args = args[1..-1]
37
- end
38
- s(:yield, *args)
35
+ s(:yield, *handle_argument_list(arglist))
39
36
  end
40
37
 
41
- def process_yield0 exp
38
+ def process_yield0(exp)
42
39
  _ = exp.shift
43
40
  s(:yield)
44
41
  end
45
42
 
46
- def process_undef exp
43
+ def process_undef(exp)
47
44
  _, args = exp.shift 2
48
45
 
49
46
  args.map! do |sub_exp|
@@ -57,7 +54,7 @@ module RipperRubyParser
57
54
  end
58
55
  end
59
56
 
60
- def process_alias exp
57
+ def process_alias(exp)
61
58
  _, left, right = exp.shift 3
62
59
 
63
60
  s(:alias,
@@ -74,22 +71,22 @@ module RipperRubyParser
74
71
  result
75
72
  end
76
73
 
77
- def make_method_name_literal exp
74
+ def make_method_name_literal(exp)
78
75
  process(exp).tap { |it| it[0] = :lit }
79
76
  end
80
77
 
81
- def method_body exp
78
+ def method_body(exp)
82
79
  block = in_method { process exp }
83
80
  case block.length
84
81
  when 0
85
- block.push s(:nil)
86
- when 1
87
- if block.first.sexp_type == :block
88
- block = block.first
89
- block.shift
82
+ [s(:nil)]
83
+ else
84
+ if block.sexp_type == :block
85
+ block.sexp_body
86
+ else
87
+ [block]
90
88
  end
91
89
  end
92
- block
93
90
  end
94
91
 
95
92
  SPECIAL_ARG_MARKER = {
@@ -98,7 +95,7 @@ module RipperRubyParser
98
95
  blockarg: '&'
99
96
  }.freeze
100
97
 
101
- def convert_special_args args
98
+ def convert_special_args(args)
102
99
  args.map! do |item|
103
100
  if item.is_a? Symbol
104
101
  item