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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +19 -0
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/lib/ripper_ruby_parser.rb +0 -7
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +112 -34
- data/lib/ripper_ruby_parser/parser.rb +26 -12
- data/lib/ripper_ruby_parser/sexp_handlers.rb +4 -1
- data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +7 -6
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +4 -2
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +39 -43
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +93 -69
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +30 -24
- data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +7 -9
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +51 -71
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +72 -56
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +14 -13
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +19 -13
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +19 -22
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +47 -35
- data/lib/ripper_ruby_parser/sexp_processor.rb +72 -85
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/end_to_end/line_numbering_test.rb +1 -1
- data/test/end_to_end/samples_comparison_test.rb +0 -1
- data/test/pt_testcase/pt_test.rb +4 -6
- data/test/{unit → ripper_ruby_parser}/commenting_ripper_parser_test.rb +82 -25
- data/test/{unit → ripper_ruby_parser}/parser_test.rb +37 -170
- data/test/{unit/parser_assignment_test.rb → ripper_ruby_parser/sexp_handlers/assignment_test.rb} +1 -1
- data/test/{unit/parser_blocks_test.rb → ripper_ruby_parser/sexp_handlers/blocks_test.rb} +267 -2
- data/test/{unit/parser_conditionals_test.rb → ripper_ruby_parser/sexp_handlers/conditionals_test.rb} +125 -17
- data/test/{unit/parser_literals_test.rb → ripper_ruby_parser/sexp_handlers/literals_test.rb} +10 -12
- data/test/{unit/parser_loops_test.rb → ripper_ruby_parser/sexp_handlers/loops_test.rb} +1 -1
- data/test/{unit/parser_method_calls_test.rb → ripper_ruby_parser/sexp_handlers/method_calls_test.rb} +10 -10
- data/test/{unit/parser_operators_test.rb → ripper_ruby_parser/sexp_handlers/operators_test.rb} +22 -2
- data/test/{unit → ripper_ruby_parser}/sexp_processor_test.rb +49 -48
- data/test/{unit → ripper_ruby_parser}/version_test.rb +0 -0
- data/test/samples/misc.rb +4 -0
- data/test/test_helper.rb +4 -4
- metadata +28 -42
- 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
|
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
|
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
|
-
|
20
|
+
alias process_word process_string_content
|
21
|
+
|
22
|
+
def process_string_embexpr(exp)
|
22
23
|
_, list = exp.shift 2
|
23
|
-
|
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
|
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
|
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
|
-
|
48
|
-
|
49
|
-
|
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
|
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
|
68
|
-
_, content, (_, flags,
|
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
|
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
|
90
|
+
def process_symbol(exp)
|
92
91
|
_, node = exp.shift 2
|
93
|
-
|
92
|
+
handle_symbol_content(node)
|
94
93
|
end
|
95
94
|
|
96
|
-
def process_dyna_symbol
|
97
|
-
_,
|
95
|
+
def process_dyna_symbol(exp)
|
96
|
+
_, node = exp.shift 2
|
97
|
+
handle_dyna_symbol_content(node)
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
112
|
-
_,
|
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
|
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
|
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
|
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
|
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
|
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
|
5
|
+
def process_until(exp)
|
5
6
|
handle_conditional_loop :until, :while, exp
|
6
7
|
end
|
7
8
|
|
8
|
-
def process_until_mod
|
9
|
+
def process_until_mod(exp)
|
9
10
|
handle_conditional_loop_mod :until, :while, exp
|
10
11
|
end
|
11
12
|
|
12
|
-
def process_while
|
13
|
+
def process_while(exp)
|
13
14
|
handle_conditional_loop :while, :until, exp
|
14
15
|
end
|
15
16
|
|
16
|
-
def process_while_mod
|
17
|
+
def process_while_mod(exp)
|
17
18
|
handle_conditional_loop_mod :while, :until, exp
|
18
19
|
end
|
19
20
|
|
20
|
-
def process_for
|
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 =
|
25
|
-
if block
|
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?
|
35
|
+
def check_at_start?(block)
|
35
36
|
block.sexp_type != :begin
|
36
37
|
end
|
37
38
|
|
38
|
-
def handle_conditional_loop
|
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
|
-
|
44
|
+
unwrap_nil(process(body)),
|
44
45
|
true)
|
45
46
|
end
|
46
47
|
|
47
|
-
def handle_conditional_loop_mod
|
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
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
19
|
+
'.': :call,
|
20
|
+
'::': :call,
|
21
|
+
'&.': :safe_call
|
22
|
+
}.freeze
|
22
23
|
|
23
|
-
def process_call
|
24
|
+
def process_call(exp)
|
24
25
|
_, receiver, op, ident = exp.shift 4
|
25
26
|
type = CALL_OP_MAP.fetch op
|
26
|
-
|
27
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
28
|
+
def process_return0(exp)
|
28
29
|
_ = exp.shift
|
29
30
|
s(:return)
|
30
31
|
end
|
31
32
|
|
32
|
-
def process_yield
|
33
|
+
def process_yield(exp)
|
33
34
|
_, arglist = exp.shift 2
|
34
|
-
|
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
|
38
|
+
def process_yield0(exp)
|
42
39
|
_ = exp.shift
|
43
40
|
s(:yield)
|
44
41
|
end
|
45
42
|
|
46
|
-
def process_undef
|
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
|
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
|
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
|
78
|
+
def method_body(exp)
|
82
79
|
block = in_method { process exp }
|
83
80
|
case block.length
|
84
81
|
when 0
|
85
|
-
|
86
|
-
|
87
|
-
if block.
|
88
|
-
block
|
89
|
-
|
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
|
98
|
+
def convert_special_args(args)
|
102
99
|
args.map! do |item|
|
103
100
|
if item.is_a? Symbol
|
104
101
|
item
|