ripper_ruby_parser 0.0.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.
- data/README.rdoc +76 -0
- data/Rakefile +24 -0
- data/lib/ripper_ruby_parser/parser.rb +18 -0
- data/lib/ripper_ruby_parser/sexp_ext.rb +14 -0
- data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +23 -0
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +15 -0
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +80 -0
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +49 -0
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +64 -0
- data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +27 -0
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +49 -0
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +83 -0
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +11 -0
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +47 -0
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +38 -0
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +41 -0
- data/lib/ripper_ruby_parser/sexp_handlers.rb +35 -0
- data/lib/ripper_ruby_parser/sexp_processor.rb +150 -0
- data/lib/ripper_ruby_parser/version.rb +3 -0
- data/lib/ripper_ruby_parser.rb +5 -0
- data/test/end_to_end/comparison_test.rb +56 -0
- data/test/end_to_end/lib_comparison_test.rb +29 -0
- data/test/end_to_end/test_comparison_test.rb +33 -0
- data/test/test_helper.rb +12 -0
- data/test/unit/parser_test.rb +623 -0
- data/test/unit/sexp_processor_test.rb +309 -0
- data/test/unit/version_test.rb +5 -0
- metadata +137 -0
@@ -0,0 +1,623 @@
|
|
1
|
+
require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe RipperRubyParser::Parser do
|
4
|
+
let(:parser) { RipperRubyParser::Parser.new }
|
5
|
+
describe "#parse" do
|
6
|
+
it "returns an s-expression" do
|
7
|
+
result = parser.parse "foo"
|
8
|
+
result.must_be_instance_of Sexp
|
9
|
+
end
|
10
|
+
|
11
|
+
it "post-processes its result with the passed sexp processor" do
|
12
|
+
sexp_p = MiniTest::Mock.new
|
13
|
+
sexp_p.expect :process, s(:result), [Sexp]
|
14
|
+
|
15
|
+
parser = RipperRubyParser::Parser.new sexp_p
|
16
|
+
result = parser.parse "any code"
|
17
|
+
|
18
|
+
result.must_equal s(:result)
|
19
|
+
sexp_p.verify
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "for if" do
|
23
|
+
it "works in the postfix case" do
|
24
|
+
result = parser.parse "foo if bar"
|
25
|
+
result.must_equal s(:if,
|
26
|
+
s(:call, nil, :bar, s(:arglist)),
|
27
|
+
s(:call, nil, :foo, s(:arglist)),
|
28
|
+
nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "works with an else clause" do
|
32
|
+
result = parser.parse "if foo; bar; else; baz; end"
|
33
|
+
result.must_equal s(:if,
|
34
|
+
s(:call, nil, :foo, s(:arglist)),
|
35
|
+
s(:call, nil, :bar, s(:arglist)),
|
36
|
+
s(:call, nil, :baz, s(:arglist)))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "works with an elsif clause" do
|
40
|
+
result = parser.parse "if foo; bar; elsif baz; qux; end"
|
41
|
+
result.must_equal s(:if,
|
42
|
+
s(:call, nil, :foo, s(:arglist)),
|
43
|
+
s(:call, nil, :bar, s(:arglist)),
|
44
|
+
s(:if,
|
45
|
+
s(:call, nil, :baz, s(:arglist)),
|
46
|
+
s(:call, nil, :qux, s(:arglist)),
|
47
|
+
nil))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "for unless" do
|
52
|
+
it "works in the postfix case" do
|
53
|
+
result = parser.parse "foo unless bar"
|
54
|
+
result.must_equal s(:if,
|
55
|
+
s(:call, nil, :bar, s(:arglist)),
|
56
|
+
nil,
|
57
|
+
s(:call, nil, :foo, s(:arglist)))
|
58
|
+
end
|
59
|
+
|
60
|
+
it "works in the block case" do
|
61
|
+
result = parser.parse "unless bar; foo; end"
|
62
|
+
result.must_equal s(:if,
|
63
|
+
s(:call, nil, :bar, s(:arglist)),
|
64
|
+
nil,
|
65
|
+
s(:call, nil, :foo, s(:arglist)))
|
66
|
+
end
|
67
|
+
|
68
|
+
it "works with an else clause" do
|
69
|
+
result = parser.parse "unless foo; bar; else; baz; end"
|
70
|
+
result.must_equal s(:if,
|
71
|
+
s(:call, nil, :foo, s(:arglist)),
|
72
|
+
s(:call, nil, :baz, s(:arglist)),
|
73
|
+
s(:call, nil, :bar, s(:arglist)))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "for a case block" do
|
78
|
+
it "works with a single when clause" do
|
79
|
+
result = parser.parse "case foo; when bar; baz; end"
|
80
|
+
result.must_equal s(:case,
|
81
|
+
s(:call, nil, :foo, s(:arglist)),
|
82
|
+
s(:when,
|
83
|
+
s(:array, s(:call, nil, :bar, s(:arglist))),
|
84
|
+
s(:call, nil, :baz, s(:arglist))),
|
85
|
+
nil)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "works with multiple when clauses" do
|
89
|
+
result = parser.parse "case foo; when bar; baz; when qux; quux; end"
|
90
|
+
result.must_equal s(:case,
|
91
|
+
s(:call, nil, :foo, s(:arglist)),
|
92
|
+
s(:when,
|
93
|
+
s(:array, s(:call, nil, :bar, s(:arglist))),
|
94
|
+
s(:call, nil, :baz, s(:arglist))),
|
95
|
+
s(:when,
|
96
|
+
s(:array, s(:call, nil, :qux, s(:arglist))),
|
97
|
+
s(:call, nil, :quux, s(:arglist))),
|
98
|
+
nil)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "works with multiple statements in the when block" do
|
102
|
+
result = parser.parse "case foo; when bar; baz; qux; end"
|
103
|
+
result.must_equal s(:case,
|
104
|
+
s(:call, nil, :foo, s(:arglist)),
|
105
|
+
s(:when,
|
106
|
+
s(:array, s(:call, nil, :bar, s(:arglist))),
|
107
|
+
s(:block,
|
108
|
+
s(:call, nil, :baz, s(:arglist)),
|
109
|
+
s(:call, nil, :qux, s(:arglist)))),
|
110
|
+
nil)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "works with an else clause" do
|
114
|
+
result = parser.parse "case foo; when bar; baz; else; qux; end"
|
115
|
+
result.must_equal s(:case,
|
116
|
+
s(:call, nil, :foo, s(:arglist)),
|
117
|
+
s(:when,
|
118
|
+
s(:array, s(:call, nil, :bar, s(:arglist))),
|
119
|
+
s(:call, nil, :baz, s(:arglist))),
|
120
|
+
s(:call, nil, :qux, s(:arglist)))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "for the return statement" do
|
125
|
+
it "works with no arguments" do
|
126
|
+
result = parser.parse "return"
|
127
|
+
result.must_equal s(:return)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "works with one argument" do
|
131
|
+
result = parser.parse "return foo"
|
132
|
+
result.must_equal s(:return,
|
133
|
+
s(:call, nil, :foo, s(:arglist)))
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "for the until statement" do
|
138
|
+
it "works with do" do
|
139
|
+
result = parser.parse "until foo do; bar; end"
|
140
|
+
result.must_equal s(:until,
|
141
|
+
s(:call, nil, :foo, s(:arglist)),
|
142
|
+
s(:call, nil, :bar, s(:arglist)), true)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "works without do" do
|
146
|
+
result = parser.parse "until foo; bar; end"
|
147
|
+
result.must_equal s(:until,
|
148
|
+
s(:call, nil, :foo, s(:arglist)),
|
149
|
+
s(:call, nil, :bar, s(:arglist)), true)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "for identifiers" do
|
154
|
+
it "works for an ivar" do
|
155
|
+
result = parser.parse "@foo"
|
156
|
+
result.must_equal s(:ivar, :@foo)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "works for self" do
|
160
|
+
result = parser.parse "self"
|
161
|
+
result.must_equal s(:self)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe "for arguments" do
|
166
|
+
it "works for a simple case with splat" do
|
167
|
+
result = parser.parse "foo *bar"
|
168
|
+
result.must_equal s(:call,
|
169
|
+
nil,
|
170
|
+
:foo,
|
171
|
+
s(:arglist,
|
172
|
+
s(:splat, s(:call, nil, :bar, s(:arglist)))))
|
173
|
+
end
|
174
|
+
|
175
|
+
it "works for a multi-argument case with splat" do
|
176
|
+
result = parser.parse "foo bar, *baz"
|
177
|
+
result.must_equal s(:call,
|
178
|
+
nil,
|
179
|
+
:foo,
|
180
|
+
s(:arglist,
|
181
|
+
s(:call, nil, :bar, s(:arglist)),
|
182
|
+
s(:splat, s(:call, nil, :baz, s(:arglist)))))
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "for array literals" do
|
187
|
+
it "works for an empty array" do
|
188
|
+
result = parser.parse "[]"
|
189
|
+
result.must_equal s(:array)
|
190
|
+
end
|
191
|
+
|
192
|
+
it "works for a simple case with splat" do
|
193
|
+
result = parser.parse "[*foo]"
|
194
|
+
result.must_equal s(:array,
|
195
|
+
s(:splat, s(:call, nil, :foo, s(:arglist))))
|
196
|
+
end
|
197
|
+
|
198
|
+
it "works for a multi-element case with splat" do
|
199
|
+
result = parser.parse "[foo, *bar]"
|
200
|
+
result.must_equal s(:array,
|
201
|
+
s(:call, nil, :foo, s(:arglist)),
|
202
|
+
s(:splat, s(:call, nil, :bar, s(:arglist))))
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "for hash literals" do
|
207
|
+
it "works for an empty hash" do
|
208
|
+
result = parser.parse "{}"
|
209
|
+
result.must_equal s(:hash)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "works for a hash with one pair" do
|
213
|
+
result = parser.parse "{foo => bar}"
|
214
|
+
result.must_equal s(:hash,
|
215
|
+
s(:call, nil, :foo, s(:arglist)),
|
216
|
+
s(:call, nil, :bar, s(:arglist)))
|
217
|
+
end
|
218
|
+
|
219
|
+
it "works for a hash with multiple pairs" do
|
220
|
+
result = parser.parse "{foo => bar, baz => qux}"
|
221
|
+
result.must_equal s(:hash,
|
222
|
+
s(:call, nil, :foo, s(:arglist)),
|
223
|
+
s(:call, nil, :bar, s(:arglist)),
|
224
|
+
s(:call, nil, :baz, s(:arglist)),
|
225
|
+
s(:call, nil, :qux, s(:arglist)))
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "for collection indexing" do
|
230
|
+
it "works in the simple case" do
|
231
|
+
result = parser.parse "foo[bar]"
|
232
|
+
result.must_equal s(:call,
|
233
|
+
s(:call, nil, :foo, s(:arglist)),
|
234
|
+
:[],
|
235
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist))))
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "for method definitions" do
|
240
|
+
it "works with def with reciever" do
|
241
|
+
result = parser.parse "def foo.bar; end"
|
242
|
+
result.must_equal s(:defs,
|
243
|
+
s(:call, nil, :foo, s(:arglist)),
|
244
|
+
:bar,
|
245
|
+
s(:args),
|
246
|
+
s(:scope, s(:block)))
|
247
|
+
end
|
248
|
+
|
249
|
+
it "works with a method argument with a default value" do
|
250
|
+
result = parser.parse "def foo bar=nil; end"
|
251
|
+
result.must_equal s(:defn,
|
252
|
+
:foo,
|
253
|
+
s(:args, :bar, s(:block, s(:lasgn, :bar, s(:nil)))),
|
254
|
+
s(:scope, s(:block, s(:nil))))
|
255
|
+
end
|
256
|
+
|
257
|
+
it "works with several method arguments with default values" do
|
258
|
+
result = parser.parse "def foo bar=1, baz=2; end"
|
259
|
+
result.must_equal s(:defn,
|
260
|
+
:foo,
|
261
|
+
s(:args,
|
262
|
+
:bar, :baz,
|
263
|
+
s(:block,
|
264
|
+
s(:lasgn, :bar, s(:lit, 1)),
|
265
|
+
s(:lasgn, :baz, s(:lit, 2)))),
|
266
|
+
s(:scope, s(:block, s(:nil))))
|
267
|
+
end
|
268
|
+
|
269
|
+
it "works with brackets around the parameter list" do
|
270
|
+
result = parser.parse "def foo(bar); end"
|
271
|
+
result.must_equal s(:defn,
|
272
|
+
:foo,
|
273
|
+
s(:args, :bar),
|
274
|
+
s(:scope, s(:block, s(:nil))))
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "for method calls" do
|
279
|
+
describe "without a reciever" do
|
280
|
+
it "works without brackets" do
|
281
|
+
result = parser.parse "foo bar"
|
282
|
+
result.must_equal s(:call, nil, :foo,
|
283
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist))))
|
284
|
+
end
|
285
|
+
|
286
|
+
it "works with brackets" do
|
287
|
+
result = parser.parse "foo(bar)"
|
288
|
+
result.must_equal s(:call, nil, :foo,
|
289
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist))))
|
290
|
+
end
|
291
|
+
|
292
|
+
it "works with brackets around an empty parameter list" do
|
293
|
+
result = parser.parse "foo()"
|
294
|
+
result.must_equal s(:call, nil, :foo, s(:arglist))
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe "with a reciever" do
|
299
|
+
it "works without brackets" do
|
300
|
+
result = parser.parse "foo.bar baz"
|
301
|
+
result.must_equal s(:call,
|
302
|
+
s(:call, nil, :foo, s(:arglist)),
|
303
|
+
:bar,
|
304
|
+
s(:arglist, s(:call, nil, :baz, s(:arglist))))
|
305
|
+
end
|
306
|
+
|
307
|
+
it "works with brackets" do
|
308
|
+
result = parser.parse "foo.bar(baz)"
|
309
|
+
result.must_equal s(:call,
|
310
|
+
s(:call, nil, :foo, s(:arglist)),
|
311
|
+
:bar,
|
312
|
+
s(:arglist, s(:call, nil, :baz, s(:arglist))))
|
313
|
+
end
|
314
|
+
|
315
|
+
it "works with brackets around a call with no brackets" do
|
316
|
+
result = parser.parse "foo.bar(baz qux)"
|
317
|
+
result.must_equal s(:call,
|
318
|
+
s(:call, nil, :foo, s(:arglist)),
|
319
|
+
:bar,
|
320
|
+
s(:arglist,
|
321
|
+
s(:call, nil, :baz,
|
322
|
+
s(:arglist,
|
323
|
+
s(:call, nil, :qux, s(:arglist))))))
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
describe "with blocks" do
|
328
|
+
it "works for a do block" do
|
329
|
+
result = parser.parse "foo.bar do baz; end"
|
330
|
+
result.must_equal s(:iter,
|
331
|
+
s(:call,
|
332
|
+
s(:call, nil, :foo, s(:arglist)),
|
333
|
+
:bar,
|
334
|
+
s(:arglist)),
|
335
|
+
nil,
|
336
|
+
s(:call, nil, :baz, s(:arglist)))
|
337
|
+
end
|
338
|
+
|
339
|
+
it "works for a do block with several statements" do
|
340
|
+
result = parser.parse "foo.bar do baz; qux; end"
|
341
|
+
result.must_equal s(:iter,
|
342
|
+
s(:call,
|
343
|
+
s(:call, nil, :foo, s(:arglist)),
|
344
|
+
:bar,
|
345
|
+
s(:arglist)),
|
346
|
+
nil,
|
347
|
+
s(:block,
|
348
|
+
s(:call, nil, :baz, s(:arglist)),
|
349
|
+
s(:call, nil, :qux, s(:arglist))))
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
describe "for literals" do
|
355
|
+
it "works for symbols" do
|
356
|
+
result = parser.parse ":foo"
|
357
|
+
result.must_equal s(:lit, :foo)
|
358
|
+
end
|
359
|
+
|
360
|
+
it "works for symbols that look like instance variable names" do
|
361
|
+
result = parser.parse ":@foo"
|
362
|
+
result.must_equal s(:lit, :@foo)
|
363
|
+
end
|
364
|
+
|
365
|
+
it "works for empty strings" do
|
366
|
+
result = parser.parse "''"
|
367
|
+
result.must_equal s(:str, "")
|
368
|
+
end
|
369
|
+
|
370
|
+
it "works for strings with escape sequences" do
|
371
|
+
result = parser.parse "\"\\n\""
|
372
|
+
result.must_equal s(:str, "\n")
|
373
|
+
end
|
374
|
+
|
375
|
+
it "works for strings with escaped backslashes" do
|
376
|
+
result = parser.parse "\"\\\\n\""
|
377
|
+
result.must_equal s(:str, "\\n")
|
378
|
+
end
|
379
|
+
|
380
|
+
it "works for a double-quoted string representing a regex literal with escaped right bracket" do
|
381
|
+
result = parser.parse "\"/\\)/\""
|
382
|
+
result.must_equal s(:str, "/\\)/")
|
383
|
+
end
|
384
|
+
|
385
|
+
it "works for a single-quoted string representing a regex literal with escaped right bracket" do
|
386
|
+
result = parser.parse "'/\\)/'"
|
387
|
+
result.must_equal s(:str, "/\\)/")
|
388
|
+
end
|
389
|
+
|
390
|
+
it "works for a string containing escaped quotes" do
|
391
|
+
result = parser.parse "\"\\\"\""
|
392
|
+
result.must_equal s(:str, "\"")
|
393
|
+
end
|
394
|
+
|
395
|
+
it "works for trivial interpolated strings" do
|
396
|
+
result = parser.parse '"#{foo}"'
|
397
|
+
result.must_equal s(:dstr,
|
398
|
+
"",
|
399
|
+
s(:evstr,
|
400
|
+
s(:call, nil, :foo, s(:arglist))))
|
401
|
+
end
|
402
|
+
|
403
|
+
it "works for basic interpolated strings" do
|
404
|
+
result = parser.parse '"foo#{bar}"'
|
405
|
+
result.must_equal s(:dstr,
|
406
|
+
"foo",
|
407
|
+
s(:evstr,
|
408
|
+
s(:call, nil, :bar, s(:arglist))))
|
409
|
+
end
|
410
|
+
|
411
|
+
it "works for strings with several interpolations" do
|
412
|
+
result = parser.parse '"foo#{bar}baz#{qux}"'
|
413
|
+
result.must_equal s(:dstr,
|
414
|
+
"foo",
|
415
|
+
s(:evstr, s(:call, nil, :bar, s(:arglist))),
|
416
|
+
s(:str, "baz"),
|
417
|
+
s(:evstr, s(:call, nil, :qux, s(:arglist))))
|
418
|
+
end
|
419
|
+
|
420
|
+
it "works for strings with interpolations followed by escape sequences" do
|
421
|
+
result = parser.parse '"#{foo}\\n"'
|
422
|
+
result.must_equal s(:dstr,
|
423
|
+
"",
|
424
|
+
s(:evstr, s(:call, nil, :foo, s(:arglist))),
|
425
|
+
s(:str, "\n"))
|
426
|
+
end
|
427
|
+
|
428
|
+
it "works for a simple regex literal" do
|
429
|
+
result = parser.parse "/foo/"
|
430
|
+
result.must_equal s(:lit, /foo/)
|
431
|
+
end
|
432
|
+
|
433
|
+
it "works for regex literals with escaped right bracket" do
|
434
|
+
result = parser.parse '/\\)/'
|
435
|
+
result.must_equal s(:lit, /\)/)
|
436
|
+
end
|
437
|
+
|
438
|
+
it "works for regex literals with escape sequences" do
|
439
|
+
result = parser.parse '/\\)\\n\\\\/'
|
440
|
+
result.must_equal s(:lit, /\)\n\\/)
|
441
|
+
end
|
442
|
+
|
443
|
+
it "works for symbols created by prefixing a simple string with :" do
|
444
|
+
result = parser.parse ':"foo"'
|
445
|
+
result.must_equal s(:lit, :foo)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
describe "for the __FILE__ keyword" do
|
450
|
+
it "creates a string sexp with value '(string)'" do
|
451
|
+
result = parser.parse "__FILE__"
|
452
|
+
result.must_equal s(:str, "(string)")
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
describe "for constant references" do
|
457
|
+
it "works when explicitely starting from the root namespace" do
|
458
|
+
result = parser.parse "::Foo"
|
459
|
+
result.must_equal s(:colon3, :Foo)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
describe "for variable references" do
|
464
|
+
it "works for global variables" do
|
465
|
+
result = parser.parse "$foo"
|
466
|
+
result.must_equal s(:gvar, :$foo)
|
467
|
+
end
|
468
|
+
|
469
|
+
it "works for regexp match references" do
|
470
|
+
result = parser.parse "$1"
|
471
|
+
result.must_equal s(:nth_ref, 1)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
describe "for single assignment" do
|
476
|
+
it "works when assigning to an instance variable" do
|
477
|
+
result = parser.parse "@foo = bar"
|
478
|
+
result.must_equal s(:iasgn,
|
479
|
+
:@foo,
|
480
|
+
s(:call, nil, :bar, s(:arglist)))
|
481
|
+
end
|
482
|
+
|
483
|
+
it "works when assigning to a constant" do
|
484
|
+
result = parser.parse "FOO = bar"
|
485
|
+
result.must_equal s(:cdecl,
|
486
|
+
:FOO,
|
487
|
+
s(:call, nil, :bar, s(:arglist)))
|
488
|
+
end
|
489
|
+
|
490
|
+
it "works when assigning to a collection element" do
|
491
|
+
result = parser.parse "foo[bar] = baz"
|
492
|
+
result.must_equal s(:attrasgn,
|
493
|
+
s(:call, nil, :foo, s(:arglist)),
|
494
|
+
:[]=,
|
495
|
+
s(:arglist,
|
496
|
+
s(:call, nil, :bar, s(:arglist)),
|
497
|
+
s(:call, nil, :baz, s(:arglist))))
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
describe "for operator assignment" do
|
502
|
+
it "works with +=" do
|
503
|
+
result = parser.parse "foo += bar"
|
504
|
+
result.must_equal s(:lasgn,
|
505
|
+
:foo,
|
506
|
+
s(:call,
|
507
|
+
s(:lvar, :foo),
|
508
|
+
:+,
|
509
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist)))))
|
510
|
+
end
|
511
|
+
|
512
|
+
it "works with -=" do
|
513
|
+
result = parser.parse "foo -= bar"
|
514
|
+
result.must_equal s(:lasgn,
|
515
|
+
:foo,
|
516
|
+
s(:call,
|
517
|
+
s(:lvar, :foo),
|
518
|
+
:-,
|
519
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist)))))
|
520
|
+
end
|
521
|
+
|
522
|
+
it "works when assigning to an instance variable" do
|
523
|
+
result = parser.parse "@foo += bar"
|
524
|
+
result.must_equal s(:iasgn,
|
525
|
+
:@foo,
|
526
|
+
s(:call,
|
527
|
+
s(:ivar, :@foo),
|
528
|
+
:+,
|
529
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist)))))
|
530
|
+
end
|
531
|
+
|
532
|
+
it "works when assigning to a collection element" do
|
533
|
+
result = parser.parse "foo[bar] += baz"
|
534
|
+
result.must_equal s(:op_asgn1,
|
535
|
+
s(:call, nil, :foo, s(:arglist)),
|
536
|
+
s(:arglist, s(:call, nil, :bar, s(:arglist))),
|
537
|
+
:+,
|
538
|
+
s(:call, nil, :baz, s(:arglist)))
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
describe "for multiple assignment" do
|
543
|
+
it "works the same number of items on each side" do
|
544
|
+
result = parser.parse "foo, bar = baz, qux"
|
545
|
+
result.must_equal s(:masgn,
|
546
|
+
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
547
|
+
s(:array,
|
548
|
+
s(:call, nil, :baz, s(:arglist)),
|
549
|
+
s(:call, nil, :qux, s(:arglist))))
|
550
|
+
end
|
551
|
+
|
552
|
+
it "works with a single item on the right-hand side" do
|
553
|
+
result = parser.parse "foo, bar = baz"
|
554
|
+
result.must_equal s(:masgn,
|
555
|
+
s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
|
556
|
+
s(:to_ary,
|
557
|
+
s(:call, nil, :baz, s(:arglist))))
|
558
|
+
end
|
559
|
+
|
560
|
+
it "works with left-hand splat" do
|
561
|
+
result = parser.parse "foo, *bar = baz, qux"
|
562
|
+
result.must_equal s(:masgn,
|
563
|
+
s(:array, s(:lasgn, :foo), s(:splat, s(:lasgn, :bar))),
|
564
|
+
s(:array,
|
565
|
+
s(:call, nil, :baz, s(:arglist)),
|
566
|
+
s(:call, nil, :qux, s(:arglist))))
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
describe "for operators" do
|
571
|
+
it "converts :&& to :and" do
|
572
|
+
result = parser.parse "foo && bar"
|
573
|
+
result.must_equal s(:and,
|
574
|
+
s(:call, nil, :foo, s(:arglist)),
|
575
|
+
s(:call, nil, :bar, s(:arglist)))
|
576
|
+
end
|
577
|
+
|
578
|
+
it "converts :|| to :or" do
|
579
|
+
result = parser.parse "foo || bar"
|
580
|
+
result.must_equal s(:or,
|
581
|
+
s(:call, nil, :foo, s(:arglist)),
|
582
|
+
s(:call, nil, :bar, s(:arglist)))
|
583
|
+
end
|
584
|
+
|
585
|
+
it "handles unary minus with a number literal" do
|
586
|
+
result = parser.parse "-1"
|
587
|
+
result.must_equal s(:lit, -1)
|
588
|
+
end
|
589
|
+
|
590
|
+
it "handles unary minus with a non-literal" do
|
591
|
+
result = parser.parse "-foo"
|
592
|
+
result.must_equal s(:call,
|
593
|
+
s(:call, nil, :foo, s(:arglist)),
|
594
|
+
:-@,
|
595
|
+
s(:arglist))
|
596
|
+
end
|
597
|
+
|
598
|
+
it "handles the range operator with positive number literals" do
|
599
|
+
result = parser.parse "1..2"
|
600
|
+
result.must_equal s(:lit, 1..2)
|
601
|
+
end
|
602
|
+
|
603
|
+
it "handles the range operator with negative number literals" do
|
604
|
+
result = parser.parse "-1..-2"
|
605
|
+
result.must_equal s(:lit, -1..-2)
|
606
|
+
end
|
607
|
+
|
608
|
+
it "handles the range operator with string literals" do
|
609
|
+
result = parser.parse "'a'..'z'"
|
610
|
+
result.must_equal s(:dot2,
|
611
|
+
s(:str, "a"),
|
612
|
+
s(:str, "z"))
|
613
|
+
end
|
614
|
+
|
615
|
+
it "handles the range operator with non-literals" do
|
616
|
+
result = parser.parse "foo..bar"
|
617
|
+
result.must_equal s(:dot2,
|
618
|
+
s(:call, nil, :foo, s(:arglist)),
|
619
|
+
s(:call, nil, :bar, s(:arglist)))
|
620
|
+
end
|
621
|
+
end
|
622
|
+
end
|
623
|
+
end
|