ripper_ruby_parser 1.4.2 → 1.5.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -1
  3. data/README.md +41 -9
  4. data/Rakefile +2 -0
  5. data/lib/ripper_ruby_parser.rb +2 -0
  6. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +23 -45
  7. data/lib/ripper_ruby_parser/parser.rb +11 -1
  8. data/lib/ripper_ruby_parser/sexp_handlers.rb +2 -6
  9. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +49 -35
  10. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +78 -39
  11. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +16 -15
  12. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +19 -15
  13. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +138 -30
  14. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +10 -6
  15. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +59 -14
  16. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +56 -32
  17. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +20 -27
  18. data/lib/ripper_ruby_parser/sexp_processor.rb +40 -10
  19. data/lib/ripper_ruby_parser/syntax_error.rb +2 -0
  20. data/lib/ripper_ruby_parser/unescape.rb +32 -11
  21. data/lib/ripper_ruby_parser/version.rb +3 -1
  22. data/test/end_to_end/comments_test.rb +2 -0
  23. data/test/end_to_end/comparison_test.rb +2 -0
  24. data/test/end_to_end/lib_comparison_test.rb +2 -0
  25. data/test/end_to_end/line_numbering_test.rb +2 -0
  26. data/test/end_to_end/samples_comparison_test.rb +5 -29
  27. data/test/end_to_end/test_comparison_test.rb +2 -0
  28. data/test/pt_testcase/pt_test.rb +2 -0
  29. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +16 -2
  30. data/test/ripper_ruby_parser/parser_test.rb +17 -688
  31. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +459 -26
  32. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +152 -82
  33. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +91 -0
  34. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +331 -24
  35. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +88 -0
  36. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +58 -5
  37. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +392 -0
  38. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +174 -12
  39. data/test/ripper_ruby_parser/sexp_processor_test.rb +8 -18
  40. data/test/ripper_ruby_parser/version_test.rb +2 -0
  41. data/test/samples/comments.rb +13 -0
  42. data/test/samples/conditionals.rb +23 -0
  43. data/test/samples/loops.rb +36 -0
  44. data/test/samples/misc.rb +157 -5
  45. data/test/samples/number.rb +7 -0
  46. data/test/samples/strings.rb +39 -0
  47. data/test/test_helper.rb +22 -1
  48. metadata +18 -12
  49. data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +0 -29
  50. data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +0 -21
  51. data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +0 -48
@@ -1,17 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../../test_helper.rb', File.dirname(__FILE__))
2
4
 
3
5
  describe RipperRubyParser::Parser do
4
6
  describe '#parse' do
5
- describe 'for negated operators' do
6
- specify do
7
- 'foo !~ bar'.must_be_parsed_as s(:not,
8
- s(:call,
9
- s(:call, nil, :foo),
10
- :=~,
11
- s(:call, nil, :bar)))
12
- end
13
- end
14
-
15
7
  describe 'for boolean operators' do
16
8
  it 'handles :and' do
17
9
  'foo and bar'.
@@ -134,6 +126,60 @@ describe RipperRubyParser::Parser do
134
126
  s(:call, nil, :baz),
135
127
  s(:call, nil, :qux))))
136
128
  end
