ripper_ruby_parser 1.4.2 → 1.5.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 +33 -1
- data/README.md +41 -9
- data/Rakefile +2 -0
- data/lib/ripper_ruby_parser.rb +2 -0
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +23 -45
- data/lib/ripper_ruby_parser/parser.rb +11 -1
- data/lib/ripper_ruby_parser/sexp_handlers.rb +2 -6
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +49 -35
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +78 -39
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +16 -15
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +19 -15
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +138 -30
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +10 -6
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +59 -14
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +56 -32
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +20 -27
- data/lib/ripper_ruby_parser/sexp_processor.rb +40 -10
- data/lib/ripper_ruby_parser/syntax_error.rb +2 -0
- data/lib/ripper_ruby_parser/unescape.rb +32 -11
- data/lib/ripper_ruby_parser/version.rb +3 -1
- data/test/end_to_end/comments_test.rb +2 -0
- data/test/end_to_end/comparison_test.rb +2 -0
- data/test/end_to_end/lib_comparison_test.rb +2 -0
- data/test/end_to_end/line_numbering_test.rb +2 -0
- data/test/end_to_end/samples_comparison_test.rb +5 -29
- data/test/end_to_end/test_comparison_test.rb +2 -0
- data/test/pt_testcase/pt_test.rb +2 -0
- data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +16 -2
- data/test/ripper_ruby_parser/parser_test.rb +17 -688
- data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +459 -26
- data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +152 -82
- data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +91 -0
- data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +331 -24
- data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +88 -0
- data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +58 -5
- data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +392 -0
- data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +174 -12
- data/test/ripper_ruby_parser/sexp_processor_test.rb +8 -18
- data/test/ripper_ruby_parser/version_test.rb +2 -0
- data/test/samples/comments.rb +13 -0
- data/test/samples/conditionals.rb +23 -0
- data/test/samples/loops.rb +36 -0
- data/test/samples/misc.rb +157 -5
- data/test/samples/number.rb +7 -0
- data/test/samples/strings.rb +39 -0
- data/test/test_helper.rb +22 -1
- metadata +18 -12
- data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +0 -29
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +0 -21
- data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +0 -48
@@ -1,15 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RipperRubyParser
|
2
4
|
# Implements string unescaping
|
3
5
|
#
|
4
6
|
# @api private
|
5
7
|
module Unescape
|
6
|
-
module_function
|
7
|
-
|
8
8
|
ESCAPE_SEQUENCE_REGEXP =
|
9
9
|
/\\(
|
10
10
|
[0-7]{1,3} | # octal character
|
11
11
|
x[0-9a-fA-F]{1,2} | # hex byte
|
12
|
-
u[0-9a-fA-F]
|
12
|
+
u[0-9a-fA-F]+ | # unicode character
|
13
|
+
u{[0-9a-fA-F]{4}} | # unicode character
|
13
14
|
M-\\C-. | # meta-ctrl
|
14
15
|
C-\\M-. | # ctrl-meta
|
15
16
|
M-\\c. | # meta-ctrl (shorthand)
|
@@ -19,7 +20,7 @@ module RipperRubyParser
|
|
19
20
|
M-. | # meta
|
20
21
|
\n | # line continuation
|
21
22
|
. # single-character
|
22
|
-
)/x
|
23
|
+
)/x.freeze
|
23
24
|
|
24
25
|
SINGLE_LETTER_ESCAPES = {
|
25
26
|
'a' => "\a",
|
@@ -49,6 +50,7 @@ module RipperRubyParser
|
|
49
50
|
string.gsub(/\\(
|
50
51
|
' | # single quote
|
51
52
|
\\ | # backslash
|
53
|
+
[ ] | # space
|
52
54
|
\n # newline
|
53
55
|
)/x) do
|
54
56
|
Regexp.last_match[1]
|
@@ -93,27 +95,46 @@ module RipperRubyParser
|
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
98
|
+
private
|
99
|
+
|
96
100
|
def unescaped_value(bare)
|
97
101
|
case bare
|
98
102
|
when SINGLE_LETTER_ESCAPES_REGEXP
|
99
103
|
SINGLE_LETTER_ESCAPES[bare]
|
100
104
|
when /^x/
|
101
|
-
bare[1..-1]
|
105
|
+
hex_to_char(bare[1..-1])
|
106
|
+
when /^u\{/
|
107
|
+
hex_to_unicode_char(bare[2..-2])
|
102
108
|
when /^u/
|
103
|
-
bare[1
|
109
|
+
hex_to_unicode_char(bare[1..4]) +
|
110
|
+
(extra_compatible ? '' : bare[5..-1])
|
104
111
|
when /^(c|C-).$/
|
105
|
-
(bare[-1].ord
|
112
|
+
control(bare[-1].ord).chr
|
106
113
|
when /^M-.$/
|
107
|
-
(bare[-1].ord
|
114
|
+
meta(bare[-1].ord).chr
|
108
115
|
when /^(M-\\C-|C-\\M-|M-\\c|c\\M-).$/
|
109
|
-
(bare[-1].ord
|
116
|
+
meta(control(bare[-1].ord)).chr
|
110
117
|
when /^[0-7]+/
|
111
118
|
bare.to_i(8).chr
|
112
|
-
when "\n"
|
113
|
-
bare
|
114
119
|
else
|
115
120
|
bare
|
116
121
|
end
|
117
122
|
end
|
123
|
+
|
124
|
+
def hex_to_unicode_char(str)
|
125
|
+
str.to_i(16).chr(Encoding::UTF_8)
|
126
|
+
end
|
127
|
+
|
128
|
+
def hex_to_char(str)
|
129
|
+
str.to_i(16).chr
|
130
|
+
end
|
131
|
+
|
132
|
+
def control(val)
|
133
|
+
val & 0b1001_1111
|
134
|
+
end
|
135
|
+
|
136
|
+
def meta(val)
|
137
|
+
val | 0b1000_0000
|
138
|
+
end
|
118
139
|
end
|
119
140
|
end
|
@@ -1,37 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
4
|
require 'ruby_parser'
|
3
5
|
|
4
6
|
describe 'Using RipperRubyParser and RubyParser' do
|
5
|
-
let :newparser do
|
6
|
-
RipperRubyParser::Parser.new
|
7
|
-
end
|
8
|
-
|
9
|
-
let :oldparser do
|
10
|
-
RubyParser.new
|
11
|
-
end
|
12
|
-
|
13
7
|
Dir.glob(File.expand_path('../samples/*.rb', File.dirname(__FILE__))).each do |file|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
let :original do
|
20
|
-
oldparser.parse program
|
21
|
-
end
|
22
|
-
|
23
|
-
let :imitation do
|
24
|
-
newparser.parse program
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'gives the same result' do
|
28
|
-
formatted(imitation).must_equal formatted(original)
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'gives the same result with comments' do
|
32
|
-
formatted(to_comments(imitation)).
|
33
|
-
must_equal formatted(to_comments(original))
|
34
|
-
end
|
8
|
+
it "gives the same result for #{file}" do
|
9
|
+
program = File.read file
|
10
|
+
program.must_be_parsed_as_before
|
35
11
|
end
|
36
12
|
end
|
37
13
|
end
|
data/test/pt_testcase/pt_test.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
4
|
|
3
5
|
describe RipperRubyParser::CommentingRipperParser do
|
@@ -99,7 +101,7 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
99
101
|
result.must_equal s(:program,
|
100
102
|
s(:stmts,
|
101
103
|
s(:dyna_symbol,
|
102
|
-
s(:xstring, s(:@tstring_content, 'foo', s(1, 2)))),
|
104
|
+
s(:xstring, s(:@tstring_content, 'foo', s(1, 2), ":'"))),
|
103
105
|
s(:comment,
|
104
106
|
'',
|
105
107
|
s(:def,
|
@@ -114,7 +116,7 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
114
116
|
s(:stmts,
|
115
117
|
s(:dyna_symbol,
|
116
118
|
s(:xstring,
|
117
|
-
s(:@tstring_content, 'foo', s(1, 2)),
|
119
|
+
s(:@tstring_content, 'foo', s(1, 2), ':"'),
|
118
120
|
s(:string_embexpr,
|
119
121
|
s(:stmts,
|
120
122
|
s(:comment,
|
@@ -128,6 +130,18 @@ describe RipperRubyParser::CommentingRipperParser do
|
|
128
130
|
nil,
|
129
131
|
nil)))))))))
|
130
132
|
end
|
133
|
+
|
134
|
+
it 'turns an embedded document into a comment node' do
|
135
|
+
result = parse_with_builder "=begin Hello\nthere\n=end\nclass Foo; end"
|
136
|
+
result.must_equal s(:program,
|
137
|
+
s(:stmts,
|
138
|
+
s(:comment,
|
139
|
+
"=begin Hello\nthere\n=end\n",
|
140
|
+
s(:class,
|
141
|
+
s(:const_ref, s(:@const, 'Foo', s(4, 6))),
|
142
|
+
nil,
|
143
|
+
s(:bodystmt, s(:stmts, s(:void_stmt)), nil, nil, nil)))))
|
144
|
+
end
|
131
145
|
end
|
132
146
|
|
133
147
|
describe 'handling syntax errors' do
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
4
|
|
3
5
|
describe RipperRubyParser::Parser do
|
@@ -28,6 +30,11 @@ describe RipperRubyParser::Parser do
|
|
28
30
|
end
|
29
31
|
|
30
32
|
describe 'for a module declaration' do
|
33
|
+
it 'works with a simple module name' do
|
34
|
+
'module Foo; end'.
|
35
|
+
must_be_parsed_as s(:module, :Foo)
|
36
|
+
end
|
37
|
+
|
31
38
|
it 'works with a namespaced module name' do
|
32
39
|
'module Foo::Bar; end'.
|
33
40
|
must_be_parsed_as s(:module,
|
@@ -41,83 +48,6 @@ describe RipperRubyParser::Parser do
|
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
44
|
-
describe 'for the return statement' do
|
45
|
-
it 'works with no arguments' do
|
46
|
-
'return'.
|
47
|
-
must_be_parsed_as s(:return)
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'works with one argument' do
|
51
|
-
'return foo'.
|
52
|
-
must_be_parsed_as s(:return,
|
53
|
-
s(:call, nil, :foo))
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'works with a splat argument' do
|
57
|
-
'return *foo'.
|
58
|
-
must_be_parsed_as s(:return,
|
59
|
-
s(:svalue,
|
60
|
-
s(:splat,
|
61
|
-
s(:call, nil, :foo))))
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'works with multiple arguments' do
|
65
|
-
'return foo, bar'.
|
66
|
-
must_be_parsed_as s(:return,
|
67
|
-
s(:array,
|
68
|
-
s(:call, nil, :foo),
|
69
|
-
s(:call, nil, :bar)))
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'works with a regular argument and a splat argument' do
|
73
|
-
'return foo, *bar'.
|
74
|
-
must_be_parsed_as s(:return,
|
75
|
-
s(:array,
|
76
|
-
s(:call, nil, :foo),
|
77
|
-
s(:splat,
|
78
|
-
s(:call, nil, :bar))))
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'works with a function call with parentheses' do
|
82
|
-
'return foo(bar)'.
|
83
|
-
must_be_parsed_as s(:return,
|
84
|
-
s(:call, nil, :foo,
|
85
|
-
s(:call, nil, :bar)))
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'works with a function call without parentheses' do
|
89
|
-
'return foo bar'.
|
90
|
-
must_be_parsed_as s(:return,
|
91
|
-
s(:call, nil, :foo,
|
92
|
-
s(:call, nil, :bar)))
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe 'for the for statement' do
|
97
|
-
it 'works with do' do
|
98
|
-
'for foo in bar do; baz; end'.
|
99
|
-
must_be_parsed_as s(:for,
|
100
|
-
s(:call, nil, :bar),
|
101
|
-
s(:lasgn, :foo),
|
102
|
-
s(:call, nil, :baz))
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'works without do' do
|
106
|
-
'for foo in bar; baz; end'.
|
107
|
-
must_be_parsed_as s(:for,
|
108
|
-
s(:call, nil, :bar),
|
109
|
-
s(:lasgn, :foo),
|
110
|
-
s(:call, nil, :baz))
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'works with an empty body' do
|
114
|
-
'for foo in bar; end'.
|
115
|
-
must_be_parsed_as s(:for,
|
116
|
-
s(:call, nil, :bar),
|
117
|
-
s(:lasgn, :foo))
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
51
|
describe 'for a begin..end block' do
|
122
52
|
it 'works with no statements' do
|
123
53
|
'begin; end'.
|
@@ -137,57 +67,6 @@ describe RipperRubyParser::Parser do
|
|
137
67
|
end
|
138
68
|
end
|
139
69
|
|
140
|
-
describe 'for the undef statement' do
|
141
|
-
it 'works with a single bareword identifier' do
|
142
|
-
'undef foo'.
|
143
|
-
must_be_parsed_as s(:undef, s(:lit, :foo))
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'works with a single symbol' do
|
147
|
-
'undef :foo'.
|
148
|
-
must_be_parsed_as s(:undef, s(:lit, :foo))
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'works with multiple bareword identifiers' do
|
152
|
-
'undef foo, bar'.
|
153
|
-
must_be_parsed_as s(:block,
|
154
|
-
s(:undef, s(:lit, :foo)),
|
155
|
-
s(:undef, s(:lit, :bar)))
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'works with multiple bareword symbols' do
|
159
|
-
'undef :foo, :bar'.
|
160
|
-
must_be_parsed_as s(:block,
|
161
|
-
s(:undef, s(:lit, :foo)),
|
162
|
-
s(:undef, s(:lit, :bar)))
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
describe 'for the alias statement' do
|
167
|
-
it 'works with regular barewords' do
|
168
|
-
'alias foo bar'.
|
169
|
-
must_be_parsed_as s(:alias,
|
170
|
-
s(:lit, :foo), s(:lit, :bar))
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'works with symbols' do
|
174
|
-
'alias :foo :bar'.
|
175
|
-
must_be_parsed_as s(:alias,
|
176
|
-
s(:lit, :foo), s(:lit, :bar))
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'works with operator barewords' do
|
180
|
-
'alias + -'.
|
181
|
-
must_be_parsed_as s(:alias,
|
182
|
-
s(:lit, :+), s(:lit, :-))
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'works with global variables' do
|
186
|
-
'alias $foo $bar'.
|
187
|
-
must_be_parsed_as s(:valias, :$foo, :$bar)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
70
|
describe 'for arguments' do
|
192
71
|
it 'works for a simple case with splat' do
|
193
72
|
'foo *bar'.
|
@@ -222,241 +101,6 @@ describe RipperRubyParser::Parser do
|
|
222
101
|
end
|
223
102
|
end
|
224
103
|
|
225
|
-
describe 'for collection indexing' do
|
226
|
-
it 'works in the simple case' do
|
227
|
-
'foo[bar]'.
|
228
|
-
must_be_parsed_as s(:call,
|
229
|
-
s(:call, nil, :foo),
|
230
|
-
:[],
|
231
|
-
s(:call, nil, :bar))
|
232
|
-
end
|
233
|
-
|
234
|
-
it 'works without any indexes' do
|
235
|
-
'foo[]'.must_be_parsed_as s(:call, s(:call, nil, :foo),
|
236
|
-
:[])
|
237
|
-
end
|
238
|
-
|
239
|
-
it 'works with self[]' do
|
240
|
-
'self[foo]'.must_be_parsed_as s(:call, s(:self), :[],
|
241
|
-
s(:call, nil, :foo))
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
describe 'for method definitions' do
|
246
|
-
it 'works with def with receiver' do
|
247
|
-
'def foo.bar; end'.
|
248
|
-
must_be_parsed_as s(:defs,
|
249
|
-
s(:call, nil, :foo),
|
250
|
-
:bar,
|
251
|
-
s(:args),
|
252
|
-
s(:nil))
|
253
|
-
end
|
254
|
-
|
255
|
-
it 'works with def with receiver and multiple statements' do
|
256
|
-
'def foo.bar; baz; qux; end'.
|
257
|
-
must_be_parsed_as s(:defs,
|
258
|
-
s(:call, nil, :foo),
|
259
|
-
:bar,
|
260
|
-
s(:args),
|
261
|
-
s(:call, nil, :baz),
|
262
|
-
s(:call, nil, :qux))
|
263
|
-
end
|
264
|
-
|
265
|
-
it 'works with a method argument with a default value' do
|
266
|
-
'def foo bar=nil; end'.
|
267
|
-
must_be_parsed_as s(:defn,
|
268
|
-
:foo,
|
269
|
-
s(:args, s(:lasgn, :bar, s(:nil))),
|
270
|
-
s(:nil))
|
271
|
-
end
|
272
|
-
|
273
|
-
it 'works with several method arguments with default values' do
|
274
|
-
'def foo bar=1, baz=2; end'.
|
275
|
-
must_be_parsed_as s(:defn,
|
276
|
-
:foo,
|
277
|
-
s(:args,
|
278
|
-
s(:lasgn, :bar, s(:lit, 1)),
|
279
|
-
s(:lasgn, :baz, s(:lit, 2))),
|
280
|
-
s(:nil))
|
281
|
-
end
|
282
|
-
|
283
|
-
it 'works with parentheses around the parameter list' do
|
284
|
-
'def foo(bar); end'.
|
285
|
-
must_be_parsed_as s(:defn, :foo, s(:args, :bar), s(:nil))
|
286
|
-
end
|
287
|
-
|
288
|
-
it 'works with a simple splat' do
|
289
|
-
'def foo *bar; end'.
|
290
|
-
must_be_parsed_as s(:defn, :foo, s(:args, :"*bar"), s(:nil))
|
291
|
-
end
|
292
|
-
|
293
|
-
it 'works with a regular argument plus splat' do
|
294
|
-
'def foo bar, *baz; end'.
|
295
|
-
must_be_parsed_as s(:defn, :foo, s(:args, :bar, :"*baz"), s(:nil))
|
296
|
-
end
|
297
|
-
|
298
|
-
it 'works with a nameless splat' do
|
299
|
-
'def foo *; end'.
|
300
|
-
must_be_parsed_as s(:defn,
|
301
|
-
:foo,
|
302
|
-
s(:args, :"*"),
|
303
|
-
s(:nil))
|
304
|
-
end
|
305
|
-
|
306
|
-
it 'works for a simple case with explicit block parameter' do
|
307
|
-
'def foo &bar; end'.
|
308
|
-
must_be_parsed_as s(:defn,
|
309
|
-
:foo,
|
310
|
-
s(:args, :"&bar"),
|
311
|
-
s(:nil))
|
312
|
-
end
|
313
|
-
|
314
|
-
it 'works with a regular argument plus explicit block parameter' do
|
315
|
-
'def foo bar, &baz; end'.
|
316
|
-
must_be_parsed_as s(:defn,
|
317
|
-
:foo,
|
318
|
-
s(:args, :bar, :"&baz"),
|
319
|
-
s(:nil))
|
320
|
-
end
|
321
|
-
|
322
|
-
it 'works with a default value plus explicit block parameter' do
|
323
|
-
'def foo bar=1, &baz; end'.
|
324
|
-
must_be_parsed_as s(:defn,
|
325
|
-
:foo,
|
326
|
-
s(:args,
|
327
|
-
s(:lasgn, :bar, s(:lit, 1)),
|
328
|
-
:"&baz"),
|
329
|
-
s(:nil))
|
330
|
-
end
|
331
|
-
|
332
|
-
it 'works with a default value plus mandatory argument' do
|
333
|
-
'def foo bar=1, baz; end'.
|
334
|
-
must_be_parsed_as s(:defn,
|
335
|
-
:foo,
|
336
|
-
s(:args,
|
337
|
-
s(:lasgn, :bar, s(:lit, 1)),
|
338
|
-
:baz),
|
339
|
-
s(:nil))
|
340
|
-
end
|
341
|
-
|
342
|
-
it 'works with a splat plus explicit block parameter' do
|
343
|
-
'def foo *bar, &baz; end'.
|
344
|
-
must_be_parsed_as s(:defn,
|
345
|
-
:foo,
|
346
|
-
s(:args, :"*bar", :"&baz"),
|
347
|
-
s(:nil))
|
348
|
-
end
|
349
|
-
|
350
|
-
it 'works with a default value plus splat' do
|
351
|
-
'def foo bar=1, *baz; end'.
|
352
|
-
must_be_parsed_as s(:defn,
|
353
|
-
:foo,
|
354
|
-
s(:args,
|
355
|
-
s(:lasgn, :bar, s(:lit, 1)),
|
356
|
-
:"*baz"),
|
357
|
-
s(:nil))
|
358
|
-
end
|
359
|
-
|
360
|
-
it 'works with a default value, splat, plus final mandatory arguments' do
|
361
|
-
'def foo bar=1, *baz, qux, quuz; end'.
|
362
|
-
must_be_parsed_as s(:defn,
|
363
|
-
:foo,
|
364
|
-
s(:args,
|
365
|
-
s(:lasgn, :bar, s(:lit, 1)),
|
366
|
-
:"*baz", :qux, :quuz),
|
367
|
-
s(:nil))
|
368
|
-
end
|
369
|
-
|
370
|
-
it 'works with a named argument with a default value' do
|
371
|
-
'def foo bar: 1; end'.
|
372
|
-
must_be_parsed_as s(:defn,
|
373
|
-
:foo,
|
374
|
-
s(:args,
|
375
|
-
s(:kwarg, :bar, s(:lit, 1))),
|
376
|
-
s(:nil))
|
377
|
-
end
|
378
|
-
|
379
|
-
it 'works with a named argument with no default value' do
|
380
|
-
'def foo bar:; end'.
|
381
|
-
must_be_parsed_as s(:defn,
|
382
|
-
:foo,
|
383
|
-
s(:args,
|
384
|
-
s(:kwarg, :bar)),
|
385
|
-
s(:nil))
|
386
|
-
end
|
387
|
-
|
388
|
-
it 'works with a double splat' do
|
389
|
-
'def foo **bar; end'.
|
390
|
-
must_be_parsed_as s(:defn,
|
391
|
-
:foo,
|
392
|
-
s(:args, :'**bar'),
|
393
|
-
s(:nil))
|
394
|
-
end
|
395
|
-
|
396
|
-
it 'works when the method name is an operator' do
|
397
|
-
'def +; end'.
|
398
|
-
must_be_parsed_as s(:defn, :+, s(:args),
|
399
|
-
s(:nil))
|
400
|
-
end
|
401
|
-
end
|
402
|
-
|
403
|
-
describe 'for yield' do
|
404
|
-
it 'works with no arguments and no parentheses' do
|
405
|
-
'yield'.
|
406
|
-
must_be_parsed_as s(:yield)
|
407
|
-
end
|
408
|
-
|
409
|
-
it 'works with parentheses but no arguments' do
|
410
|
-
'yield()'.
|
411
|
-
must_be_parsed_as s(:yield)
|
412
|
-
end
|
413
|
-
|
414
|
-
it 'works with one argument and no parentheses' do
|
415
|
-
'yield foo'.
|
416
|
-
must_be_parsed_as s(:yield, s(:call, nil, :foo))
|
417
|
-
end
|
418
|
-
|
419
|
-
it 'works with one argument and parentheses' do
|
420
|
-
'yield(foo)'.
|
421
|
-
must_be_parsed_as s(:yield, s(:call, nil, :foo))
|
422
|
-
end
|
423
|
-
|
424
|
-
it 'works with multiple arguments and no parentheses' do
|
425
|
-
'yield foo, bar'.
|
426
|
-
must_be_parsed_as s(:yield,
|
427
|
-
s(:call, nil, :foo),
|
428
|
-
s(:call, nil, :bar))
|
429
|
-
end
|
430
|
-
|
431
|
-
it 'works with multiple arguments and parentheses' do
|
432
|
-
'yield(foo, bar)'.
|
433
|
-
must_be_parsed_as s(:yield,
|
434
|
-
s(:call, nil, :foo),
|
435
|
-
s(:call, nil, :bar))
|
436
|
-
end
|
437
|
-
|
438
|
-
it 'works with splat' do
|
439
|
-
'yield foo, *bar'.
|
440
|
-
must_be_parsed_as s(:yield,
|
441
|
-
s(:call, nil, :foo),
|
442
|
-
s(:splat, s(:call, nil, :bar)))
|
443
|
-
end
|
444
|
-
|
445
|
-
it 'works with a function call with parentheses' do
|
446
|
-
'yield foo(bar)'.
|
447
|
-
must_be_parsed_as s(:yield,
|
448
|
-
s(:call, nil, :foo,
|
449
|
-
s(:call, nil, :bar)))
|
450
|
-
end
|
451
|
-
|
452
|
-
it 'works with a function call without parentheses' do
|
453
|
-
'yield foo bar'.
|
454
|
-
must_be_parsed_as s(:yield,
|
455
|
-
s(:call, nil, :foo,
|
456
|
-
s(:call, nil, :bar)))
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
104
|
describe 'for the __ENCODING__ keyword' do
|
461
105
|
it 'evaluates to the equivalent of Encoding::UTF_8' do
|
462
106
|
'__ENCODING__'.
|
@@ -494,6 +138,11 @@ describe RipperRubyParser::Parser do
|
|
494
138
|
'END { foo }'.
|
495
139
|
must_be_parsed_as s(:iter, s(:postexe), 0, s(:call, nil, :foo))
|
496
140
|
end
|
141
|
+
|
142
|
+
it 'works with an empty block' do
|
143
|
+
'END { }'.
|
144
|
+
must_be_parsed_as s(:iter, s(:postexe), 0)
|
145
|
+
end
|
497
146
|
end
|
498
147
|
|
499
148
|
describe 'for the BEGIN keyword' do
|
@@ -501,6 +150,11 @@ describe RipperRubyParser::Parser do
|
|
501
150
|
'BEGIN { foo }'.
|
502
151
|
must_be_parsed_as s(:iter, s(:preexe), s(:args), s(:call, nil, :foo))
|
503
152
|
end
|
153
|
+
|
154
|
+
it 'works with an empty block' do
|
155
|
+
'BEGIN { }'.
|
156
|
+
must_be_parsed_as s(:iter, s(:preexe), s(:args))
|
157
|
+
end
|
504
158
|
end
|
505
159
|
|
506
160
|
describe 'for constant lookups' do
|
@@ -553,307 +207,6 @@ describe RipperRubyParser::Parser do
|
|
553
207
|
end
|
554
208
|
end
|
555
209
|
|
556
|
-
describe 'for single assignment' do
|
557
|
-
it 'works when assigning to an instance variable' do
|
558
|
-
'@foo = bar'.
|
559
|
-
must_be_parsed_as s(:iasgn,
|
560
|
-
:@foo,
|
561
|
-
s(:call, nil, :bar))
|
562
|
-
end
|
563
|
-
|
564
|
-
it 'works when assigning to a constant' do
|
565
|
-
'FOO = bar'.
|
566
|
-
must_be_parsed_as s(:cdecl,
|
567
|
-
:FOO,
|
568
|
-
s(:call, nil, :bar))
|
569
|
-
end
|
570
|
-
|
571
|
-
it 'works when assigning to a collection element' do
|
572
|
-
'foo[bar] = baz'.
|
573
|
-
must_be_parsed_as s(:attrasgn,
|
574
|
-
s(:call, nil, :foo),
|
575
|
-
:[]=,
|
576
|
-
s(:call, nil, :bar),
|
577
|
-
s(:call, nil, :baz))
|
578
|
-
end
|
579
|
-
|
580
|
-
it 'works when assigning to an attribute' do
|
581
|
-
'foo.bar = baz'.
|
582
|
-
must_be_parsed_as s(:attrasgn,
|
583
|
-
s(:call, nil, :foo),
|
584
|
-
:bar=,
|
585
|
-
s(:call, nil, :baz))
|
586
|
-
end
|
587
|
-
|
588
|
-
it 'works when assigning to a class variable' do
|
589
|
-
'@@foo = bar'.
|
590
|
-
must_be_parsed_as s(:cvdecl,
|
591
|
-
:@@foo,
|
592
|
-
s(:call, nil, :bar))
|
593
|
-
end
|
594
|
-
|
595
|
-
it 'works when assigning to a class variable inside a method' do
|
596
|
-
'def foo; @@bar = baz; end'.
|
597
|
-
must_be_parsed_as s(:defn,
|
598
|
-
:foo, s(:args),
|
599
|
-
s(:cvasgn, :@@bar, s(:call, nil, :baz)))
|
600
|
-
end
|
601
|
-
|
602
|
-
it 'works when assigning to a class variable inside a method with a receiver' do
|
603
|
-
'def self.foo; @@bar = baz; end'.
|
604
|
-
must_be_parsed_as s(:defs,
|
605
|
-
s(:self),
|
606
|
-
:foo, s(:args),
|
607
|
-
s(:cvasgn, :@@bar, s(:call, nil, :baz)))
|
608
|
-
end
|
609
|
-
|
610
|
-
it 'works when assigning to a global variable' do
|
611
|
-
'$foo = bar'.
|
612
|
-
must_be_parsed_as s(:gasgn,
|
613
|
-
:$foo,
|
614
|
-
s(:call, nil, :bar))
|
615
|
-
end
|
616
|
-
end
|
617
|
-
|
618
|
-
describe 'for operator assignment' do
|
619
|
-
it 'works with +=' do
|
620
|
-
'foo += bar'.
|
621
|
-
must_be_parsed_as s(:lasgn,
|
622
|
-
:foo,
|
623
|
-
s(:call,
|
624
|
-
s(:lvar, :foo),
|
625
|
-
:+,
|
626
|
-
s(:call, nil, :bar)))
|
627
|
-
end
|
628
|
-
|
629
|
-
it 'works with -=' do
|
630
|
-
'foo -= bar'.
|
631
|
-
must_be_parsed_as s(:lasgn,
|
632
|
-
:foo,
|
633
|
-
s(:call,
|
634
|
-
s(:lvar, :foo),
|
635
|
-
:-,
|
636
|
-
s(:call, nil, :bar)))
|
637
|
-
end
|
638
|
-
|
639
|
-
it 'works with ||=' do
|
640
|
-
'foo ||= bar'.
|
641
|
-
must_be_parsed_as s(:op_asgn_or,
|
642
|
-
s(:lvar, :foo),
|
643
|
-
s(:lasgn, :foo,
|
644
|
-
s(:call, nil, :bar)))
|
645
|
-
end
|
646
|
-
|
647
|
-
it 'works when assigning to an instance variable' do
|
648
|
-
'@foo += bar'.
|
649
|
-
must_be_parsed_as s(:iasgn,
|
650
|
-
:@foo,
|
651
|
-
s(:call,
|
652
|
-
s(:ivar, :@foo),
|
653
|
-
:+,
|
654
|
-
s(:call, nil, :bar)))
|
655
|
-
end
|
656
|
-
|
657
|
-
it 'works when assigning to a collection element' do
|
658
|
-
'foo[bar] += baz'.
|
659
|
-
must_be_parsed_as s(:op_asgn1,
|
660
|
-
s(:call, nil, :foo),
|
661
|
-
s(:arglist, s(:call, nil, :bar)),
|
662
|
-
:+,
|
663
|
-
s(:call, nil, :baz))
|
664
|
-
end
|
665
|
-
|
666
|
-
it 'works with ||= when assigning to a collection element' do
|
667
|
-
'foo[bar] ||= baz'.
|
668
|
-
must_be_parsed_as s(:op_asgn1,
|
669
|
-
s(:call, nil, :foo),
|
670
|
-
s(:arglist, s(:call, nil, :bar)),
|
671
|
-
:"||",
|
672
|
-
s(:call, nil, :baz))
|
673
|
-
end
|
674
|
-
|
675
|
-
it 'works when assigning to an attribute' do
|
676
|
-
'foo.bar += baz'.
|
677
|
-
must_be_parsed_as s(:op_asgn2,
|
678
|
-
s(:call, nil, :foo),
|
679
|
-
:bar=,
|
680
|
-
:+,
|
681
|
-
s(:call, nil, :baz))
|
682
|
-
end
|
683
|
-
|
684
|
-
it 'works with ||= when assigning to an attribute' do
|
685
|
-
'foo.bar ||= baz'.
|
686
|
-
must_be_parsed_as s(:op_asgn2,
|
687
|
-
s(:call, nil, :foo),
|
688
|
-
:bar=,
|
689
|
-
:"||",
|
690
|
-
s(:call, nil, :baz))
|
691
|
-
end
|
692
|
-
end
|
693
|
-
|
694
|
-
describe 'for multiple assignment' do
|
695
|
-
it 'works the same number of items on each side' do
|
696
|
-
'foo, bar = baz, qux'.
|
697
|
-
must_be_parsed_as s(:masgn,
|
698
|
-
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
699
|
-
s(:array,
|
700
|
-
s(:call, nil, :baz),
|
701
|
-
s(:call, nil, :qux)))
|
702
|
-
end
|
703
|
-
|
704
|
-
it 'works with a single item on the right-hand side' do
|
705
|
-
'foo, bar = baz'.
|
706
|
-
must_be_parsed_as s(:masgn,
|
707
|
-
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
708
|
-
s(:to_ary,
|
709
|
-
s(:call, nil, :baz)))
|
710
|
-
end
|
711
|
-
|
712
|
-
it 'works with left-hand splat' do
|
713
|
-
'foo, *bar = baz, qux'.
|
714
|
-
must_be_parsed_as s(:masgn,
|
715
|
-
s(:array, s(:lasgn, :foo), s(:splat, s(:lasgn, :bar))),
|
716
|
-
s(:array,
|
717
|
-
s(:call, nil, :baz),
|
718
|
-
s(:call, nil, :qux)))
|
719
|
-
end
|
720
|
-
|
721
|
-
it 'works with parentheses around the left-hand side' do
|
722
|
-
'(foo, bar) = baz'.
|
723
|
-
must_be_parsed_as s(:masgn,
|
724
|
-
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
725
|
-
s(:to_ary, s(:call, nil, :baz)))
|
726
|
-
end
|
727
|
-
|
728
|
-
it 'works with complex destructuring' do
|
729
|
-
'foo, (bar, baz) = qux'.
|
730
|
-
must_be_parsed_as s(:masgn,
|
731
|
-
s(:array,
|
732
|
-
s(:lasgn, :foo),
|
733
|
-
s(:masgn,
|
734
|
-
s(:array, s(:lasgn, :bar), s(:lasgn, :baz)))),
|
735
|
-
s(:to_ary, s(:call, nil, :qux)))
|
736
|
-
end
|
737
|
-
|
738
|
-
it 'works with complex destructuring of the value' do
|
739
|
-
'foo, (bar, baz) = [qux, [quz, quuz]]'.
|
740
|
-
must_be_parsed_as s(:masgn,
|
741
|
-
s(:array,
|
742
|
-
s(:lasgn, :foo),
|
743
|
-
s(:masgn, s(:array, s(:lasgn, :bar), s(:lasgn, :baz)))),
|
744
|
-
s(:to_ary,
|
745
|
-
s(:array,
|
746
|
-
s(:call, nil, :qux),
|
747
|
-
s(:array, s(:call, nil, :quz), s(:call, nil, :quuz)))))
|
748
|
-
end
|
749
|
-
|
750
|
-
it 'works with instance variables' do
|
751
|
-
'@foo, @bar = baz'.
|
752
|
-
must_be_parsed_as s(:masgn,
|
753
|
-
s(:array, s(:iasgn, :@foo), s(:iasgn, :@bar)),
|
754
|
-
s(:to_ary, s(:call, nil, :baz)))
|
755
|
-
end
|
756
|
-
|
757
|
-
it 'works with class variables' do
|
758
|
-
'@@foo, @@bar = baz'.
|
759
|
-
must_be_parsed_as s(:masgn,
|
760
|
-
s(:array, s(:cvdecl, :@@foo), s(:cvdecl, :@@bar)),
|
761
|
-
s(:to_ary, s(:call, nil, :baz)))
|
762
|
-
end
|
763
|
-
|
764
|
-
it 'works with attributes' do
|
765
|
-
'foo.bar, foo.baz = qux'.
|
766
|
-
must_be_parsed_as s(:masgn,
|
767
|
-
s(:array,
|
768
|
-
s(:attrasgn, s(:call, nil, :foo), :bar=),
|
769
|
-
s(:attrasgn, s(:call, nil, :foo), :baz=)),
|
770
|
-
s(:to_ary, s(:call, nil, :qux)))
|
771
|
-
end
|
772
|
-
|
773
|
-
it 'works with collection elements' do
|
774
|
-
'foo[1], bar[2] = baz'.
|
775
|
-
must_be_parsed_as s(:masgn,
|
776
|
-
s(:array,
|
777
|
-
s(:attrasgn,
|
778
|
-
s(:call, nil, :foo), :[]=, s(:lit, 1)),
|
779
|
-
s(:attrasgn,
|
780
|
-
s(:call, nil, :bar), :[]=, s(:lit, 2))),
|
781
|
-
s(:to_ary, s(:call, nil, :baz)))
|
782
|
-
end
|
783
|
-
|
784
|
-
it 'works with constants' do
|
785
|
-
'Foo, Bar = baz'.
|
786
|
-
must_be_parsed_as s(:masgn,
|
787
|
-
s(:array, s(:cdecl, :Foo), s(:cdecl, :Bar)),
|
788
|
-
s(:to_ary, s(:call, nil, :baz)))
|
789
|
-
end
|
790
|
-
|
791
|
-
it 'works with instance variables and splat' do
|
792
|
-
'@foo, *@bar = baz'.
|
793
|
-
must_be_parsed_as s(:masgn,
|
794
|
-
s(:array,
|
795
|
-
s(:iasgn, :@foo),
|
796
|
-
s(:splat, s(:iasgn, :@bar))),
|
797
|
-
s(:to_ary,
|
798
|
-
s(:call, nil, :baz)))
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
802
|
-
describe 'for operators' do
|
803
|
-
it 'handles :!=' do
|
804
|
-
'foo != bar'.
|
805
|
-
must_be_parsed_as s(:call,
|
806
|
-
s(:call, nil, :foo),
|
807
|
-
:!=,
|
808
|
-
s(:call, nil, :bar))
|
809
|
-
end
|
810
|
-
|
811
|
-
it 'handles :=~ with two non-literals' do
|
812
|
-
'foo =~ bar'.
|
813
|
-
must_be_parsed_as s(:call,
|
814
|
-
s(:call, nil, :foo),
|
815
|
-
:=~,
|
816
|
-
s(:call, nil, :bar))
|
817
|
-
end
|
818
|
-
|
819
|
-
it 'handles :=~ with literal regexp on the left hand side' do
|
820
|
-
'/foo/ =~ bar'.
|
821
|
-
must_be_parsed_as s(:match2,
|
822
|
-
s(:lit, /foo/),
|
823
|
-
s(:call, nil, :bar))
|
824
|
-
end
|
825
|
-
|
826
|
-
it 'handles :=~ with literal regexp on the right hand side' do
|
827
|
-
'foo =~ /bar/'.
|
828
|
-
must_be_parsed_as s(:match3,
|
829
|
-
s(:lit, /bar/),
|
830
|
-
s(:call, nil, :foo))
|
831
|
-
end
|
832
|
-
|
833
|
-
it 'handles unary !' do
|
834
|
-
'!foo'.
|
835
|
-
must_be_parsed_as s(:call, s(:call, nil, :foo), :!)
|
836
|
-
end
|
837
|
-
|
838
|
-
it 'converts :not to :!' do
|
839
|
-
'not foo'.
|
840
|
-
must_be_parsed_as s(:call, s(:call, nil, :foo), :!)
|
841
|
-
end
|
842
|
-
|
843
|
-
it 'handles unary ! with a number literal' do
|
844
|
-
'!1'.
|
845
|
-
must_be_parsed_as s(:call, s(:lit, 1), :!)
|
846
|
-
end
|
847
|
-
|
848
|
-
it 'handles the ternary operator' do
|
849
|
-
'foo ? bar : baz'.
|
850
|
-
must_be_parsed_as s(:if,
|
851
|
-
s(:call, nil, :foo),
|
852
|
-
s(:call, nil, :bar),
|
853
|
-
s(:call, nil, :baz))
|
854
|
-
end
|
855
|
-
end
|
856
|
-
|
857
210
|
describe 'for expressions' do
|
858
211
|
it 'handles assignment inside binary operator expressions' do
|
859
212
|
'foo + (bar = baz)'.
|
@@ -938,15 +291,6 @@ describe RipperRubyParser::Parser do
|
|
938
291
|
result[4].comments.must_equal "# bar\n"
|
939
292
|
end
|
940
293
|
|
941
|
-
it 'handles the use of symbols that are keywords' do
|
942
|
-
result = parser.parse "# Foo\ndef bar\n:class\nend"
|
943
|
-
result.must_equal s(:defn,
|
944
|
-
:bar,
|
945
|
-
s(:args),
|
946
|
-
s(:lit, :class))
|
947
|
-
result.comments.must_equal "# Foo\n"
|
948
|
-
end
|
949
|
-
|
950
294
|
it 'handles use of singleton class inside methods' do
|
951
295
|
result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
|
952
296
|
result.must_equal s(:defn,
|
@@ -1052,11 +396,6 @@ describe RipperRubyParser::Parser do
|
|
1052
396
|
result.line.must_equal 1
|
1053
397
|
end
|
1054
398
|
|
1055
|
-
it 'works for a symbol literal' do
|
1056
|
-
result = parser.parse ':foo'
|
1057
|
-
result.line.must_equal 1
|
1058
|
-
end
|
1059
|
-
|
1060
399
|
it 'works for a class definition' do
|
1061
400
|
result = parser.parse 'class Foo; end'
|
1062
401
|
result.line.must_equal 1
|
@@ -1072,16 +411,6 @@ describe RipperRubyParser::Parser do
|
|
1072
411
|
result.line.must_equal 1
|
1073
412
|
end
|
1074
413
|
|
1075
|
-
it 'works for assignment of the empty hash' do
|
1076
|
-
result = parser.parse 'foo = {}'
|
1077
|
-
result.line.must_equal 1
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
it 'works for multiple assignment of empty hashes' do
|
1081
|
-
result = parser.parse 'foo, bar = {}, {}'
|
1082
|
-
result.line.must_equal 1
|
1083
|
-
end
|
1084
|
-
|
1085
414
|
it 'assigns line numbers to nested sexps without their own line numbers' do
|
1086
415
|
result = parser.parse "foo(bar) do\nnext baz\nend\n"
|
1087
416
|
result.must_equal s(:iter,
|