ripper_ruby_parser 1.7.0 → 1.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +76 -0
- data/README.md +6 -4
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +24 -12
- data/lib/ripper_ruby_parser/sexp_handlers.rb +2 -0
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +9 -4
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +40 -52
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +35 -2
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +9 -5
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +22 -17
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +3 -3
- data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +256 -0
- data/lib/ripper_ruby_parser/sexp_processor.rb +12 -56
- data/lib/ripper_ruby_parser/unescape.rb +89 -43
- data/lib/ripper_ruby_parser/version.rb +1 -1
- metadata +125 -76
- data/Rakefile +0 -33
- data/test/end_to_end/comments_test.rb +0 -59
- data/test/end_to_end/comparison_test.rb +0 -104
- data/test/end_to_end/lib_comparison_test.rb +0 -29
- data/test/end_to_end/line_numbering_test.rb +0 -31
- data/test/end_to_end/samples_comparison_test.rb +0 -13
- data/test/end_to_end/test_comparison_test.rb +0 -32
- data/test/pt_testcase/pt_test.rb +0 -44
- data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -200
- data/test/ripper_ruby_parser/parser_test.rb +0 -553
- data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -613
- data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -679
- data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
- data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -1106
- data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
- data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -267
- data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -421
- data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -399
- data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -303
- data/test/ripper_ruby_parser/version_test.rb +0 -7
- data/test/samples/assignment.rb +0 -17
- data/test/samples/comments.rb +0 -13
- data/test/samples/conditionals.rb +0 -23
- data/test/samples/lambdas.rb +0 -5
- data/test/samples/loops.rb +0 -36
- data/test/samples/misc.rb +0 -281
- data/test/samples/number.rb +0 -7
- data/test/samples/operators.rb +0 -18
- data/test/samples/strings.rb +0 -147
- data/test/test_helper.rb +0 -107
@@ -41,7 +41,7 @@ module RipperRubyParser
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def integer_literal?(exp)
|
44
|
-
exp.sexp_type == :lit && exp[1].is_a?(Integer)
|
44
|
+
exp && exp.sexp_type == :lit && exp[1].is_a?(Integer)
|
45
45
|
end
|
46
46
|
|
47
47
|
def reject_void_stmt(body)
|
@@ -81,13 +81,46 @@ module RipperRubyParser
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def unwrap_block(exp)
|
84
|
-
|
84
|
+
case exp.sexp_type
|
85
|
+
when :block
|
85
86
|
exp.sexp_body
|
87
|
+
when :void_stmt
|
88
|
+
[nil]
|
86
89
|
else
|
87
90
|
[exp]
|
88
91
|
end
|
89
92
|
end
|
90
93
|
|
94
|
+
def wrap_in_block(statements, line)
|
95
|
+
case statements.length
|
96
|
+
when 0
|
97
|
+
s(:void_stmt).line(line)
|
98
|
+
when 1
|
99
|
+
statements.first
|
100
|
+
else
|
101
|
+
first = statements.shift
|
102
|
+
s(:block, *unwrap_block(first), *statements)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def convert_void_stmt_to_nil_symbol(block)
|
107
|
+
case block.sexp_type
|
108
|
+
when :void_stmt
|
109
|
+
s(:nil)
|
110
|
+
else
|
111
|
+
block
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def convert_empty_to_nil_symbol(block)
|
116
|
+
case block.length
|
117
|
+
when 0
|
118
|
+
s(:nil)
|
119
|
+
else
|
120
|
+
block
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
91
124
|
def handle_return_argument_list(arglist)
|
92
125
|
args = process(arglist).sexp_body
|
93
126
|
|
@@ -4,134 +4,10 @@ module RipperRubyParser
|
|
4
4
|
module SexpHandlers
|
5
5
|
# Sexp handlers for literals
|
6
6
|
module Literals
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def process_string_content(exp)
|
13
|
-
_, *rest = shift_all exp
|
14
|
-
line, string, rest = extract_string_parts(rest)
|
15
|
-
|
16
|
-
if rest.empty?
|
17
|
-
with_line_number(line, s(:str, string))
|
18
|
-
else
|
19
|
-
s(:dstr, string, *rest)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
alias process_word process_string_content
|
24
|
-
|
25
|
-
def process_string_embexpr(exp)
|
26
|
-
_, list = exp.shift 2
|
27
|
-
|
28
|
-
val = process(list.sexp_body.first)
|
29
|
-
|
30
|
-
case val.sexp_type
|
31
|
-
when :str, :dstr
|
32
|
-
val
|
33
|
-
when :void_stmt
|
34
|
-
s(:dstr, "", s(:evstr))
|
35
|
-
else
|
36
|
-
s(:dstr, "", s(:evstr, val))
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def process_string_dvar(exp)
|
41
|
-
_, list = exp.shift 2
|
42
|
-
val = process(list)
|
43
|
-
s(:dstr, "", s(:evstr, val))
|
44
|
-
end
|
45
|
-
|
46
|
-
def process_string_concat(exp)
|
47
|
-
_, left, right = exp.shift 3
|
48
|
-
|
49
|
-
left = process(left)
|
50
|
-
right = process(right)
|
51
|
-
|
52
|
-
if left.sexp_type == :str
|
53
|
-
merge_left_into_right(left, right)
|
54
|
-
else
|
55
|
-
merge_right_into_left(left, right)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def process_xstring_literal(exp)
|
60
|
-
_, content = exp.shift 2
|
61
|
-
process(content)
|
62
|
-
end
|
63
|
-
|
64
|
-
def process_xstring(exp)
|
65
|
-
_, *rest = shift_all exp
|
66
|
-
line, string, rest = extract_string_parts(rest)
|
67
|
-
if rest.empty?
|
68
|
-
s(:xstr, string).line(line)
|
69
|
-
else
|
70
|
-
s(:dxstr, string, *rest)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def process_regexp_literal(exp)
|
75
|
-
_, content, (_, flags,) = exp.shift 3
|
76
|
-
|
77
|
-
content = process(content)
|
78
|
-
numflags = character_flags_to_numerical flags
|
79
|
-
|
80
|
-
if content.length == 2
|
81
|
-
return with_line_number(content.line, s(:lit, Regexp.new(content.last, numflags)))
|
82
|
-
end
|
83
|
-
|
84
|
-
content.sexp_type = :dregx_once if /o/.match?(flags)
|
85
|
-
content << numflags unless numflags == 0
|
86
|
-
content
|
87
|
-
end
|
88
|
-
|
89
|
-
def process_regexp(exp)
|
90
|
-
_, *rest = shift_all exp
|
91
|
-
line, string, rest = extract_string_parts(rest)
|
92
|
-
with_line_number(line, s(:dregx, string, *rest))
|
93
|
-
end
|
94
|
-
|
95
|
-
def process_symbol_literal(exp)
|
96
|
-
_, symbol = exp.shift 2
|
97
|
-
handle_symbol_content(symbol)
|
98
|
-
end
|
99
|
-
|
100
|
-
def process_symbol(exp)
|
101
|
-
_, node = exp.shift 2
|
102
|
-
handle_symbol_content(node)
|
103
|
-
end
|
104
|
-
|
105
|
-
def process_dyna_symbol(exp)
|
106
|
-
_, node = exp.shift 2
|
107
|
-
handle_dyna_symbol_content(node)
|
108
|
-
end
|
109
|
-
|
110
|
-
def process_qsymbols(exp)
|
111
|
-
_, *items = shift_all(exp)
|
112
|
-
items = items.map { |item| handle_symbol_content(item) }
|
113
|
-
s(:qsymbols, *items)
|
114
|
-
end
|
115
|
-
|
116
|
-
def process_symbols(exp)
|
117
|
-
_, *items = shift_all(exp)
|
118
|
-
items = items.map { |item| handle_dyna_symbol_content(item) }
|
119
|
-
s(:symbols, *items)
|
120
|
-
end
|
121
|
-
|
122
|
-
INTERPOLATING_HEREDOC = /^<<[-~]?[^-~']/.freeze
|
123
|
-
NON_INTERPOLATING_HEREDOC = /^<<[-~]?'/.freeze
|
124
|
-
INTERPOLATING_STRINGS = ['"', "`", ':"', /^%Q.$/, /^%.$/].freeze
|
125
|
-
NON_INTERPOLATING_STRINGS = ["'", ":'", /^%q.$/].freeze
|
126
|
-
INTERPOLATING_WORD_LIST = /^%[WI].$/.freeze
|
127
|
-
NON_INTERPOLATING_WORD_LIST = /^%[wi].$/.freeze
|
128
|
-
REGEXP_LITERALS = ["/", /^%r.$/].freeze
|
129
|
-
|
130
|
-
def process_at_tstring_content(exp)
|
131
|
-
_, content, pos, delim = exp.shift 4
|
132
|
-
string = handle_string_unescaping(content, delim)
|
133
|
-
string = handle_string_encoding(string, delim)
|
134
|
-
with_position(pos, s(:str, string))
|
7
|
+
# character literals
|
8
|
+
def process_at_CHAR(exp)
|
9
|
+
_, val, pos = exp.shift 3
|
10
|
+
with_position(pos, s(:str, fix_encoding(unescape(val[1..-1]))))
|
135
11
|
end
|
136
12
|
|
137
13
|
def process_array(exp)
|
@@ -163,134 +39,31 @@ module RipperRubyParser
|
|
163
39
|
s(:kwsplat, process(param))
|
164
40
|
end
|
165
41
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
return nil, "", [] if list.empty?
|
170
|
-
|
171
|
-
list = merge_raw_string_literals list
|
172
|
-
list = map_process_list list
|
173
|
-
|
174
|
-
parts = list.flat_map do |item|
|
175
|
-
type, val, *rest = item
|
176
|
-
if type == :dstr
|
177
|
-
if val.empty?
|
178
|
-
rest
|
179
|
-
else
|
180
|
-
[s(:str, val), *rest]
|
181
|
-
end
|
182
|
-
else
|
183
|
-
[item]
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
string = ""
|
188
|
-
while parts.first&.sexp_type == :str
|
189
|
-
str = parts.shift
|
190
|
-
line ||= str.line
|
191
|
-
string += str.last
|
192
|
-
end
|
193
|
-
|
194
|
-
return line, string, parts
|
195
|
-
end
|
196
|
-
|
197
|
-
def merge_raw_string_literals(list)
|
198
|
-
chunks = list.chunk { |it| it.sexp_type == :@tstring_content }
|
199
|
-
chunks.flat_map do |is_simple, items|
|
200
|
-
if is_simple && items.count > 1
|
201
|
-
head = items.first
|
202
|
-
contents = items.map { |it| it[1] }.join
|
203
|
-
[s(:@tstring_content, contents, head[2], head[3])]
|
204
|
-
else
|
205
|
-
items
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def character_flags_to_numerical(flags)
|
211
|
-
numflags = 0
|
212
|
-
|
213
|
-
numflags = Regexp::MULTILINE if /m/.match?(flags)
|
214
|
-
numflags |= Regexp::EXTENDED if /x/.match?(flags)
|
215
|
-
numflags |= Regexp::IGNORECASE if /i/.match?(flags)
|
216
|
-
|
217
|
-
numflags |= Regexp::NOENCODING if /n/.match?(flags)
|
218
|
-
numflags |= Regexp::FIXEDENCODING if /[ues]/.match?(flags)
|
219
|
-
|
220
|
-
numflags
|
221
|
-
end
|
222
|
-
|
223
|
-
def handle_dyna_symbol_content(node)
|
224
|
-
type, *body = *process(node)
|
225
|
-
case type
|
226
|
-
when :str, :xstr
|
227
|
-
s(:lit, body.first.to_sym)
|
228
|
-
when :dstr, :dxstr
|
229
|
-
s(:dsym, *body)
|
230
|
-
end
|
42
|
+
# number literals
|
43
|
+
def process_at_int(exp)
|
44
|
+
make_literal(exp) { |val| Integer(val) }
|
231
45
|
end
|
232
46
|
|
233
|
-
def
|
234
|
-
|
235
|
-
symbol, position = extract_node_symbol_with_position(node)
|
236
|
-
with_position(position, s(:lit, symbol))
|
237
|
-
else
|
238
|
-
processed = process(node)
|
239
|
-
symbol = processed.last.to_sym
|
240
|
-
line = processed.line
|
241
|
-
with_line_number(line, s(:lit, symbol))
|
242
|
-
end
|
47
|
+
def process_at_float(exp)
|
48
|
+
make_literal(exp, &:to_f)
|
243
49
|
end
|
244
50
|
|
245
|
-
def
|
246
|
-
|
247
|
-
right
|
51
|
+
def process_at_rational(exp)
|
52
|
+
make_literal(exp, &:to_r)
|
248
53
|
end
|
249
54
|
|
250
|
-
def
|
251
|
-
|
252
|
-
left.push right
|
253
|
-
else
|
254
|
-
_, first, *rest = right
|
255
|
-
left.push s(:str, first) unless first.empty?
|
256
|
-
left.push(*rest)
|
257
|
-
end
|
55
|
+
def process_at_imaginary(exp)
|
56
|
+
make_literal(exp, &:to_c)
|
258
57
|
end
|
259
58
|
|
260
|
-
|
261
|
-
case delim
|
262
|
-
when INTERPOLATING_HEREDOC
|
263
|
-
unescape(content)
|
264
|
-
when *INTERPOLATING_STRINGS
|
265
|
-
unescape(content)
|
266
|
-
when INTERPOLATING_WORD_LIST
|
267
|
-
unescape_wordlist_word(content)
|
268
|
-
when *NON_INTERPOLATING_STRINGS
|
269
|
-
simple_unescape(content)
|
270
|
-
when *REGEXP_LITERALS
|
271
|
-
unescape_regexp(content)
|
272
|
-
when NON_INTERPOLATING_WORD_LIST
|
273
|
-
simple_unescape_wordlist_word(content)
|
274
|
-
else
|
275
|
-
content
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
def handle_string_encoding(string, delim)
|
280
|
-
case delim
|
281
|
-
when INTERPOLATING_HEREDOC, INTERPOLATING_WORD_LIST, *INTERPOLATING_STRINGS
|
282
|
-
fix_encoding string
|
283
|
-
else
|
284
|
-
string
|
285
|
-
end
|
286
|
-
end
|
59
|
+
private
|
287
60
|
|
288
61
|
# Process list of items that can be either :assoc_new or :assoc_splat
|
289
62
|
def make_hash_items(elems)
|
290
63
|
result = s()
|
291
64
|
elems.each do |sub_exp|
|
292
65
|
if sub_exp.sexp_type == :assoc_new
|
293
|
-
|
66
|
+
result += process(sub_exp).sexp_body
|
294
67
|
else # :assoc_splat
|
295
68
|
result << process(sub_exp)
|
296
69
|
end
|
@@ -17,7 +17,7 @@ module RipperRubyParser
|
|
17
17
|
|
18
18
|
def process_arg_paren(exp)
|
19
19
|
_, args = exp.shift 2
|
20
|
-
return s() if args.nil?
|
20
|
+
return s(:arglist) if args.nil?
|
21
21
|
|
22
22
|
process(args)
|
23
23
|
end
|
@@ -26,7 +26,11 @@ module RipperRubyParser
|
|
26
26
|
_, call, parens = exp.shift 3
|
27
27
|
call = process(call)
|
28
28
|
parens = process(parens)
|
29
|
-
|
29
|
+
if parens.sexp_type == :forward_args
|
30
|
+
call.push(parens)
|
31
|
+
else
|
32
|
+
call.push(*parens.sexp_body)
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
# Handle implied hashes, such as at the end of argument lists.
|
@@ -36,9 +40,9 @@ module RipperRubyParser
|
|
36
40
|
end
|
37
41
|
|
38
42
|
CALL_OP_MAP = {
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
".": :call,
|
44
|
+
"::": :call,
|
45
|
+
"&.": :safe_call
|
42
46
|
}.freeze
|
43
47
|
|
44
48
|
def process_call(exp)
|
@@ -72,6 +72,11 @@ module RipperRubyParser
|
|
72
72
|
s(:alias, process(left), process(right))
|
73
73
|
end
|
74
74
|
|
75
|
+
def process_args_forward(exp)
|
76
|
+
_ = exp.shift
|
77
|
+
s(:forward_args)
|
78
|
+
end
|
79
|
+
|
75
80
|
private
|
76
81
|
|
77
82
|
def in_method
|
@@ -83,8 +88,8 @@ module RipperRubyParser
|
|
83
88
|
|
84
89
|
def method_body(exp)
|
85
90
|
block = process exp
|
86
|
-
case block.
|
87
|
-
when
|
91
|
+
case block.sexp_type
|
92
|
+
when :void_stmt
|
88
93
|
[s(:nil).line(block.line)]
|
89
94
|
else
|
90
95
|
unwrap_block block
|
@@ -98,21 +103,21 @@ module RipperRubyParser
|
|
98
103
|
}.freeze
|
99
104
|
|
100
105
|
def convert_arguments(args)
|
101
|
-
args.
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
106
|
+
args.line ||= args.sexp_body.first&.line
|
107
|
+
args.sexp_body = args.sexp_body.map { |item| convert_argument item }
|
108
|
+
args
|
109
|
+
end
|
110
|
+
|
111
|
+
def convert_argument(item)
|
112
|
+
case item.sexp_type
|
113
|
+
when :lvar
|
114
|
+
item.last
|
115
|
+
when *SPECIAL_ARG_MARKER.keys
|
116
|
+
convert_marked_argument(item)
|
117
|
+
when :masgn
|
118
|
+
convert_masgn_argument(item)
|
119
|
+
else
|
120
|
+
item
|
116
121
|
end
|
117
122
|
end
|
118
123
|
|
@@ -5,8 +5,8 @@ module RipperRubyParser
|
|
5
5
|
# Sexp handlers for operators
|
6
6
|
module Operators
|
7
7
|
BINARY_OPERATOR_MAP = {
|
8
|
-
|
9
|
-
|
8
|
+
"&&": :and,
|
9
|
+
"||": :or,
|
10
10
|
and: :and,
|
11
11
|
or: :or
|
12
12
|
}.freeze
|
@@ -16,7 +16,7 @@ module RipperRubyParser
|
|
16
16
|
}.freeze
|
17
17
|
|
18
18
|
NEGATED_BINARY_OPERATOR_MAP = {
|
19
|
-
|
19
|
+
"!~": :=~
|
20
20
|
}.freeze
|
21
21
|
|
22
22
|
SHIFT_OPERATORS = [:<<, :>>].freeze
|