129
+
130
+ it 'handles :!=' do
131
+ 'foo != bar'.
132
+ must_be_parsed_as s(:call,
133
+ s(:call, nil, :foo),
134
+ :!=,
135
+ s(:call, nil, :bar))
136
+ end
137
+
138
+ it 'keeps :begin for the first argument of a binary operator' do
139
+ 'begin; bar; end + foo'.
140
+ must_be_parsed_as s(:call,
141
+ s(:begin, s(:call, nil, :bar)),
142
+ :+,
143
+ s(:call, nil, :foo))
144
+ end
145
+
146
+ it 'keeps :begin for the second argument of a binary operator' do
147
+ 'foo + begin; bar; end'.
148
+ must_be_parsed_as s(:call,
149
+ s(:call, nil, :foo),
150
+ :+,
151
+ s(:begin, s(:call, nil, :bar)))
152
+ end
153
+
154
+ it 'does not keep :begin for the first argument of a boolean operator' do
155
+ 'begin; bar; end and foo'.
156
+ must_be_parsed_as s(:and,
157
+ s(:call, nil, :bar),
158
+ s(:call, nil, :foo))
159
+ end
160
+
161
+ it 'keeps :begin for the second argument of a boolean operator' do
162
+ 'foo and begin; bar; end'.
163
+ must_be_parsed_as s(:and,
164
+ s(:call, nil, :foo),
165
+ s(:begin, s(:call, nil, :bar)))
166
+ end
167
+
168
+ it 'does not keep :begin for the first argument of a shift operator' do
169
+ 'begin; bar; end << foo'.
170
+ must_be_parsed_as s(:call,
171
+ s(:call, nil, :bar),
172
+ :<<,
173
+ s(:call, nil, :foo))
174
+ end
175
+
176
+ it 'does not keep :begin for the second argument of a shift operator' do
177
+ 'foo >> begin; bar; end'.
178
+ must_be_parsed_as s(:call,
179
+ s(:call, nil, :foo),
180
+ :>>,
181
+ s(:call, nil, :bar))
182
+ end
137
183
  end
138
184
 
139
185
  describe 'for the range operator' do
@@ -161,6 +207,20 @@ describe RipperRubyParser::Parser do
161
207
  s(:str, 'z'))
162
208
  end
163
209
 
210
+ it 'handles non-literal begin' do
211
+ 'foo..3'.
212
+ must_be_parsed_as s(:dot2,
213
+ s(:call, nil, :foo),
214
+ s(:lit, 3))
215
+ end
216
+
217
+ it 'handles non-literal end' do
218
+ '3..foo'.
219
+ must_be_parsed_as s(:dot2,
220
+ s(:lit, 3),
221
+ s(:call, nil, :foo))
222
+ end
223
+
164
224
  it 'handles non-literals' do
165
225
  'foo..bar'.
166
226
  must_be_parsed_as s(:dot2,
@@ -194,7 +254,21 @@ describe RipperRubyParser::Parser do
194
254
  s(:str, 'z'))
195
255
  end
196
256
 
197
- it 'handles non-literals' do
257
+ it 'handles non-literal begin' do
258
+ 'foo...3'.
259
+ must_be_parsed_as s(:dot3,
260
+ s(:call, nil, :foo),
261
+ s(:lit, 3))
262
+ end
263
+
264
+ it 'handles non-literal end' do
265
+ '3...foo'.
266
+ must_be_parsed_as s(:dot3,
267
+ s(:lit, 3),
268
+ s(:call, nil, :foo))
269
+ end
270
+
271
+ it 'handles two non-literals' do
198
272
  'foo...bar'.
199
273
  must_be_parsed_as s(:dot3,
200
274
  s(:call, nil, :foo),
@@ -202,7 +276,7 @@ describe RipperRubyParser::Parser do
202
276
  end
203
277
  end
204
278
 
205
- describe 'for unary numerical operators' do
279
+ describe 'for unary operators' do
206
280
  it 'handles unary minus with an integer literal' do
207
281
  '- 1'.must_be_parsed_as s(:call, s(:lit, 1), :-@)
208
282
  end
@@ -232,6 +306,94 @@ describe RipperRubyParser::Parser do
232
306
  s(:call, nil, :foo),
233
307
  :+@)
234
308
  end
