ripper_ruby_parser 1.6.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
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