ripper_ruby_parser 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +2 -2
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +23 -4
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +6 -4
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +17 -13
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +4 -2
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +4 -4
- data/lib/ripper_ruby_parser/sexp_processor.rb +31 -18
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/end_to_end/comparison_test.rb +8 -8
- data/test/end_to_end/line_numbering_test.rb +2 -35
- data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +29 -13
- data/test/ripper_ruby_parser/parser_test.rb +98 -14
- data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +9 -0
- data/test/ripper_ruby_parser/sexp_processor_test.rb +5 -5
- data/test/test_helper.rb +39 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20d34b3ba8f1c186e8df1118334a231d2520c9ef51a36b4c7d5b12c33fe9947b
|
4
|
+
data.tar.gz: 881e3286d632c0189a33a2add98dd43bddda798cf6c7c8f3fa75e1b9dfdda7e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3a58dd16a10a8c0f64996c753e2da3c02d7b0ec074099795bf240925e388a5edb215edf680df0c70baab82c42ea77d22762d2a2b27a7a9a246aa01bb47753a1
|
7
|
+
data.tar.gz: 7b360aaea5ba1fe76855a4e534d56aec13b1a470f7cc9e539d4e2c996ef0684848142ea6c4d2e522c439e84d62628ebaf571da5c993e9a44a0f9641d8e3283df
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.6.1 / 2019-04-22
|
4
|
+
|
5
|
+
* Improve line numbering for some block structures ([#82])
|
6
|
+
- Fix line numbering for empty method bodies
|
7
|
+
- Assign correct line numbers to END blocks
|
8
|
+
- Assign correct line numbers to begin blocks
|
9
|
+
- Assign correct line numbers to BEGIN blocks
|
10
|
+
* Fix line numbering for several literals ([#80])
|
11
|
+
- Fix line numbering for plain regexp literals
|
12
|
+
- Fix line numbering for backtick literals
|
13
|
+
- Fix line numbering for simple string literals
|
14
|
+
- Fix line numbering for keyword-like symbols
|
15
|
+
|
3
16
|
## 1.6.0 / 2019-04-12
|
4
17
|
|
5
18
|
* Fix line numbering for range literals ([#79])
|
@@ -158,6 +171,8 @@
|
|
158
171
|
* Initial release
|
159
172
|
|
160
173
|
<!-- Pull request links -->
|
174
|
+
[#82]: https://github.com/mvz/ripper_ruby_parser/pull/82
|
175
|
+
[#80]: https://github.com/mvz/ripper_ruby_parser/pull/80
|
161
176
|
[#79]: https://github.com/mvz/ripper_ruby_parser/pull/79
|
162
177
|
[#78]: https://github.com/mvz/ripper_ruby_parser/pull/78
|
163
178
|
[#77]: https://github.com/mvz/ripper_ruby_parser/pull/77
|
data/README.md
CHANGED
@@ -22,14 +22,14 @@ The following incompatibilities cannot be changed:
|
|
22
22
|
|
23
23
|
* RipperRubyParser won't handle non-UTF-8 files without an encoding comment,
|
24
24
|
just like regular Ruby
|
25
|
-
* RipperRubyParser does not
|
25
|
+
* RipperRubyParser does not match RubyParser's line numbering
|
26
26
|
* RipperRubyParser correctly dedents heredocs with interpolations
|
27
27
|
|
28
28
|
The following incompatibilities can be made compatible by turning on
|
29
29
|
extra-compatible mode:
|
30
30
|
|
31
31
|
* Operator assignment of a method call without parentheses to a collection
|
32
|
-
element uses
|
32
|
+
element uses an `:array` S-expression instead of `:arglist`
|
33
33
|
* RipperRubyParser keeps carriage return characters in heredocs that include
|
34
34
|
them
|
35
35
|
|
@@ -32,6 +32,15 @@ module RipperRubyParser
|
|
32
32
|
super
|
33
33
|
end
|
34
34
|
|
35
|
+
def on_begin(*args)
|
36
|
+
commentize(:begin, super)
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_void_stmt
|
40
|
+
result = super
|
41
|
+
result << [lineno, column]
|
42
|
+
end
|
43
|
+
|
35
44
|
def on_comment(tok)
|
36
45
|
@comment += tok
|
37
46
|
end
|
@@ -49,14 +58,15 @@ module RipperRubyParser
|
|
49
58
|
end
|
50
59
|
|
51
60
|
def on_kw(tok)
|
61
|
+
result = super
|
52
62
|
case tok
|
53
|
-
when 'class', 'def', 'module'
|
63
|
+
when 'class', 'def', 'module', 'BEGIN', 'begin', 'END'
|
54
64
|
unless @in_symbol
|
55
|
-
@comment_stack.push [
|
65
|
+
@comment_stack.push [result, @comment]
|
56
66
|
@comment = ''
|
57
67
|
end
|
58
68
|
end
|
59
|
-
|
69
|
+
result
|
60
70
|
end
|
61
71
|
|
62
72
|
def on_module(*args)
|
@@ -275,6 +285,14 @@ module RipperRubyParser
|
|
275
285
|
super
|
276
286
|
end
|
277
287
|
|
288
|
+
def on_BEGIN(*args)
|
289
|
+
commentize(:BEGIN, super)
|
290
|
+
end
|
291
|
+
|
292
|
+
def on_END(*args)
|
293
|
+
commentize(:END, super)
|
294
|
+
end
|
295
|
+
|
278
296
|
def on_parse_error(*args)
|
279
297
|
raise SyntaxError, *args
|
280
298
|
end
|
@@ -298,8 +316,9 @@ module RipperRubyParser
|
|
298
316
|
private
|
299
317
|
|
300
318
|
def commentize(_name, exp)
|
301
|
-
|
319
|
+
(_, _kw, loc), comment = @comment_stack.pop
|
302
320
|
@comment = ''
|
321
|
+
exp.push loc
|
303
322
|
[:comment, comment, exp]
|
304
323
|
end
|
305
324
|
end
|
@@ -47,10 +47,10 @@ module RipperRubyParser
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def process_begin(exp)
|
50
|
-
_, body = exp.shift
|
50
|
+
_, body, pos = exp.shift 3
|
51
51
|
|
52
52
|
body = convert_empty_to_nil_symbol process(body)
|
53
|
-
s(:begin, body)
|
53
|
+
with_position pos, s(:begin, body)
|
54
54
|
end
|
55
55
|
|
56
56
|
def process_rescue(exp)
|
@@ -86,7 +86,9 @@ module RipperRubyParser
|
|
86
86
|
|
87
87
|
body = s()
|
88
88
|
|
89
|
-
|
89
|
+
main_list = map_unwrap_begin_list map_process_list main.sexp_body
|
90
|
+
line = main_list.first.line
|
91
|
+
main = wrap_in_block reject_void_stmt main_list
|
90
92
|
body << main if main
|
91
93
|
|
92
94
|
if rescue_block
|
@@ -102,7 +104,7 @@ module RipperRubyParser
|
|
102
104
|
body = s(s(:ensure, *body))
|
103
105
|
end
|
104
106
|
|
105
|
-
wrap_in_block(body) || s()
|
107
|
+
wrap_in_block(body) || s().line(line)
|
106
108
|
end
|
107
109
|
|
108
110
|
def process_rescue_mod(exp)
|
@@ -11,10 +11,10 @@ module RipperRubyParser
|
|
11
11
|
|
12
12
|
def process_string_content(exp)
|
13
13
|
_, *rest = shift_all exp
|
14
|
-
string, rest = extract_string_parts(rest)
|
14
|
+
line, string, rest = extract_string_parts(rest)
|
15
15
|
|
16
16
|
if rest.empty?
|
17
|
-
s(:str, string)
|
17
|
+
with_line_number(line, s(:str, string))
|
18
18
|
else
|
19
19
|
s(:dstr, string, *rest)
|
20
20
|
end
|
@@ -63,9 +63,9 @@ module RipperRubyParser
|
|
63
63
|
|
64
64
|
def process_xstring(exp)
|
65
65
|
_, *rest = shift_all exp
|
66
|
-
string, rest = extract_string_parts(rest)
|
66
|
+
line, string, rest = extract_string_parts(rest)
|
67
67
|
if rest.empty?
|
68
|
-
s(:xstr, string)
|
68
|
+
s(:xstr, string).line(line)
|
69
69
|
else
|
70
70
|
s(:dxstr, string, *rest)
|
71
71
|
end
|
@@ -77,7 +77,9 @@ module RipperRubyParser
|
|
77
77
|
content = process(content)
|
78
78
|
numflags = character_flags_to_numerical flags
|
79
79
|
|
80
|
-
|
80
|
+
if content.length == 2
|
81
|
+
return with_line_number(content.line, s(:lit, Regexp.new(content.last, numflags)))
|
82
|
+
end
|
81
83
|
|
82
84
|
content.sexp_type = :dregx_once if flags =~ /o/
|
83
85
|
content << numflags unless numflags == 0
|
@@ -86,8 +88,8 @@ module RipperRubyParser
|
|
86
88
|
|
87
89
|
def process_regexp(exp)
|
88
90
|
_, *rest = shift_all exp
|
89
|
-
string, rest = extract_string_parts(rest)
|
90
|
-
s(:dregx, string, *rest)
|
91
|
+
line, string, rest = extract_string_parts(rest)
|
92
|
+
with_line_number(line, s(:dregx, string, *rest))
|
91
93
|
end
|
92
94
|
|
93
95
|
def process_symbol_literal(exp)
|
@@ -126,10 +128,10 @@ module RipperRubyParser
|
|
126
128
|
REGEXP_LITERALS = ['/', /^%r.$/].freeze
|
127
129
|
|
128
130
|
def process_at_tstring_content(exp)
|
129
|
-
_, content,
|
131
|
+
_, content, pos, delim = exp.shift 4
|
130
132
|
string = handle_string_unescaping(content, delim)
|
131
133
|
string = handle_string_encoding(string, delim)
|
132
|
-
s(:str, string)
|
134
|
+
with_position(pos, s(:str, string))
|
133
135
|
end
|
134
136
|
|
135
137
|
def process_array(exp)
|
@@ -164,7 +166,7 @@ module RipperRubyParser
|
|
164
166
|
private
|
165
167
|
|
166
168
|
def extract_string_parts(list)
|
167
|
-
return '', [] if list.empty?
|
169
|
+
return nil, '', [] if list.empty?
|
168
170
|
|
169
171
|
list = merge_raw_string_literals list
|
170
172
|
list = map_process_list list
|
@@ -185,10 +187,11 @@ module RipperRubyParser
|
|
185
187
|
string = ''
|
186
188
|
while parts.first&.sexp_type == :str
|
187
189
|
str = parts.shift
|
190
|
+
line ||= str.line
|
188
191
|
string += str.last
|
189
192
|
end
|
190
193
|
|
191
|
-
return string, parts
|
194
|
+
return line, string, parts
|
192
195
|
end
|
193
196
|
|
194
197
|
def merge_raw_string_literals(list)
|
@@ -230,12 +233,13 @@ module RipperRubyParser
|
|
230
233
|
def handle_symbol_content(node)
|
231
234
|
if node.sexp_type == :'@kw'
|
232
235
|
symbol, position = extract_node_symbol_with_position(node)
|
236
|
+
with_position(position, s(:lit, symbol))
|
233
237
|
else
|
234
238
|
processed = process(node)
|
235
239
|
symbol = processed.last.to_sym
|
236
|
-
|
240
|
+
line = processed.line
|
241
|
+
with_line_number(line, s(:lit, symbol))
|
237
242
|
end
|
238
|
-
with_line_number(position, s(:lit, symbol))
|
239
243
|
end
|
240
244
|
|
241
245
|
def merge_left_into_right(left, right)
|
@@ -52,10 +52,12 @@ module RipperRubyParser
|
|
52
52
|
def handle_conditional_loop_mod(type, negated_type, exp)
|
53
53
|
_, cond, body = exp.shift 3
|
54
54
|
|
55
|
+
cond = process(cond)
|
56
|
+
body = process(body)
|
55
57
|
check_at_start = check_at_start?(body)
|
56
58
|
construct_conditional_loop(type, negated_type,
|
57
|
-
unwrap_begin(
|
58
|
-
unwrap_begin(
|
59
|
+
unwrap_begin(cond),
|
60
|
+
unwrap_begin(body),
|
59
61
|
check_at_start)
|
60
62
|
end
|
61
63
|
|
@@ -5,9 +5,9 @@ module RipperRubyParser
|
|
5
5
|
# Sexp handers for method definitions and related constructs
|
6
6
|
module Methods
|
7
7
|
def process_def(exp)
|
8
|
-
_, ident, params, body = exp.shift
|
8
|
+
_, ident, params, body, pos = exp.shift 5
|
9
9
|
|
10
|
-
ident,
|
10
|
+
ident, = extract_node_symbol_with_position ident
|
11
11
|
|
12
12
|
in_method do
|
13
13
|
params = convert_arguments(process(params))
|
@@ -19,7 +19,7 @@ module RipperRubyParser
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def process_defs(exp)
|
22
|
-
_, receiver, _, ident, params, body = exp.shift
|
22
|
+
_, receiver, _, ident, params, body, = exp.shift 7
|
23
23
|
|
24
24
|
ident, = extract_node_symbol_with_position ident
|
25
25
|
|
@@ -85,7 +85,7 @@ module RipperRubyParser
|
|
85
85
|
block = process exp
|
86
86
|
case block.length
|
87
87
|
when 0
|
88
|
-
[s(:nil)]
|
88
|
+
[s(:nil).line(block.line)]
|
89
89
|
else
|
90
90
|
unwrap_block block
|
91
91
|
end
|
@@ -45,6 +45,8 @@ module RipperRubyParser
|
|
45
45
|
@in_method_body = false
|
46
46
|
@kwrest = []
|
47
47
|
@block_kwrest = []
|
48
|
+
|
49
|
+
@kept_comment = nil
|
48
50
|
end
|
49
51
|
|
50
52
|
include SexpHandlers
|
@@ -56,23 +58,23 @@ module RipperRubyParser
|
|
56
58
|
end
|
57
59
|
|
58
60
|
def process_module(exp)
|
59
|
-
_, const_ref, body = exp.shift
|
60
|
-
const
|
61
|
-
|
62
|
-
|
61
|
+
_, const_ref, body, pos = exp.shift 4
|
62
|
+
const = const_ref_to_const const_ref
|
63
|
+
with_position(pos,
|
64
|
+
s(:module, const, *class_or_module_body(body)))
|
63
65
|
end
|
64
66
|
|
65
67
|
def process_class(exp)
|
66
|
-
_, const_ref, parent, body = exp.shift
|
67
|
-
const
|
68
|
+
_, const_ref, parent, body, pos = exp.shift 5
|
69
|
+
const = const_ref_to_const const_ref
|
68
70
|
parent = process(parent)
|
69
|
-
|
70
|
-
|
71
|
+
with_position(pos,
|
72
|
+
s(:class, const, parent, *class_or_module_body(body)))
|
71
73
|
end
|
72
74
|
|
73
75
|
def process_sclass(exp)
|
74
|
-
_, klass, block = exp.shift
|
75
|
-
s(:sclass, process(klass), *class_or_module_body(block))
|
76
|
+
_, klass, block, pos = exp.shift 4
|
77
|
+
with_position pos, s(:sclass, process(klass), *class_or_module_body(block))
|
76
78
|
end
|
77
79
|
|
78
80
|
def process_stmts(exp)
|
@@ -104,6 +106,11 @@ module RipperRubyParser
|
|
104
106
|
s(:valias, left[1].to_sym, right[1].to_sym)
|
105
107
|
end
|
106
108
|
|
109
|
+
def process_void_stmt(exp)
|
110
|
+
_, pos = exp.shift 2
|
111
|
+
with_position pos, s(:void_stmt)
|
112
|
+
end
|
113
|
+
|
107
114
|
def process_const_path_ref(exp)
|
108
115
|
_, left, right = exp.shift 3
|
109
116
|
s(:colon2, process(left), extract_node_symbol(process(right)))
|
@@ -139,21 +146,28 @@ module RipperRubyParser
|
|
139
146
|
|
140
147
|
def process_comment(exp)
|
141
148
|
_, comment, inner = exp.shift 3
|
149
|
+
comment = @kept_comment + comment if @kept_comment
|
150
|
+
@kept_comment = nil
|
142
151
|
sexp = process(inner)
|
143
|
-
sexp.
|
152
|
+
case sexp.sexp_type
|
153
|
+
when :defs, :defn, :module, :class, :sclass
|
154
|
+
sexp.comments = comment
|
155
|
+
else
|
156
|
+
@kept_comment = comment
|
157
|
+
end
|
144
158
|
sexp
|
145
159
|
end
|
146
160
|
|
147
161
|
def process_BEGIN(exp)
|
148
|
-
_, body = exp.shift
|
162
|
+
_, body, pos = exp.shift 3
|
149
163
|
body = reject_void_stmt map_process_list body.sexp_body
|
150
|
-
s(:iter, s(:preexe), 0, *body)
|
164
|
+
with_position pos, s(:iter, s(:preexe), 0, *body)
|
151
165
|
end
|
152
166
|
|
153
167
|
def process_END(exp)
|
154
|
-
_, body = exp.shift
|
168
|
+
_, body, pos = exp.shift 3
|
155
169
|
body = map_process_list_compact body.sexp_body
|
156
|
-
s(:iter, s(:postexe), 0, *body)
|
170
|
+
with_position pos, s(:iter, s(:postexe), 0, *body)
|
157
171
|
end
|
158
172
|
|
159
173
|
# number literals
|
@@ -242,11 +256,10 @@ module RipperRubyParser
|
|
242
256
|
|
243
257
|
private
|
244
258
|
|
245
|
-
def
|
259
|
+
def const_ref_to_const(const_ref)
|
246
260
|
const = process(const_ref)
|
247
|
-
line = const.line
|
248
261
|
const = const[1] if const.sexp_type == :const
|
249
|
-
|
262
|
+
const
|
250
263
|
end
|
251
264
|
|
252
265
|
def class_or_module_body(exp)
|
@@ -9,8 +9,8 @@ describe 'Using RipperRubyParser and RubyParser' do
|
|
9
9
|
"puts 'Hello World'"
|
10
10
|
end
|
11
11
|
|
12
|
-
it 'gives the same result' do
|
13
|
-
program.must_be_parsed_as_before
|
12
|
+
it 'gives the same result with line numbers' do
|
13
|
+
program.must_be_parsed_as_before with_line_numbers: true
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -35,8 +35,8 @@ describe 'Using RipperRubyParser and RubyParser' do
|
|
35
35
|
END
|
36
36
|
end
|
37
37
|
|
38
|
-
it 'gives the same result' do
|
39
|
-
program.must_be_parsed_as_before
|
38
|
+
it 'gives the same result with line numbers' do
|
39
|
+
program.must_be_parsed_as_before with_line_numbers: true
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -45,8 +45,8 @@ describe 'Using RipperRubyParser and RubyParser' do
|
|
45
45
|
'def fred() yield(3) if block_given?; end'
|
46
46
|
end
|
47
47
|
|
48
|
-
it 'gives the same result' do
|
49
|
-
program.must_be_parsed_as_before
|
48
|
+
it 'gives the same result with line numbers' do
|
49
|
+
program.must_be_parsed_as_before with_line_numbers: true
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -97,8 +97,8 @@ describe 'Using RipperRubyParser and RubyParser' do
|
|
97
97
|
"/(\#{@types})\\s*(\\w+)\\s*\\(([^)]*)\\)/"
|
98
98
|
end
|
99
99
|
|
100
|
-
it 'gives the same result' do
|
101
|
-
program.must_be_parsed_as_before
|
100
|
+
it 'gives the same result with line numbers' do
|
101
|
+
program.must_be_parsed_as_before with_line_numbers: true
|
102
102
|
end
|
103
103
|
end
|
104
104
|
end
|
@@ -4,30 +4,6 @@ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
|
4
4
|
require 'ruby_parser'
|
5
5
|
|
6
6
|
describe 'Using RipperRubyParser and RubyParser' do
|
7
|
-
def to_line_numbers(exp)
|
8
|
-
exp.map! do |sub_exp|
|
9
|
-
if sub_exp.is_a? Sexp
|
10
|
-
to_line_numbers sub_exp
|
11
|
-
else
|
12
|
-
sub_exp
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
if exp.sexp_type == :scope
|
17
|
-
exp
|
18
|
-
else
|
19
|
-
s(:line_number, exp.line, exp)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
let :newparser do
|
24
|
-
RipperRubyParser::Parser.new
|
25
|
-
end
|
26
|
-
|
27
|
-
let :oldparser do
|
28
|
-
RubyParser.for_current_ruby
|
29
|
-
end
|
30
|
-
|
31
7
|
describe 'for a multi-line program' do
|
32
8
|
let :program do
|
33
9
|
<<-END
|
@@ -44,21 +20,12 @@ describe 'Using RipperRubyParser and RubyParser' do
|
|
44
20
|
END
|
45
21
|
end
|
46
22
|
|
47
|
-
let :original do
|
48
|
-
oldparser.parse program
|
49
|
-
end
|
50
|
-
|
51
|
-
let :imitation do
|
52
|
-
newparser.parse program
|
53
|
-
end
|
54
|
-
|
55
23
|
it 'gives the same result' do
|
56
|
-
|
24
|
+
program.must_be_parsed_as_before
|
57
25
|
end
|
58
26
|
|
59
27
|
it 'gives the same result with line numbers' do
|
60
|
-
|
61
|
-
must_equal formatted(to_line_numbers(original))
|
28
|
+
program.must_be_parsed_as_before with_line_numbers: true
|
62
29
|
end
|
63
30
|
end
|
64
31
|
end
|
@@ -22,7 +22,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
22
22
|
s(:def,
|
23
23
|
s(:@ident, 'foo', s(2, 4)),
|
24
24
|
empty_params_list,
|
25
|
-
s(:bodystmt,
|
25
|
+
s(:bodystmt,
|
26
|
+
s(:stmts, s(:void_stmt, s(2, 12))), nil, nil, nil),
|
27
|
+
s(2, 0)))))
|
26
28
|
end
|
27
29
|
|
28
30
|
it 'produces a blank comment node surrounding a def that has no comment' do
|
@@ -34,7 +36,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
34
36
|
s(:def,
|
35
37
|
s(:@ident, 'foo', s(1, 4)),
|
36
38
|
empty_params_list,
|
37
|
-
s(:bodystmt,
|
39
|
+
s(:bodystmt,
|
40
|
+
s(:stmts, s(:void_stmt, s(1, 12))), nil, nil, nil),
|
41
|
+
s(1, 0)))))
|
38
42
|
end
|
39
43
|
|
40
44
|
it 'produces a comment node surrounding a commented class' do
|
@@ -46,7 +50,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
46
50
|
s(:class,
|
47
51
|
s(:const_ref, s(:@const, 'Foo', s(2, 6))),
|
48
52
|
nil,
|
49
|
-
s(:bodystmt,
|
53
|
+
s(:bodystmt,
|
54
|
+
s(:stmts, s(:void_stmt, s(2, 10))), nil, nil, nil),
|
55
|
+
s(2, 0)))))
|
50
56
|
end
|
51
57
|
|
52
58
|
it 'produce a blank comment node surrounding a class that has no comment' do
|
@@ -58,7 +64,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
58
64
|
s(:class,
|
59
65
|
s(:const_ref, s(:@const, 'Foo', s(1, 6))),
|
60
66
|
nil,
|
61
|
-
s(:bodystmt,
|
67
|
+
s(:bodystmt,
|
68
|
+
s(:stmts, s(:void_stmt, s(1, 10))), nil, nil, nil),
|
69
|
+
s(1, 0)))))
|
62
70
|
end
|
63
71
|
|
64
72
|
it 'produces a comment node surrounding a commented module' do
|
@@ -69,7 +77,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
69
77
|
"# Foo\n",
|
70
78
|
s(:module,
|
71
79
|
s(:const_ref, s(:@const, 'Foo', s(2, 7))),
|
72
|
-
s(:bodystmt,
|
80
|
+
s(:bodystmt,
|
81
|
+
s(:stmts, s(:void_stmt, s(2, 11))), nil, nil, nil),
|
82
|
+
s(2, 0)))))
|
73
83
|
end
|
74
84
|
|
75
85
|
it 'produces a blank comment node surrounding a module that has no comment' do
|
@@ -80,7 +90,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
80
90
|
'',
|
81
91
|
s(:module,
|
82
92
|
s(:const_ref, s(:@const, 'Foo', s(1, 7))),
|
83
|
-
s(:bodystmt,
|
93
|
+
s(:bodystmt,
|
94
|
+
s(:stmts, s(:void_stmt, s(1, 11))), nil, nil, nil),
|
95
|
+
s(1, 0)))))
|
84
96
|
end
|
85
97
|
|
86
98
|
it 'is not confused by a symbol containing a keyword' do
|
@@ -93,7 +105,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
93
105
|
s(:def,
|
94
106
|
s(:@ident, 'foo', s(1, 12)),
|
95
107
|
empty_params_list,
|
96
|
-
s(:bodystmt,
|
108
|
+
s(:bodystmt,
|
109
|
+
s(:stmts, s(:void_stmt, s(1, 20))), nil, nil, nil),
|
110
|
+
s(1, 8)))))
|
97
111
|
end
|
98
112
|
|
99
113
|
it 'is not confused by a dynamic symbol' do
|
@@ -107,7 +121,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
107
121
|
s(:def,
|
108
122
|
s(:@ident, 'bar', s(1, 12)),
|
109
123
|
empty_params_list,
|
110
|
-
s(:bodystmt,
|
124
|
+
s(:bodystmt,
|
125
|
+
s(:stmts, s(:void_stmt, s(1, 20))), nil, nil, nil),
|
126
|
+
s(1, 8)))))
|
111
127
|
end
|
112
128
|
|
113
129
|
it 'is not confused by a dynamic symbol containing a class definition' do
|
@@ -125,10 +141,8 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
125
141
|
s(:const_ref, s(:@const, 'Bar', s(1, 13))),
|
126
142
|
nil,
|
127
143
|
s(:bodystmt,
|
128
|
-
s(:stmts, s(:void_stmt)),
|
129
|
-
|
130
|
-
nil,
|
131
|
-
nil)))))))))
|
144
|
+
s(:stmts, s(:void_stmt, s(1, 17))), nil, nil, nil),
|
145
|
+
s(1, 7)))))))))
|
132
146
|
end
|
133
147
|
|
134
148
|
it 'turns an embedded document into a comment node' do
|
@@ -140,7 +154,9 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
140
154
|
s(:class,
|
141
155
|
s(:const_ref, s(:@const, 'Foo', s(4, 6))),
|
142
156
|
nil,
|
143
|
-
s(:bodystmt,
|
157
|
+
s(:bodystmt,
|
158
|
+
s(:stmts, s(:void_stmt, s(4, 10))), nil, nil, nil),
|
159
|
+
s(4, 0)))))
|
144
160
|
end
|
145
161
|
end
|
146
162
|
|
@@ -143,6 +143,22 @@ describe RipperRubyParser::Parser do
|
|
143
143
|
'END { }'.
|
144
144
|
must_be_parsed_as s(:iter, s(:postexe), 0)
|
145
145
|
end
|
146
|
+
|
147
|
+
it 'assigns correct line numbers' do
|
148
|
+
"END {\nfoo\n}".
|
149
|
+
must_be_parsed_as s(:iter,
|
150
|
+
s(:postexe).line(1), 0,
|
151
|
+
s(:call, nil, :foo).line(2)).line(1),
|
152
|
+
with_line_numbers: true
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'assigns correct line numbers to a embedded begin block' do
|
156
|
+
"END {\nbegin\nfoo\nend\n}".
|
157
|
+
must_be_parsed_as s(:iter,
|
158
|
+
s(:postexe).line(1), 0,
|
159
|
+
s(:call, nil, :foo).line(3)).line(1),
|
160
|
+
with_line_numbers: true
|
161
|
+
end
|
146
162
|
end
|
147
163
|
|
148
164
|
describe 'for the BEGIN keyword' do
|
@@ -155,6 +171,23 @@ describe RipperRubyParser::Parser do
|
|
155
171
|
'BEGIN { }'.
|
156
172
|
must_be_parsed_as s(:iter, s(:preexe), 0)
|
157
173
|
end
|
174
|
+
|
175
|
+
it 'assigns correct line numbers' do
|
176
|
+
"BEGIN {\nfoo\n}".
|
177
|
+
must_be_parsed_as s(:iter,
|
178
|
+
s(:preexe).line(1), 0,
|
179
|
+
s(:call, nil, :foo).line(2)).line(1),
|
180
|
+
with_line_numbers: true
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'assigns correct line numbers to a embedded begin block' do
|
184
|
+
"BEGIN {\nbegin\nfoo\nend\n}".
|
185
|
+
must_be_parsed_as s(:iter,
|
186
|
+
s(:preexe).line(1), 0,
|
187
|
+
s(:begin,
|
188
|
+
s(:call, nil, :foo).line(3)).line(2)).line(1),
|
189
|
+
with_line_numbers: true
|
190
|
+
end
|
158
191
|
end
|
159
192
|
|
160
193
|
describe 'for constant lookups' do
|
@@ -300,6 +333,35 @@ describe RipperRubyParser::Parser do
|
|
300
333
|
s(:call, nil, :baz)))
|
301
334
|
result.comments.must_equal "# Foo\n"
|
302
335
|
end
|
336
|
+
|
337
|
+
# TODO: Prefer assigning comment to the BEGIN instead
|
338
|
+
it 'assigns comments on BEGIN blocks to the following item' do
|
339
|
+
result = parser.parse "# Bar\nBEGIN { }\n# Foo\nclass Bar\n# foo\ndef foo; end\nend"
|
340
|
+
result.must_equal s(:block,
|
341
|
+
s(:iter, s(:preexe), 0),
|
342
|
+
s(:class, :Bar, nil,
|
343
|
+
s(:defn, :foo, s(:args), s(:nil))))
|
344
|
+
result[2].comments.must_equal "# Bar\n# Foo\n"
|
345
|
+
result[2][3].comments.must_equal "# foo\n"
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'assigns comments on multiple BEGIN blocks to the following item' do
|
349
|
+
result = parser.parse "# Bar\nBEGIN { }\n# Baz\nBEGIN { }\n# Foo\ndef foo; end"
|
350
|
+
result.must_equal s(:block,
|
351
|
+
s(:iter, s(:preexe), 0),
|
352
|
+
s(:iter, s(:preexe), 0),
|
353
|
+
s(:defn, :foo, s(:args), s(:nil)))
|
354
|
+
result[3].comments.must_equal "# Bar\n# Baz\n# Foo\n"
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'assigns comments on BEGIN blocks to the first following item' do
|
358
|
+
result = parser.parse "# Bar\nBEGIN { }\n# Baz\nBEGIN { }\n# Foo\ndef foo; end"
|
359
|
+
result.must_equal s(:block,
|
360
|
+
s(:iter, s(:preexe), 0),
|
361
|
+
s(:iter, s(:preexe), 0),
|
362
|
+
s(:defn, :foo, s(:args), s(:nil)))
|
363
|
+
result[3].comments.must_equal "# Bar\n# Baz\n# Foo\n"
|
364
|
+
end
|
303
365
|
end
|
304
366
|
|
305
367
|
# Note: differences in the handling of line numbers are not caught by
|
@@ -359,11 +421,11 @@ describe RipperRubyParser::Parser do
|
|
359
421
|
end
|
360
422
|
|
361
423
|
it 'works for a local variable' do
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
424
|
+
"foo = bar\nfoo\n".
|
425
|
+
must_be_parsed_as s(:block,
|
426
|
+
s(:lasgn, :foo, s(:call, nil, :bar).line(1)).line(1),
|
427
|
+
s(:lvar, :foo).line(2)).line(1),
|
428
|
+
with_line_numbers: true
|
367
429
|
end
|
368
430
|
|
369
431
|
it 'works for an integer literal' do
|
@@ -386,6 +448,31 @@ describe RipperRubyParser::Parser do
|
|
386
448
|
result.line.must_equal 1
|
387
449
|
end
|
388
450
|
|
451
|
+
it 'works for a symbol literal' do
|
452
|
+
result = parser.parse ':foo'
|
453
|
+
result.line.must_equal 1
|
454
|
+
end
|
455
|
+
|
456
|
+
it 'works for a keyword-like symbol literal' do
|
457
|
+
result = parser.parse ':and'
|
458
|
+
result.line.must_equal 1
|
459
|
+
end
|
460
|
+
|
461
|
+
it 'works for a string literal' do
|
462
|
+
result = parser.parse '"foo"'
|
463
|
+
result.line.must_equal 1
|
464
|
+
end
|
465
|
+
|
466
|
+
it 'works for a backtick string literal' do
|
467
|
+
result = parser.parse '`foo`'
|
468
|
+
result.line.must_equal 1
|
469
|
+
end
|
470
|
+
|
471
|
+
it 'works for a plain regexp literal' do
|
472
|
+
result = parser.parse '/foo/'
|
473
|
+
result.line.must_equal 1
|
474
|
+
end
|
475
|
+
|
389
476
|
it 'works for a regular expression back reference' do
|
390
477
|
result = parser.parse '$1'
|
391
478
|
result.line.must_equal 1
|
@@ -422,15 +509,12 @@ describe RipperRubyParser::Parser do
|
|
422
509
|
end
|
423
510
|
|
424
511
|
it 'assigns line numbers to nested sexps without their own line numbers' do
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
block = result[3]
|
432
|
-
nums = [arglist.line, block.line]
|
433
|
-
nums.must_equal [1, 2]
|
512
|
+
"foo(bar) do\nnext baz\nend\n".
|
513
|
+
must_be_parsed_as s(:iter,
|
514
|
+
s(:call, nil, :foo, s(:call, nil, :bar).line(1)).line(1),
|
515
|
+
0,
|
516
|
+
s(:next, s(:call, nil, :baz).line(2)).line(2)).line(1),
|
517
|
+
with_line_numbers: true
|
434
518
|
end
|
435
519
|
|
436
520
|
describe 'when a line number is passed' do
|
@@ -204,6 +204,15 @@ describe RipperRubyParser::Parser do
|
|
204
204
|
must_be_parsed_as s(:defn, :for, s(:args),
|
205
205
|
s(:nil))
|
206
206
|
end
|
207
|
+
|
208
|
+
it 'assigns correct line numbers when the body is empty' do
|
209
|
+
"def bar\nend".
|
210
|
+
must_be_parsed_as s(:defn,
|
211
|
+
:bar,
|
212
|
+
s(:args).line(1),
|
213
|
+
s(:nil).line(2)).line(1),
|
214
|
+
with_line_numbers: true
|
215
|
+
end
|
207
216
|
end
|
208
217
|
|
209
218
|
describe 'for singleton method definitions' do
|
@@ -74,10 +74,10 @@ describe RipperRubyParser::SexpProcessor do
|
|
74
74
|
end
|
75
75
|
|
76
76
|
describe 'for a :module sexp' do
|
77
|
-
it 'does not create body
|
77
|
+
it 'does not create body elements for an empty definition' do
|
78
78
|
sexp = s(:module,
|
79
79
|
s(:const_ref, s(:@const, 'Foo', s(1, 13))),
|
80
|
-
s(:bodystmt, s(:stmts, s(:void_stmt)), nil, nil, nil))
|
80
|
+
s(:bodystmt, s(:stmts, s(:void_stmt, s(2, 3))), nil, nil, nil))
|
81
81
|
result = processor.process sexp
|
82
82
|
result.must_equal s(:module, :Foo)
|
83
83
|
end
|
@@ -103,7 +103,7 @@ describe RipperRubyParser::SexpProcessor do
|
|
103
103
|
it 'does not create body eleents for an empty definition' do
|
104
104
|
sexp = s(:class,
|
105
105
|
s(:const_ref, s(:@const, 'Foo', s(1, 13))), nil,
|
106
|
-
s(:bodystmt, s(:stmts, s(:void_stmt)), nil, nil, nil))
|
106
|
+
s(:bodystmt, s(:stmts, s(:void_stmt, s(2, 8))), nil, nil, nil))
|
107
107
|
result = processor.process sexp
|
108
108
|
result.must_equal s(:class, :Foo, nil)
|
109
109
|
end
|
@@ -128,7 +128,7 @@ describe RipperRubyParser::SexpProcessor do
|
|
128
128
|
sexp = s(:class,
|
129
129
|
s(:const_ref, s(:@const, 'Foo', s(1, 13))),
|
130
130
|
s(:var_ref, s(:@const, 'Bar', s(1, 12))),
|
131
|
-
s(:bodystmt, s(:stmts, s(:void_stmt)), nil, nil, nil))
|
131
|
+
s(:bodystmt, s(:stmts, s(:void_stmt, s(2, 7))), nil, nil, nil))
|
132
132
|
result = processor.process sexp
|
133
133
|
result.must_equal s(:class, :Foo, s(:const, :Bar))
|
134
134
|
end
|
@@ -153,7 +153,7 @@ describe RipperRubyParser::SexpProcessor do
|
|
153
153
|
sexp = s(:def,
|
154
154
|
s(:@ident, 'foo', s(1, 4)),
|
155
155
|
s(:params, nil, nil, nil, nil, nil),
|
156
|
-
s(:bodystmt, s(:stmts, s(:void_stmt)), nil, nil, nil))
|
156
|
+
s(:bodystmt, s(:stmts, s(:void_stmt, s(2, 3))), nil, nil, nil))
|
157
157
|
result = processor.process sexp
|
158
158
|
result.must_equal s(:defn, :foo, s(:args), s(:nil))
|
159
159
|
end
|
data/test/test_helper.rb
CHANGED
@@ -13,14 +13,36 @@ require 'ripper_ruby_parser'
|
|
13
13
|
|
14
14
|
module MiniTest
|
15
15
|
class Spec
|
16
|
-
def
|
17
|
-
exp.
|
16
|
+
def inspect_with_line_numbers(exp)
|
17
|
+
parts = exp.map do |sub_exp|
|
18
|
+
if sub_exp.is_a? Sexp
|
19
|
+
inspect_with_line_numbers(sub_exp)
|
20
|
+
else
|
21
|
+
sub_exp.inspect
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
plain = "s(#{parts.join(', ')})"
|
26
|
+
if exp.line
|
27
|
+
"#{plain}.line(#{exp.line})"
|
28
|
+
else
|
29
|
+
plain
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def formatted(exp, with_line_numbers: false)
|
34
|
+
inspection = if with_line_numbers
|
35
|
+
inspect_with_line_numbers(exp)
|
36
|
+
else
|
37
|
+
exp.inspect
|
38
|
+
end
|
39
|
+
inspection.gsub(/\), /, "),\n")
|
18
40
|
end
|
19
41
|
|
20
42
|
def fix_lines(exp)
|
21
|
-
return s(:lit, :__LINE__) if exp.sexp_type == :lit && exp.line == exp[1]
|
43
|
+
return s(:lit, :__LINE__).line(exp.line) if exp.sexp_type == :lit && exp.line == exp[1]
|
22
44
|
|
23
|
-
|
45
|
+
exp.sexp_body = exp.sexp_body.map do |sub_exp|
|
24
46
|
if sub_exp.is_a? Sexp
|
25
47
|
fix_lines sub_exp
|
26
48
|
else
|
@@ -28,11 +50,13 @@ module MiniTest
|
|
28
50
|
end
|
29
51
|
end
|
30
52
|
|
31
|
-
|
53
|
+
exp
|
32
54
|
end
|
33
55
|
|
34
56
|
def to_comments(exp)
|
35
|
-
|
57
|
+
comments = exp.comments.to_s.gsub(/\n\s*\n/, "\n")
|
58
|
+
|
59
|
+
exp.sexp_body = exp.sexp_body.map do |sub_exp|
|
36
60
|
if sub_exp.is_a? Sexp
|
37
61
|
to_comments sub_exp
|
38
62
|
else
|
@@ -40,15 +64,14 @@ module MiniTest
|
|
40
64
|
end
|
41
65
|
end
|
42
66
|
|
43
|
-
comments = exp.comments.to_s.gsub(/\n\s*\n/, "\n")
|
44
67
|
if comments.empty?
|
45
|
-
|
68
|
+
exp
|
46
69
|
else
|
47
|
-
s(:comment, comments,
|
70
|
+
s(:comment, comments, exp)
|
48
71
|
end
|
49
72
|
end
|
50
73
|
|
51
|
-
def assert_parsed_as(sexp, code, extra_compatible: false)
|
74
|
+
def assert_parsed_as(sexp, code, extra_compatible: false, with_line_numbers: false)
|
52
75
|
parser = RipperRubyParser::Parser.new
|
53
76
|
parser.extra_compatible = extra_compatible
|
54
77
|
result = parser.parse code
|
@@ -56,11 +79,12 @@ module MiniTest
|
|
56
79
|
assert_nil result
|
57
80
|
else
|
58
81
|
assert_equal sexp, result
|
59
|
-
assert_equal
|
82
|
+
assert_equal(formatted(sexp, with_line_numbers: with_line_numbers),
|
83
|
+
formatted(result, with_line_numbers: with_line_numbers))
|
60
84
|
end
|
61
85
|
end
|
62
86
|
|
63
|
-
def assert_parsed_as_before(code)
|
87
|
+
def assert_parsed_as_before(code, with_line_numbers: false)
|
64
88
|
oldparser = RubyParser.for_current_ruby
|
65
89
|
newparser = RipperRubyParser::Parser.new
|
66
90
|
newparser.extra_compatible = true
|
@@ -68,7 +92,9 @@ module MiniTest
|
|
68
92
|
result = newparser.parse code
|
69
93
|
expected = to_comments fix_lines expected
|
70
94
|
result = to_comments fix_lines result
|
71
|
-
assert_equal
|
95
|
+
assert_equal expected, result
|
96
|
+
assert_equal(formatted(expected, with_line_numbers: with_line_numbers),
|
97
|
+
formatted(result, with_line_numbers: with_line_numbers))
|
72
98
|
end
|
73
99
|
end
|
74
100
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ripper_ruby_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matijs van Zuijlen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sexp_processor
|