309
+
310
+ it 'handles unary !' do
311
+ '!foo'.
312
+ must_be_parsed_as s(:call, s(:call, nil, :foo), :!)
313
+ end
314
+
315
+ it 'converts :not to :!' do
316
+ 'not foo'.
317
+ must_be_parsed_as s(:call, s(:call, nil, :foo), :!)
318
+ end
319
+
320
+ it 'handles unary ! with a number literal' do
321
+ '!1'.
322
+ must_be_parsed_as s(:call, s(:lit, 1), :!)
323
+ end
324
+
325
+ it 'keeps :begin for the argument' do
326
+ '- begin; foo; end'.
327
+ must_be_parsed_as s(:call,
328
+ s(:begin, s(:call, nil, :foo)),
329
+ :-@)
330
+ end
331
+ end
332
+
333
+ describe 'for the ternary operater' do
334
+ it 'works in the simple case' do
335
+ 'foo ? bar : baz'.
336
+ must_be_parsed_as s(:if,
337
+ s(:call, nil, :foo),
338
+ s(:call, nil, :bar),
339
+ s(:call, nil, :baz))
340
+ end
341
+
342
+ it 'keeps :begin for the first argument' do
343
+ 'begin; foo; end ? bar : baz'.
344
+ must_be_parsed_as s(:if,
345
+ s(:begin, s(:call, nil, :foo)),
346
+ s(:call, nil, :bar),
347
+ s(:call, nil, :baz))
348
+ end
349
+
350
+ it 'keeps :begin for the second argument' do
351
+ 'foo ? begin; bar; end : baz'.
352
+ must_be_parsed_as s(:if,
353
+ s(:call, nil, :foo),
354
+ s(:begin, s(:call, nil, :bar)),
355
+ s(:call, nil, :baz))
356
+ end
357
+
358
+ it 'keeps :begin for the third argument' do
359
+ 'foo ? bar : begin; baz; end'.
360
+ must_be_parsed_as s(:if,
361
+ s(:call, nil, :foo),
362
+ s(:call, nil, :bar),
363
+ s(:begin, s(:call, nil, :baz)))
364
+ end
365
+ end
366
+
367
+ describe 'for match operators' do
368
+ it 'handles :=~ with two non-literals' do
369
+ 'foo =~ bar'.
370
+ must_be_parsed_as s(:call,
371
+ s(:call, nil, :foo),
372
+ :=~,
373
+ s(:call, nil, :bar))
374
+ end
375
+
376
+ it 'handles :=~ with literal regexp on the left hand side' do
377
+ '/foo/ =~ bar'.
378
+ must_be_parsed_as s(:match2,
379
+ s(:lit, /foo/),
380
+ s(:call, nil, :bar))
381
+ end
382
+
383
+ it 'handles :=~ with literal regexp on the right hand side' do
384
+ 'foo =~ /bar/'.
385
+ must_be_parsed_as s(:match3,
386
+ s(:lit, /bar/),
387
+ s(:call, nil, :foo))
388
+ end
389
+
390
+ it 'handles negated match operators' do
391
+ 'foo !~ bar'.must_be_parsed_as s(:not,
392
+ s(:call,
393
+ s(:call, nil, :foo),
394
+ :=~,
395
+ s(:call, nil, :bar)))
396
+ end
235
397
  end
236
398
  end
237
399
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
4
 
3
5
  class TestProcessor < RipperRubyParser::SexpProcessor
@@ -39,26 +41,14 @@ describe RipperRubyParser::SexpProcessor do
39
41
 
40
42
  describe 'for a :string_literal sexp' do
41
43
  it 'transforms a simple sexp to :str' do
42
- sexp = s(:string_literal, s(:string_content, s(:@tstring_content, 'foo')))
44
+ sexp = s(:string_literal,
45
+ s(:string_content,
46
+ s(:@tstring_content, 'foo', s(1, 1), '"')))
43
47
  result = processor.process sexp
44
48
  result.must_equal s(:str, 'foo')
45
49
  end
46
50
  end
47
51
 
48
- describe 'for an :args_add_block sexp' do
49
- it 'transforms a one-argument sexp to an :arglist' do
50
- sexp = s(:args_add_block, s(:args, s(:foo)), false)
51
- result = processor.process sexp
52
- result.must_equal s(:arglist, s(:foo_p))
53
- end
54
-
55
- it 'transforms a multi-argument sexp to an :arglist' do
56
- sexp = s(:args_add_block, s(:args, s(:foo), s(:bar)), false)
57
- result = processor.process sexp
58
- result.must_equal s(:arglist, s(:foo_p), s(:bar_p))
59
- end
60
- end
61
-
62
52
  describe 'for a :command sexp' do
