ripper_ruby_parser 1.6.0 → 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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -0
  3. data/README.md +8 -25
  4. data/lib/ripper_ruby_parser.rb +2 -2
  5. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +54 -23
  6. data/lib/ripper_ruby_parser/parser.rb +3 -3
  7. data/lib/ripper_ruby_parser/sexp_handlers.rb +11 -9
  8. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +10 -11
  9. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +48 -63
  10. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
  11. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +35 -2
  12. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
  13. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +4 -2
  14. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +1 -1
  15. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +24 -24
  16. data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +266 -0
  17. data/lib/ripper_ruby_parser/sexp_processor.rb +47 -78
  18. data/lib/ripper_ruby_parser/unescape.rb +79 -50
  19. data/lib/ripper_ruby_parser/version.rb +1 -1
  20. metadata +115 -78
  21. data/Rakefile +0 -33
  22. data/test/end_to_end/comments_test.rb +0 -59
  23. data/test/end_to_end/comparison_test.rb +0 -104
  24. data/test/end_to_end/lib_comparison_test.rb +0 -29
  25. data/test/end_to_end/line_numbering_test.rb +0 -64
  26. data/test/end_to_end/samples_comparison_test.rb +0 -13
  27. data/test/end_to_end/test_comparison_test.rb +0 -32
  28. data/test/pt_testcase/pt_test.rb +0 -44
  29. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -190
  30. data/test/ripper_ruby_parser/parser_test.rb +0 -469
  31. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -649
  32. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -661
  33. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
  34. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -1117
  35. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
  36. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -267
  37. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -427
  38. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -399
  39. data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -303
  40. data/test/ripper_ruby_parser/version_test.rb +0 -7
  41. data/test/samples/assignment.rb +0 -17
  42. data/test/samples/comments.rb +0 -13
  43. data/test/samples/conditionals.rb +0 -23
  44. data/test/samples/loops.rb +0 -36
  45. data/test/samples/misc.rb +0 -278
  46. data/test/samples/number.rb +0 -7
  47. data/test/samples/operators.rb +0 -18
  48. data/test/samples/strings.rb +0 -140
  49. data/test/test_helper.rb +0 -79
