ripper_ruby_parser 1.6.0 → 1.6.1
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 +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
|