63
53
  it 'transforms a sexp to a :call' do
64
54
  sexp = s(:command, s(:@ident, 'foo', s(1, 0)), s(:arglist, s(:foo)))
@@ -298,14 +288,14 @@ describe RipperRubyParser::SexpProcessor do
298
288
  end
299
289
 
300
290
  describe '#extract_node_symbol' do
301
- it 'processes an identifier sexp to a bare symbol' do
302
- sexp = s(:@ident, 'foo', s(1, 0))
291
+ it 'processes an lvar sexp to a bare symbol' do
292
+ sexp = s(:lvar, 'foo')
303
293
  result = processor.send :extract_node_symbol, sexp
304
294
  result.must_equal :foo
305
295
  end
306
296
 
307
297
  it 'processes a const sexp to a bare symbol' do
308
- sexp = s(:@const, 'Foo', s(1, 0))
298
+ sexp = s(:const, 'Foo')
309
299
  result = processor.send :extract_node_symbol, sexp
310
300
  result.must_equal :Foo
311
301
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  describe RipperRubyParser do
2
4
  it 'knows its own version' do
3
5
  RipperRubyParser::VERSION.wont_be_nil
@@ -0,0 +1,13 @@
1
+ =begin
2
+ This is an unusual type of comment that needs to be handled correctly
3
+ =end
4
+
5
+ class Foo
6
+
7
+ end
8
+
9
+ # This is a more common type of comment
10
+
11
+ class Bar
12
+
13
+ end
@@ -0,0 +1,23 @@
1
+ # Conditionals
2
+
3
+ if begin foo end
4
+ bar
5
+ end
6
+
7
+ if begin foo..bar end
8
+ baz
9
+ end
10
+
11
+ if foo
12
+ elsif begin bar end
13
+ end
14
+
15
+ if foo
16
+ elsif begin bar..baz end
17
+ end
18
+
19
+ if 1
20
+ bar
21
+ else
22
+ baz
23
+ end
@@ -0,0 +1,36 @@
1
+ # Loop samples
2
+
3
+ def for_samples
4
+ for foo in bar
5
+ end
6
+
7
+ for foo, bar in baz
8
+ end
9
+
10
+ for foo, in bar
11
+ end
12
+ end
13
+
14
+ # begin..end in conditions
15
+ #
16
+ def while_until_samples
17
+ while begin foo end
18
+ bar
19
+ end
20
+
21
+ until begin foo end
22
+ bar
23
+ end
24
+
25
+ while begin foo end do
26
+ bar
27
+ end
28
+
29
+ until begin foo end do
30
+ bar
31
+ end
32
+
33
+ foo while begin bar end
34
+
35
+ foo until begin bar end
36
+ end
@@ -1,5 +1,21 @@
1
1
  # Miscellaneous samples
2
2
 
3
+ BEGIN {
4
+ begin
5
+ foo
6
+ end
7
+ }
8
+
9
+ BEGIN {}
10
+
11
+ END {
12
+ begin
13
+ bar
14
+ end
15
+ }
16
+
17
+ END {}
18
+
3
19
  # regular expressions with different encoding flags
4
20
  regular = /foo/
5
21
  noenc = /foo/n
@@ -18,19 +34,19 @@ sjis = /foo#{bar}/s
18
34
  enc = __ENCODING__
19
35
 
20
36
  class Foo
21
- # calling #[] on self
22
- # https://github.com/seattlerb/ruby_parser/issues/250
37
+ # calling #[] on self
38
+ # https://github.com/seattlerb/ruby_parser/issues/250
23
39
  def bar
24
40
  self[:foo]
25
41
  end
26
42
 
27
- # required keyword arguments and no parentheses
28
- # https://github.com/seattlerb/ruby_parser/pull/254
43
+ # required keyword arguments and no parentheses
44
+ # https://github.com/seattlerb/ruby_parser/pull/254
29
45
  def foo a:, b:
30
46
  puts "A: #{a}, B: #{b}"
31
47
  end
