ripper_ruby_parser 1.4.2 → 1.5.0

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