@@ -1,469 +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
- end
147
-
148
- describe 'for the BEGIN keyword' do
149
- it 'converts to a :preexe iterator' do
150
- 'BEGIN { foo }'.
151
- must_be_parsed_as s(:iter, s(:preexe), 0, s(:call, nil, :foo))
152
- end
153
-
154
- it 'works with an empty block' do
155
- 'BEGIN { }'.
156
- must_be_parsed_as s(:iter, s(:preexe), 0)
157
- end
158
- end
159
-
160
- describe 'for constant lookups' do
161
- it 'works when explicitely starting from the root namespace' do
162
- '::Foo'.
163
- must_be_parsed_as s(:colon3, :Foo)
164
- end
165
-
166
- it 'works with a three-level constant lookup' do
167
- 'Foo::Bar::Baz'.
168
- must_be_parsed_as s(:colon2,
169
- s(:colon2, s(:const, :Foo), :Bar),
170
- :Baz)
171
- end
172
-
173
- it 'works looking up a constant in a non-constant' do
174
- 'foo::Bar'.must_be_parsed_as s(:colon2,
175
- s(:call, nil, :foo),
176
- :Bar)
177
- end
178
- end
179
-
180
- describe 'for variable references' do
181
- it 'works for self' do
182
- 'self'.
183
- must_be_parsed_as s(:self)
184
- end
185
-
186
- it 'works for instance variables' do
187
- '@foo'.
188
- must_be_parsed_as s(:ivar, :@foo)
189
- end
190
-
191
- it 'works for global variables' do
192
- '$foo'.
193
- must_be_parsed_as s(:gvar, :$foo)
194
- end
195
-
196
- it 'works for regexp match references' do
197
- '$1'.
198
- must_be_parsed_as s(:nth_ref, 1)
199
- end
200
-
201
- specify { "$'".must_be_parsed_as s(:back_ref, :"'") }
202
- specify { '$&'.must_be_parsed_as s(:back_ref, :"&") }
203
-
204
- it 'works for class variables' do
205
- '@@foo'.
206
- must_be_parsed_as s(:cvar, :@@foo)
207
- end
208
- end
209
-
210
- describe 'for expressions' do
211
- it 'handles assignment inside binary operator expressions' do
212
- 'foo + (bar = baz)'.
213
- must_be_parsed_as s(:call,
214
- s(:call, nil, :foo),
215
- :+,
216
- s(:lasgn,
217
- :bar,
218
- s(:call, nil, :baz)))
219
- end
220
-
221
- it 'handles assignment inside unary operator expressions' do
222
- '+(foo = bar)'.
223
- must_be_parsed_as s(:call,
224
- s(:lasgn, :foo, s(:call, nil, :bar)),
225
- :+@)
226
- end
227
- end
228
-
229
- # Note: differences in the handling of comments are not caught by Sexp's
230
- # implementation of equality.
231
- describe 'for comments' do
232
- it 'handles method comments' do
233
- result = parser.parse "# Foo\ndef foo; end"
234
- result.must_equal s(:defn,
235
- :foo,
236
- s(:args), s(:nil))
237
- result.comments.must_equal "# Foo\n"
238
- end
239
-
240
- it 'handles comments for methods with explicit receiver' do
241
- result = parser.parse "# Foo\ndef foo.bar; end"
242
- result.must_equal s(:defs,
243
- s(:call, nil, :foo),
244
- :bar,
245
- s(:args),
246
- s(:nil))
247
- result.comments.must_equal "# Foo\n"
248
- end
249
-
250
- it 'matches comments to the correct entity' do
251
- result = parser.parse "# Foo\nclass Foo\n# Bar\ndef bar\nend\nend"
252
- result.must_equal s(:class, :Foo, nil,
253
- s(:defn, :bar,
254
- s(:args), s(:nil)))
255
- result.comments.must_equal "# Foo\n"
256
- defn = result[3]
257
- defn.sexp_type.must_equal :defn
258
- defn.comments.must_equal "# Bar\n"
259
- end
260
-
261
- it 'combines multi-line comments' do
262
- result = parser.parse "# Foo\n# Bar\ndef foo; end"
263
- result.must_equal s(:defn,
264
- :foo,
265
- s(:args), s(:nil))
266
- result.comments.must_equal "# Foo\n# Bar\n"
267
- end
268
-
269
- it 'drops comments inside method bodies' do
270
- result = parser.parse <<-END
271
- # Foo
272
- class Foo
273
- # foo
274
- def foo
275
- bar # this is dropped
276
- end
277
-
278
- # bar
279
- def bar
280
- baz
281
- end
282
- end
283
- END
284
- result.must_equal s(:class,
285
- :Foo,
286
- nil,
287
- s(:defn, :foo, s(:args), s(:call, nil, :bar)),
288
- s(:defn, :bar, s(:args), s(:call, nil, :baz)))
289
- result.comments.must_equal "# Foo\n"
290
- result[3].comments.must_equal "# foo\n"
291
- result[4].comments.must_equal "# bar\n"
292
- end
293
-
294
- it 'handles use of singleton class inside methods' do
295
- result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
296
- result.must_equal s(:defn,
297
- :bar,
298
- s(:args),
299
- s(:sclass, s(:self),
300
- s(:call, nil, :baz)))
301
- result.comments.must_equal "# Foo\n"
302
- end
303
- end
304
-
305
- # Note: differences in the handling of line numbers are not caught by
306
- # Sexp's implementation of equality.
307
- describe 'assigning line numbers' do
308
- it 'works for a plain method call' do
309
- result = parser.parse 'foo'
310
- result.line.must_equal 1
311
- end
312
-
313
- it 'works for a method call with parentheses' do
314
- result = parser.parse 'foo()'
315
- result.line.must_equal 1
316
- end
317
-
318
- it 'works for a method call with receiver' do
319
- result = parser.parse 'foo.bar'
320
- result.line.must_equal 1
321
- end
322
-
323
- it 'works for a method call with receiver and arguments' do
324
- result = parser.parse 'foo.bar baz'
325
- result.line.must_equal 1
326
- end
327
-
328
- it 'works for a method call with arguments' do
329
- result = parser.parse 'foo bar'
330
- result.line.must_equal 1
331
- end
332
-
333
- it 'works for a block with two lines' do
334
- result = parser.parse "foo\nbar\n"
335
- result.sexp_type.must_equal :block
336
- result[1].line.must_equal 1
337
- result[2].line.must_equal 2
338
- result.line.must_equal 1
339
- end
340
-
341
- it 'works for a constant reference' do
342
- result = parser.parse 'Foo'
343
- result.line.must_equal 1
344
- end
345
-
346
- it 'works for an instance variable' do
347
- result = parser.parse '@foo'
348
- result.line.must_equal 1
349
- end
350
-
351
- it 'works for a global variable' do
352
- result = parser.parse '$foo'
353
- result.line.must_equal 1
354
- end
355
-
356
- it 'works for a class variable' do
357
- result = parser.parse '@@foo'
358
- result.line.must_equal 1
359
- end
360
-
361
- it 'works for a local variable' do
362
- result = parser.parse "foo = bar\nfoo\n"
363
- result.sexp_type.must_equal :block
364
- result[1].line.must_equal 1
365
- result[2].line.must_equal 2
366
- result.line.must_equal 1
367
- end
368
-
369
- it 'works for an integer literal' do
370
- result = parser.parse '42'
371
- result.line.must_equal 1
372
- end
373
-
374
- it 'works for a float literal' do
375
- result = parser.parse '3.14'
376
- result.line.must_equal 1
377
- end
378
-
379
- it 'works for a range literal' do
380
- result = parser.parse '0..4'
381
- result.line.must_equal 1
382
- end
383
-
384
- it 'works for an exclusive range literal' do
385
- result = parser.parse '0...4'
386
- result.line.must_equal 1
387
- end
388
-
389
- it 'works for a regular expression back reference' do
390
- result = parser.parse '$1'
391
- result.line.must_equal 1
392
- end
393
-
394
- it 'works for self' do
395
- result = parser.parse 'self'
396
- result.line.must_equal 1
397
- end
398
-
399
- it 'works for __FILE__' do
400
- result = parser.parse '__FILE__'
401
- result.line.must_equal 1
402
- end
403
-
404
- it 'works for nil' do
405
- result = parser.parse 'nil'
406
- result.line.must_equal 1
407
- end
408
-
409
- it 'works for a class definition' do
410
- result = parser.parse 'class Foo; end'
411
- result.line.must_equal 1
412
- end
413
-
414
- it 'works for a module definition' do
415
- result = parser.parse 'module Foo; end'
416
- result.line.must_equal 1
417
- end
418
-
419
- it 'works for a method definition' do
420
- result = parser.parse 'def foo; end'
421
- result.line.must_equal 1
422
- end
423
-
424
- it 'assigns line numbers to nested sexps without their own line numbers' do
425
- result = parser.parse "foo(bar) do\nnext baz\nend\n"
426
- result.must_equal s(:iter,
427
- s(:call, nil, :foo, s(:call, nil, :bar)),
428
- 0,
429
- s(:next, s(:call, nil, :baz)))
430
- arglist = result[1][3]
431
- block = result[3]
432
- nums = [arglist.line, block.line]
433
- nums.must_equal [1, 2]
434
- end
435
-
436
- describe 'when a line number is passed' do
437
- it 'shifts all line numbers as appropriate' do
438
- result = parser.parse "foo\nbar\n", '(string)', 3
439
- result.must_equal s(:block,
440
- s(:call, nil, :foo),
441
- s(:call, nil, :bar))
442
- result.line.must_equal 3
443
- result[1].line.must_equal 3
444
- result[2].line.must_equal 4
445
- end
446
- end
447
- end
448
- end
449
-
450
- describe '#trickle_up_line_numbers' do
451
- it 'works through several nested levels' do
452
- inner = s(:foo)
453
- outer = s(:bar, s(:baz, s(:qux, inner)))
454
- outer.line = 42
455
- parser.send :trickle_down_line_numbers, outer
456
- inner.line.must_equal 42
457
- end
458
- end
459
-
460
- describe '#trickle_down_line_numbers' do
461
- it 'works through several nested levels' do
462
- inner = s(:foo)
463
- inner.line = 42
464
- outer = s(:bar, s(:baz, s(:qux, inner)))
465
- parser.send :trickle_up_line_numbers, outer
466
- outer.line.must_equal 42
467
- end
468
- end
469
- end