32
48
 
33
- # Combinations of begin..end and diverse operators
49
+ # Combinations of begin..end and diverse operators
34
50
  def qux
35
51
  begin end
36
52
  begin; foo; end
@@ -45,5 +61,141 @@ class Foo
45
61
  foo and begin; bar; end
46
62
  begin; foo; end if bar
47
63
  begin; foo; end unless bar
64
+ begin; foo; end.bar
65
+ foo ||= begin; bar; end
66
+ foo += begin; bar; end
67
+ foo[qux] ||= begin; bar; end
68
+ foo = begin; bar; end
69
+ foo = begin; if bar; baz; end; end
70
+ baz = begin; foo; ensure; bar; end
71
+ foo = *begin; bar; end
72
+ foo = bar, *begin; baz; end
73
+ foo, bar = *begin; baz; end
74
+ foo if begin bar end
75
+ end
76
+
77
+ # Nested do and begin blocks
78
+ def quuz
79
+ foo do
80
+ bar
81
+
82
+ begin
83
+ baz
84
+ rescue
85
+ qux
86
+ end
87
+
88
+ quuz
89
+ end
90
+ end
91
+
92
+ # Nested begin/rescue blocks
93
+ def quuz
94
+ begin
95
+ bar
96
+ rescue
97
+ begin
98
+ baz
99
+ end
100
+ end
101
+
102
+ begin
103
+ bar
104
+ rescue
105
+ begin
106
+ baz
107
+ rescue
108
+ qux
109
+ end
110
+ end
111
+
112
+ begin
113
+ bar
114
+ rescue
115
+ begin
116
+ baz
117
+ end
118
+ begin
119
+ qux
120
+ end
121
+ end
122
+ end
123
+
124
+ # Begin/end blocks and case statements
125
+ def quuz
126
+ case foo
127
+ when bar
128
+ begin
129
+ baz
130
+ end
131
+ end
132
+ end
133
+
134
+ # Using splat and double-splat args
135
+ def barbaz(*foo, **bar)
136
+ puts [foo, bar]
137
+ foo.each do |baz, **qux|
138
+ puts [foo, bar, baz, qux]
139
+ end
140
+ puts [foo, bar]
141
+ end
142
+
143
+ def barbaz_block(*foo, **bar, &block)
144
+ puts [foo, bar]
145
+ end
146
+
147
+ def self.barbaz(*foo, **bar)
148
+ puts [foo, bar]
149
+ foo.each do |baz, **qux|
150
+ puts [foo, bar, baz, qux]
151
+ end
152
+ puts [foo, bar]
153
+ end
154
+
155
+ # rescue
156
+ def barfoo
157
+ foo
158
+ rescue *bar
159
+ baz
160
+ rescue *quuz, Bar
161
+ zyxxy
162
+ rescue *qux => err
163
+ puts err
164
+ end
165
+
166
+ # alias
167
+ alias foo bar
168
+ alias :foo bar
169
+ alias :foo :bar
170
+ alias foo :bar
171
+ alias :+ -
172
+ alias next bar
173
+
174
+ # rescue with assignment
175
+ foo = bar rescue baz
176
+ foo = bar baz rescue qux
177
+ foo = bar(baz) rescue qux
178
+ foo, bar = baz qux rescue quuz
179
+ @foo = bar baz rescue qux
180
+ @@foo = bar baz rescue qux
181
+ FOO = bar baz rescue qux
182
+ $foo = bar baz rescue qux
183
+ foo = Foo.bar(baz) rescue qux
184
+ foo = Foo.bar baz rescue qux
185
+
186
+ # Assignment to class variables inside method argument
187
+ # definitions.
188
+ def foo(bar = (@@baz = qux))
189
+ end
190
+
191
+ def self.foo(bar = (@@baz = qux))
192
+ end
193
+
194
+ def (bar = (@@baz = qux)).foo
195
+ end
196
+
197
+ # Assignment to global variables inside method argument
198
+ # definitions.
199
+ def foo(bar = ($baz = qux))
48
200
  end
49
201
  end