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