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.
@@ -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