ripper_ruby_parser 1.7.2 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -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/assignment.rb +2 -2
  6. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +47 -53
  7. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
  8. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +34 -1
  9. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +1 -1
  10. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +9 -5
  11. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +17 -15
  12. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +3 -3
  13. data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +24 -28
  14. data/lib/ripper_ruby_parser/sexp_processor.rb +5 -18
  15. data/lib/ripper_ruby_parser/unescape.rb +63 -22
  16. data/lib/ripper_ruby_parser/version.rb +1 -1
  17. metadata +140 -79
  18. data/Rakefile +0 -33
  19. data/test/end_to_end/comments_test.rb +0 -59
  20. data/test/end_to_end/comparison_test.rb +0 -104
  21. data/test/end_to_end/lib_comparison_test.rb +0 -18
  22. data/test/end_to_end/line_numbering_test.rb +0 -31
  23. data/test/end_to_end/samples_comparison_test.rb +0 -13
  24. data/test/end_to_end/test_comparison_test.rb +0 -18
  25. data/test/pt_testcase/pt_test.rb +0 -44
  26. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -200
  27. data/test/ripper_ruby_parser/parser_test.rb +0 -576
  28. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -597
  29. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -717
  30. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
  31. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -165
  32. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
  33. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -237
  34. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -429
  35. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -405
  36. data/test/ripper_ruby_parser/sexp_handlers/string_literals_test.rb +0 -973
  37. data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -327
  38. data/test/ripper_ruby_parser/version_test.rb +0 -7
  39. data/test/samples/assignment.rb +0 -22
  40. data/test/samples/comments.rb +0 -13
  41. data/test/samples/conditionals.rb +0 -23
  42. data/test/samples/lambdas.rb +0 -5
  43. data/test/samples/loops.rb +0 -36
  44. data/test/samples/misc.rb +0 -285
  45. data/test/samples/number.rb +0 -9
  46. data/test/samples/operators.rb +0 -18
  47. data/test/samples/strings.rb +0 -147
  48. 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