ripper_ruby_parser 1.7.2 → 1.8.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +4 -4
  4. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +24 -12
  5. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +33 -54
  6. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
  7. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +34 -1
  8. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +1 -1
  9. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +12 -15
  10. data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +21 -15
  11. data/lib/ripper_ruby_parser/sexp_processor.rb +4 -17
  12. data/lib/ripper_ruby_parser/unescape.rb +36 -12
  13. data/lib/ripper_ruby_parser/version.rb +1 -1
  14. metadata +110 -78
  15. data/Rakefile +0 -33
  16. data/test/end_to_end/comments_test.rb +0 -59
  17. data/test/end_to_end/comparison_test.rb +0 -104
  18. data/test/end_to_end/lib_comparison_test.rb +0 -18
  19. data/test/end_to_end/line_numbering_test.rb +0 -31
  20. data/test/end_to_end/samples_comparison_test.rb +0 -13
  21. data/test/end_to_end/test_comparison_test.rb +0 -18
  22. data/test/pt_testcase/pt_test.rb +0 -44
  23. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -200
  24. data/test/ripper_ruby_parser/parser_test.rb +0 -576
  25. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -597
  26. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -717
  27. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
  28. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -165
  29. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
  30. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -237
  31. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -429
  32. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -405
  33. data/test/ripper_ruby_parser/sexp_handlers/string_literals_test.rb +0 -973
  34. data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -327
  35. data/test/ripper_ruby_parser/version_test.rb +0 -7
  36. data/test/samples/assignment.rb +0 -22
  37. data/test/samples/comments.rb +0 -13
  38. data/test/samples/conditionals.rb +0 -23
  39. data/test/samples/lambdas.rb +0 -5
  40. data/test/samples/loops.rb +0 -36
  41. data/test/samples/misc.rb +0 -285
  42. data/test/samples/number.rb +0 -9
  43. data/test/samples/operators.rb +0 -18
  44. data/test/samples/strings.rb +0 -147
  45. data/test/test_helper.rb +0 -111
@@ -1,576 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require File.expand_path("../test_helper.rb", File.dirname(__FILE__))
4
-
5
- describe RipperRubyParser::Parser do
6
- let(:parser) { RipperRubyParser::Parser.new }
7
- describe "#parse" do
8
- it "returns an s-expression" do
9
- result = parser.parse "foo"
10
- _(result).must_be_instance_of Sexp
11
- end
12
-
13
- describe "for an empty program" do
14
- it "returns nil" do
15
- _("").must_be_parsed_as nil
16
- end
17
- end
18
-
19
- describe "for a class declaration" do
20
- it "works with a namespaced class name" do
21
- _("class Foo::Bar; end")
22
- .must_be_parsed_as s(:class,
23
- s(:colon2, s(:const, :Foo), :Bar),
24
- nil)
25
- end
26
-
27
- it "works for singleton classes" do
28
- _("class << self; end").must_be_parsed_as s(:sclass, s(:self))
29
- end
30
- end
31
-
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
-
38
- it "works with a namespaced module name" do
39
- _("module Foo::Bar; end")
40
- .must_be_parsed_as s(:module,
41
- s(:colon2, s(:const, :Foo), :Bar))
42
- end
43
- end
44
-
45
- describe "for empty parentheses" do
46
- it "works with lone ()" do
47
- _("()").must_be_parsed_as s(:nil)
48
- end
49
- end
50
-
51
- describe "for a begin..end block" do
52
- it "works with no statements" do
53
- _("begin; end")
54
- .must_be_parsed_as s(:nil)
55
- end
56
-
57
- it "works with one statement" do
58
- _("begin; foo; end")
59
- .must_be_parsed_as s(:call, nil, :foo)
60
- end
61
-
62
- it "works with multiple statements" do
63
- _("begin; foo; bar; end")
64
- .must_be_parsed_as s(:block,
65
- s(:call, nil, :foo),
66
- s(:call, nil, :bar))
67
- end
68
- end
69
-
70
- describe "for arguments" do
71
- it "works for a simple case with splat" do
72
- _("foo *bar")
73
- .must_be_parsed_as s(:call,
74
- nil,
75
- :foo,
76
- s(:splat, s(:call, nil, :bar)))
77
- end
78
-
79
- it "works for a multi-argument case with splat" do
80
- _("foo bar, *baz")
81
- .must_be_parsed_as s(:call,
82
- nil,
83
- :foo,
84
- s(:call, nil, :bar),
85
- s(:splat, s(:call, nil, :baz)))
86
- end
87
-
88
- it "works for a simple case passing a block" do
89
- _("foo &bar")
90
- .must_be_parsed_as s(:call, nil, :foo,
91
- s(:block_pass,
92
- s(:call, nil, :bar)))
93
- end
94
-
95
- it "works for a bare hash" do
96
- _("foo bar => baz")
97
- .must_be_parsed_as s(:call, nil, :foo,
98
- s(:hash,
99
- s(:call, nil, :bar),
100
- s(:call, nil, :baz)))
101
- end
102
- end
103
-
104
- describe "for the __ENCODING__ keyword" do
105
- it "evaluates to the equivalent of Encoding::UTF_8" do
106
- _("__ENCODING__")
107
- .must_be_parsed_as s(:colon2, s(:const, :Encoding), :UTF_8)
108
- end
109
- end
110
-
111
- describe "for the __FILE__ keyword" do
112
- describe "when not passing a file name" do
113
- it "creates a string sexp with value '(string)'" do
114
- _("__FILE__")
115
- .must_be_parsed_as s(:str, "(string)")
116
- end
117
- end
118
-
119
- describe "when passing a file name" do
120
- it "creates a string sexp with the file name" do
121
- result = parser.parse "__FILE__", "foo"
122
- _(result).must_equal s(:str, "foo")
123
- end
124
- end
125
- end
126
-
127
- describe "for the __LINE__ keyword" do
128
- it "creates a literal sexp with value of the line number" do
129
- _("__LINE__")
130
- .must_be_parsed_as s(:lit, 1)
131
- _("\n__LINE__")
132
- .must_be_parsed_as s(:lit, 2)
133
- end
134
- end
135
-
136
- describe "for the END keyword" do
137
- it "converts to a :postexe iterator" do
138
- _("END { foo }")
139
- .must_be_parsed_as s(:iter, s(:postexe), 0, s(:call, nil, :foo))
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
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
162
- end
163
-
164
- describe "for the BEGIN keyword" do
165
- it "converts to a :preexe iterator" do
166
- _("BEGIN { foo }")
167
- .must_be_parsed_as s(:iter, s(:preexe), 0, s(:call, nil, :foo))
168
- end
169
-
170
- it "works with an empty block" do
171
- _("BEGIN { }")
172
- .must_be_parsed_as s(:iter, s(:preexe), 0)
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
191
- end
192
-
193
- describe "for constant lookups" do
194
- it "works when explicitely starting from the root namespace" do
195
- _("::Foo")
196
- .must_be_parsed_as s(:colon3, :Foo)
197
- end
198
-
199
- it "works with a three-level constant lookup" do
200
- _("Foo::Bar::Baz")
201
- .must_be_parsed_as s(:colon2,
202
- s(:colon2, s(:const, :Foo), :Bar),
203
- :Baz)
204
- end
205
-
206
- it "works looking up a constant in a non-constant" do
207
- _("foo::Bar").must_be_parsed_as s(:colon2,
208
- s(:call, nil, :foo),
209
- :Bar)
210
- end
211
- end
212
-
213
- describe "for variable references" do
214
- it "works for self" do
215
- _("self")
216
- .must_be_parsed_as s(:self)
217
- end
218
-
219
- it "works for instance variables" do
220
- _("@foo")
221
- .must_be_parsed_as s(:ivar, :@foo)
222
- end
223
-
224
- it "works for global variables" do
225
- _("$foo")
226
- .must_be_parsed_as s(:gvar, :$foo)
227
- end
228
-
229
- it "works for regexp match references" do
230
- _("$1")
231
- .must_be_parsed_as s(:nth_ref, 1)
232
- end
233
-
234
- specify { _("$'").must_be_parsed_as s(:back_ref, :"'") }
235
- specify { _("$&").must_be_parsed_as s(:back_ref, :"&") }
236
-
237
- it "works for class variables" do
238
- _("@@foo")
239
- .must_be_parsed_as s(:cvar, :@@foo)
240
- end
241
- end
242
-
243
- describe "for expressions" do
244
- it "handles assignment inside binary operator expressions" do
245
- _("foo + (bar = baz)")
246
- .must_be_parsed_as s(:call,
247
- s(:call, nil, :foo),
248
- :+,
249
- s(:lasgn,
250
- :bar,
251
- s(:call, nil, :baz)))
252
- end
253
-
254
- it "handles assignment inside unary operator expressions" do
255
- _("+(foo = bar)")
256
- .must_be_parsed_as s(:call,
257
- s(:lasgn, :foo, s(:call, nil, :bar)),
258
- :+@)
259
- end
260
- end
261
-
262
- # Note: differences in the handling of comments are not caught by Sexp's
263
- # implementation of equality.
264
- describe "for comments" do
265
- it "handles method comments" do
266
- result = parser.parse "# Foo\ndef foo; end"
267
- _(result).must_equal s(:defn,
268
- :foo,
269
- s(:args), s(:nil))
270
- _(result.comments).must_equal "# Foo\n"
271
- end
272
-
273
- it "handles comments for methods with explicit receiver" do
274
- result = parser.parse "# Foo\ndef foo.bar; end"
275
- _(result).must_equal s(:defs,
276
- s(:call, nil, :foo),
277
- :bar,
278
- s(:args),
279
- s(:nil))
280
- _(result.comments).must_equal "# Foo\n"
281
- end
282
-
283
- it "matches comments to the correct entity" do
284
- result = parser.parse "# Foo\nclass Foo\n# Bar\ndef bar\nend\nend"
285
- _(result).must_equal s(:class, :Foo, nil,
286
- s(:defn, :bar,
287
- s(:args), s(:nil)))
288
- _(result.comments).must_equal "# Foo\n"
289
- defn = result[3]
290
- _(defn.sexp_type).must_equal :defn
291
- _(defn.comments).must_equal "# Bar\n"
292
- end
293
-
294
- it "combines multi-line comments" do
295
- result = parser.parse "# Foo\n# Bar\ndef foo; end"
296
- _(result).must_equal s(:defn,
297
- :foo,
298
- s(:args), s(:nil))
299
- _(result.comments).must_equal "# Foo\n# Bar\n"
300
- end
301
-
302
- it "drops comments inside method bodies" do
303
- result = parser.parse <<-RUBY
304
- # Foo
305
- class Foo
306
- # foo
307
- def foo
308
- bar # this is dropped
309
- end
310
-
311
- # bar
312
- def bar
313
- baz
314
- end
315
- end
316
- RUBY
317
- _(result).must_equal s(:class,
318
- :Foo,
319
- nil,
320
- s(:defn, :foo, s(:args), s(:call, nil, :bar)),
321
- s(:defn, :bar, s(:args), s(:call, nil, :baz)))
322
- _(result.comments).must_equal "# Foo\n"
323
- _(result[3].comments).must_equal "# foo\n"
324
- _(result[4].comments).must_equal "# bar\n"
325
- end
326
-
327
- it "handles the use of symbols that are keywords" do
328
- result = parser.parse "# Foo\ndef bar\n:class\nend"
329
- _(result).must_equal s(:defn,
330
- :bar,
331
- s(:args),
332
- s(:lit, :class))
333
- _(result.comments).must_equal "# Foo\n"
334
- end
335
-
336
- it "handles use of singleton class inside methods" do
337
- result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
338
- _(result).must_equal s(:defn,
339
- :bar,
340
- s(:args),
341
- s(:sclass, s(:self),
342
- s(:call, nil, :baz)))
343
- _(result.comments).must_equal "# Foo\n"
344
- end
345
-
346
- # TODO: Prefer assigning comment to the BEGIN instead
347
- it "assigns comments on BEGIN blocks to the following item" do
348
- result = parser.parse "# Bar\nBEGIN { }\n# Foo\ndef foo; end"
349
- _(result).must_equal s(:block,
350
- s(:iter, s(:preexe), 0),
351
- s(:defn, :foo, s(:args), s(:nil)))
352
- _(result[2].comments).must_equal "# Bar\n# Foo\n"
353
- end
354
-
355
- it "assigns comments on multiple BEGIN blocks to the following item" do
356
- result = parser.parse "# Bar\nBEGIN { }\n# Baz\nBEGIN { }\n# Foo\ndef foo; end"
357
- _(result).must_equal s(:block,
358
- s(:iter, s(:preexe), 0),
359
- s(:iter, s(:preexe), 0),
360
- s(:defn, :foo, s(:args), s(:nil)))
361
- _(result[3].comments).must_equal "# Bar\n# Baz\n# Foo\n"
362
- end
363
-
364
- it "assigns comments on BEGIN blocks to the first following item" do
365
- result = parser.parse "# Bar\nBEGIN { }\n# Foo\nclass Bar\n# foo\ndef foo; end\nend"
366
- _(result).must_equal s(:block,
367
- s(:iter, s(:preexe), 0),
368
- s(:class, :Bar, nil,
369
- s(:defn, :foo, s(:args), s(:nil))))
370
- _(result[2].comments).must_equal "# Bar\n# Foo\n"
371
- _(result[2][3].comments).must_equal "# foo\n"
372
- end
373
- end
374
-
375
- # Note: differences in the handling of line numbers are not caught by
376
- # Sexp's implementation of equality.
377
- describe "assigning line numbers" do
378
- it "works for a plain method call" do
379
- result = parser.parse "foo"
380
- _(result.line).must_equal 1
381
- end
382
-
383
- it "works for a method call with parentheses" do
384
- result = parser.parse "foo()"
385
- _(result.line).must_equal 1
386
- end
387
-
388
- it "works for a method call with receiver" do
389
- result = parser.parse "foo.bar"
390
- _(result.line).must_equal 1
391
- end
392
-
393
- it "works for a method call with receiver and arguments" do
394
- result = parser.parse "foo.bar baz"
395
- _(result.line).must_equal 1
396
- end
397
-
398
- it "works for a method call with arguments" do
399
- result = parser.parse "foo bar"
400
- _(result.line).must_equal 1
401
- end
402
-
403
- it "works for a block with two lines" do
404
- result = parser.parse "foo\nbar\n"
405
- _(result.sexp_type).must_equal :block
406
- _(result[1].line).must_equal 1
407
- _(result[2].line).must_equal 2
408
- _(result.line).must_equal 1
409
- end
410
-
411
- it "works for a constant reference" do
412
- result = parser.parse "Foo"
413
- _(result.line).must_equal 1
414
- end
415
-
416
- it "works for an instance variable" do
417
- result = parser.parse "@foo"
418
- _(result.line).must_equal 1
419
- end
420
-
421
- it "works for a global variable" do
422
- result = parser.parse "$foo"
423
- _(result.line).must_equal 1
424
- end
425
-
426
- it "works for a class variable" do
427
- result = parser.parse "@@foo"
428
- _(result.line).must_equal 1
429
- end
430
-
431
- it "works for a local variable" do
432
- _("foo = bar\nfoo\n")
433
- .must_be_parsed_as s(:block,
434
- s(:lasgn, :foo, s(:call, nil, :bar).line(1)).line(1),
435
- s(:lvar, :foo).line(2)).line(1),
436
- with_line_numbers: true
437
- end
438
-
439
- it "works for an integer literal" do
440
- result = parser.parse "42"
441
- _(result.line).must_equal 1
442
- end
443
-
444
- it "works for a float literal" do
445
- result = parser.parse "3.14"
446
- _(result.line).must_equal 1
447
- end
448
-
449
- it "works for a range literal" do
450
- result = parser.parse "0..4"
451
- _(result.line).must_equal 1
452
- end
453
-
454
- it "works for an exclusive range literal" do
455
- result = parser.parse "0...4"
456
- _(result.line).must_equal 1
457
- end
458
-
459
- it "works for a symbol literal" do
460
- result = parser.parse ":foo"
461
- _(result.line).must_equal 1
462
- end
463
-
464
- it "works for a keyword-like symbol literal" do
465
- result = parser.parse ":and"
466
- _(result.line).must_equal 1
467
- end
468
-
469
- it "works for a string literal" do
470
- result = parser.parse '"foo"'
471
- _(result.line).must_equal 1
472
- end
473
-
474
- it "works for a backtick string literal" do
475
- result = parser.parse "`foo`"
476
- _(result.line).must_equal 1
477
- end
478
-
479
- it "works for a plain regexp literal" do
480
- result = parser.parse "/foo/"
481
- _(result.line).must_equal 1
482
- end
483
-
484
- it "works for a regular expression back reference" do
485
- result = parser.parse "$1"
486
- _(result.line).must_equal 1
487
- end
488
-
489
- it "works for self" do
490
- result = parser.parse "self"
491
- _(result.line).must_equal 1
492
- end
493
-
494
- it "works for __FILE__" do
495
- result = parser.parse "__FILE__"
496
- _(result.line).must_equal 1
497
- end
498
-
499
- it "works for nil" do
500
- result = parser.parse "nil"
501
- _(result.line).must_equal 1
502
- end
503
-
504
- it "works for a symbol literal" do
505
- result = parser.parse ":foo"
506
- _(result.line).must_equal 1
507
- end
508
-
509
- it "works for a class definition" do
510
- result = parser.parse "class Foo; end"
511
- _(result.line).must_equal 1
512
- end
513
-
514
- it "works for a module definition" do
515
- result = parser.parse "module Foo; end"
516
- _(result.line).must_equal 1
517
- end
518
-
519
- it "works for a method definition" do
520
- result = parser.parse "def foo; end"
521
- _(result.line).must_equal 1
522
- end
523
-
524
- it "works for assignment of the empty hash" do
525
- result = parser.parse "foo = {}"
526
- _(result.line).must_equal 1
527
- end
528
-
529
- it "works for multiple assignment of empty hashes" do
530
- result = parser.parse "foo, bar = {}, {}"
531
- _(result.line).must_equal 1
532
- end
533
-
534
- it "assigns line numbers to nested sexps without their own line numbers" do
535
- _("foo(bar) do\nnext baz\nend\n")
536
- .must_be_parsed_as s(:iter,
537
- s(:call, nil, :foo, s(:call, nil, :bar).line(1)).line(1),
538
- 0,
539
- s(:next, s(:call, nil, :baz).line(2)).line(2)).line(1),
540
- with_line_numbers: true
541
- end
542
-
543
- describe "when a line number is passed" do
544
- it "shifts all line numbers as appropriate" do
545
- result = parser.parse "foo\nbar\n", "(string)", 3
546
- _(result).must_equal s(:block,
547
- s(:call, nil, :foo),
548
- s(:call, nil, :bar))
549
- _(result.line).must_equal 3
550
- _(result[1].line).must_equal 3
551
- _(result[2].line).must_equal 4
552
- end
553
- end
554
- end
555
- end
556
-
557
- describe "#trickle_up_line_numbers" do
558
- it "works through several nested levels" do
559
- inner = s(:foo)
560
- outer = s(:bar, s(:baz, s(:qux, inner)))
561
- outer.line = 42
562
- parser.send :trickle_down_line_numbers, outer
563
- _(inner.line).must_equal 42
564
- end
565
- end
566
-
567
- describe "#trickle_down_line_numbers" do
568
- it "works through several nested levels" do
569
- inner = s(:foo)
570
- inner.line = 42
571
- outer = s(:bar, s(:baz, s(:qux, inner)))
572
- parser.send :trickle_up_line_numbers, outer
573
- _(outer.line).must_equal 42
574
- end
575
- end
576
- end