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,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RipperRubyParser
2
4
  class SyntaxError < RuntimeError; end
3
5
  end
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RipperRubyParser
2
4
  # Implements string unescaping
3
5
  #
4
6
  # @api private
5
7
  module Unescape
6
- module_function
7
-
8
8
  ESCAPE_SEQUENCE_REGEXP =
9
9
  /\\(
10
10
  [0-7]{1,3} | # octal character
11
11
  x[0-9a-fA-F]{1,2} | # hex byte
12
- u[0-9a-fA-F]{4} | # unicode character
12
+ u[0-9a-fA-F]+ | # unicode character
13
+ u{[0-9a-fA-F]{4}} | # unicode character
13
14
  M-\\C-. | # meta-ctrl
14
15
  C-\\M-. | # ctrl-meta
15
16
  M-\\c. | # meta-ctrl (shorthand)
@@ -19,7 +20,7 @@ module RipperRubyParser
19
20
  M-. | # meta
20
21
  \n | # line continuation
21
22
  . # single-character
22
- )/x
23
+ )/x.freeze
23
24
 
24
25
  SINGLE_LETTER_ESCAPES = {
25
26
  'a' => "\a",
@@ -49,6 +50,7 @@ module RipperRubyParser
49
50
  string.gsub(/\\(
50
51
  ' | # single quote
51
52
  \\ | # backslash
53
+ [ ] | # space
52
54
  \n # newline
53
55
  )/x) do
54
56
  Regexp.last_match[1]
@@ -93,27 +95,46 @@ module RipperRubyParser
93
95
  end
94
96
  end
95
97
 
98
+ private
99
+
96
100
  def unescaped_value(bare)
97
101
  case bare
98
102
  when SINGLE_LETTER_ESCAPES_REGEXP
99
103
  SINGLE_LETTER_ESCAPES[bare]
100
104
  when /^x/
101
- bare[1..-1].to_i(16).chr
105
+ hex_to_char(bare[1..-1])
106
+ when /^u\{/
107
+ hex_to_unicode_char(bare[2..-2])
102
108
  when /^u/
103
- bare[1..-1].to_i(16).chr(Encoding::UTF_8)
109
+ hex_to_unicode_char(bare[1..4]) +
110
+ (extra_compatible ? '' : bare[5..-1])
104
111
  when /^(c|C-).$/
105
- (bare[-1].ord & 0b1001_1111).chr
112
+ control(bare[-1].ord).chr
106
113
  when /^M-.$/
107
- (bare[-1].ord | 0b1000_0000).chr
114
+ meta(bare[-1].ord).chr
108
115
  when /^(M-\\C-|C-\\M-|M-\\c|c\\M-).$/
109
- (bare[-1].ord & 0b1001_1111 | 0b1000_0000).chr
116
+ meta(control(bare[-1].ord)).chr
110
117
  when /^[0-7]+/
111
118
  bare.to_i(8).chr
112
- when "\n"
113
- bare
114
119
  else
115
120
  bare
116
121
  end
117
122
  end
123
+
124
+ def hex_to_unicode_char(str)
125
+ str.to_i(16).chr(Encoding::UTF_8)
126
+ end
127
+
128
+ def hex_to_char(str)
129
+ str.to_i(16).chr
130
+ end
131
+
132
+ def control(val)
133
+ val & 0b1001_1111
134
+ end
135
+
136
+ def meta(val)
137
+ val | 0b1000_0000
138
+ end
118
139
  end
119
140
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RipperRubyParser
2
- VERSION = '1.4.2'.freeze
4
+ VERSION = '1.5.0'
3
5
  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
  require 'ruby_parser'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
4
  require 'ruby_parser'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
4
  require 'ruby_parser'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
4
  require 'ruby_parser'
3
5
 
@@ -1,37 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
4
  require 'ruby_parser'
3
5
 
4
6
  describe 'Using RipperRubyParser and RubyParser' do
5
- let :newparser do
6
- RipperRubyParser::Parser.new
7
- end
8
-
9
- let :oldparser do
10
- RubyParser.new
11
- end
12
-
13
7
  Dir.glob(File.expand_path('../samples/*.rb', File.dirname(__FILE__))).each do |file|
14
- describe "for #{file}" do
15
- let :program do
16
- File.read file
17
- end
18
-
19
- let :original do
20
- oldparser.parse program
21
- end
22
-
23
- let :imitation do
24
- newparser.parse program
25
- end
26
-
27
- it 'gives the same result' do
28
- formatted(imitation).must_equal formatted(original)
29
- end
30
-
31
- it 'gives the same result with comments' do
32
- formatted(to_comments(imitation)).
33
- must_equal formatted(to_comments(original))
34
- end
8
+ it "gives the same result for #{file}" do
9
+ program = File.read file
10
+ program.must_be_parsed_as_before
35
11
  end
36
12
  end
37
13
  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
  require 'ruby_parser'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
4
  require 'pt_testcase'
3
5
 
@@ -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
  describe RipperRubyParser::CommentingRipperParser do
@@ -99,7 +101,7 @@ describe RipperRubyParser::CommentingRipperParser do
99
101
  result.must_equal s(:program,
100
102
  s(:stmts,
101
103
  s(:dyna_symbol,
102
- s(:xstring, s(:@tstring_content, 'foo', s(1, 2)))),
104
+ s(:xstring, s(:@tstring_content, 'foo', s(1, 2), ":'"))),
103
105
  s(:comment,
104
106
  '',
105
107
  s(:def,
@@ -114,7 +116,7 @@ describe RipperRubyParser::CommentingRipperParser do
114
116
  s(:stmts,
115
117
  s(:dyna_symbol,
116
118
  s(:xstring,
117
- s(:@tstring_content, 'foo', s(1, 2)),
119
+ s(:@tstring_content, 'foo', s(1, 2), ':"'),
118
120
  s(:string_embexpr,
119
121
  s(:stmts,
120
122
  s(:comment,
@@ -128,6 +130,18 @@ describe RipperRubyParser::CommentingRipperParser do
128
130
  nil,
129
131
  nil)))))))))
130
132
  end
133
+
134
+ it 'turns an embedded document into a comment node' do
135
+ result = parse_with_builder "=begin Hello\nthere\n=end\nclass Foo; end"
136
+ result.must_equal s(:program,
137
+ s(:stmts,
138
+ s(:comment,
139
+ "=begin Hello\nthere\n=end\n",
140
+ s(:class,
141
+ s(:const_ref, s(:@const, 'Foo', s(4, 6))),
142
+ nil,
143
+ s(:bodystmt, s(:stmts, s(:void_stmt)), nil, nil, nil)))))
144
+ end
131
145
  end
132
146
 
133
147
  describe 'handling syntax errors' do
@@ -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
  describe RipperRubyParser::Parser do
@@ -28,6 +30,11 @@ describe RipperRubyParser::Parser do
28
30
  end
29
31
 
30
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
+
31
38
  it 'works with a namespaced module name' do
32
39
  'module Foo::Bar; end'.
33
40
  must_be_parsed_as s(:module,
@@ -41,83 +48,6 @@ describe RipperRubyParser::Parser do
41
48
  end
42
49
  end
43
50
 
44
- describe 'for the return statement' do
45
- it 'works with no arguments' do
46
- 'return'.
47
- must_be_parsed_as s(:return)
48
- end
49
-
50
- it 'works with one argument' do
51
- 'return foo'.
52
- must_be_parsed_as s(:return,
53
- s(:call, nil, :foo))
54
- end
55
-
56
- it 'works with a splat argument' do
57
- 'return *foo'.
58
- must_be_parsed_as s(:return,
59
- s(:svalue,
60
- s(:splat,
61
- s(:call, nil, :foo))))
62
- end
63
-
64
- it 'works with multiple arguments' do
65
- 'return foo, bar'.
66
- must_be_parsed_as s(:return,
67
- s(:array,
68
- s(:call, nil, :foo),
69
- s(:call, nil, :bar)))
70
- end
71
-
72
- it 'works with a regular argument and a splat argument' do
73
- 'return foo, *bar'.
74
- must_be_parsed_as s(:return,
75
- s(:array,
76
- s(:call, nil, :foo),
77
- s(:splat,
78
- s(:call, nil, :bar))))
79
- end
80
-
81
- it 'works with a function call with parentheses' do
82
- 'return foo(bar)'.
83
- must_be_parsed_as s(:return,
84
- s(:call, nil, :foo,
85
- s(:call, nil, :bar)))
86
- end
87
-
88
- it 'works with a function call without parentheses' do
89
- 'return foo bar'.
90
- must_be_parsed_as s(:return,
91
- s(:call, nil, :foo,
92
- s(:call, nil, :bar)))
93
- end
94
- end
95
-
96
- describe 'for the for statement' do
97
- it 'works with do' do
98
- 'for foo in bar do; baz; end'.
99
- must_be_parsed_as s(:for,
100
- s(:call, nil, :bar),
101
- s(:lasgn, :foo),
102
- s(:call, nil, :baz))
103
- end
104
-
105
- it 'works without do' do
106
- 'for foo in bar; baz; end'.
107
- must_be_parsed_as s(:for,
108
- s(:call, nil, :bar),
109
- s(:lasgn, :foo),
110
- s(:call, nil, :baz))
111
- end
112
-
113
- it 'works with an empty body' do
114
- 'for foo in bar; end'.
115
- must_be_parsed_as s(:for,
116
- s(:call, nil, :bar),
117
- s(:lasgn, :foo))
118
- end
119
- end
120
-
121
51
  describe 'for a begin..end block' do
122
52
  it 'works with no statements' do
123
53
  'begin; end'.
@@ -137,57 +67,6 @@ describe RipperRubyParser::Parser do
137
67
  end
138
68
  end
139
69
 
140
- describe 'for the undef statement' do
141
- it 'works with a single bareword identifier' do
142
- 'undef foo'.
143
- must_be_parsed_as s(:undef, s(:lit, :foo))
144
- end
145
-
146
- it 'works with a single symbol' do
147
- 'undef :foo'.
148
- must_be_parsed_as s(:undef, s(:lit, :foo))
149
- end
150
-
151
- it 'works with multiple bareword identifiers' do
152
- 'undef foo, bar'.
153
- must_be_parsed_as s(:block,
154
- s(:undef, s(:lit, :foo)),
155
- s(:undef, s(:lit, :bar)))
156
- end
157
-
158
- it 'works with multiple bareword symbols' do
159
- 'undef :foo, :bar'.
160
- must_be_parsed_as s(:block,
161
- s(:undef, s(:lit, :foo)),
162
- s(:undef, s(:lit, :bar)))
163
- end
164
- end
165
-
166
- describe 'for the alias statement' do
167
- it 'works with regular barewords' do
168
- 'alias foo bar'.
169
- must_be_parsed_as s(:alias,
170
- s(:lit, :foo), s(:lit, :bar))
171
- end
172
-
173
- it 'works with symbols' do
174
- 'alias :foo :bar'.
175
- must_be_parsed_as s(:alias,
176
- s(:lit, :foo), s(:lit, :bar))
177
- end
178
-
179
- it 'works with operator barewords' do
180
- 'alias + -'.
181
- must_be_parsed_as s(:alias,
182
- s(:lit, :+), s(:lit, :-))
183
- end
184
-
185
- it 'works with global variables' do
186
- 'alias $foo $bar'.
187
- must_be_parsed_as s(:valias, :$foo, :$bar)
188
- end
189
- end
190
-
191
70
  describe 'for arguments' do
192
71
  it 'works for a simple case with splat' do
193
72
  'foo *bar'.
@@ -222,241 +101,6 @@ describe RipperRubyParser::Parser do
222
101
  end
223
102
  end
224
103
 
225
- describe 'for collection indexing' do
226
- it 'works in the simple case' do
227
- 'foo[bar]'.
228
- must_be_parsed_as s(:call,
229
- s(:call, nil, :foo),
230
- :[],
231
- s(:call, nil, :bar))
232
- end
233
-
234
- it 'works without any indexes' do
235
- 'foo[]'.must_be_parsed_as s(:call, s(:call, nil, :foo),
236
- :[])
237
- end
238
-
239
- it 'works with self[]' do
240
- 'self[foo]'.must_be_parsed_as s(:call, s(:self), :[],
241
- s(:call, nil, :foo))
242
- end
243
- end
244
-
245
- describe 'for method definitions' do
246
- it 'works with def with receiver' do
247
- 'def foo.bar; end'.
248
- must_be_parsed_as s(:defs,
249
- s(:call, nil, :foo),
250
- :bar,
251
- s(:args),
252
- s(:nil))
253
- end
254
-
255
- it 'works with def with receiver and multiple statements' do
256
- 'def foo.bar; baz; qux; end'.
257
- must_be_parsed_as s(:defs,
258
- s(:call, nil, :foo),
259
- :bar,
260
- s(:args),
261
- s(:call, nil, :baz),
262
- s(:call, nil, :qux))
263
- end
264
-
265
- it 'works with a method argument with a default value' do
266
- 'def foo bar=nil; end'.
267
- must_be_parsed_as s(:defn,
268
- :foo,
269
- s(:args, s(:lasgn, :bar, s(:nil))),
270
- s(:nil))
271
- end
272
-
273
- it 'works with several method arguments with default values' do
274
- 'def foo bar=1, baz=2; end'.
275
- must_be_parsed_as s(:defn,
276
- :foo,
277
- s(:args,
278
- s(:lasgn, :bar, s(:lit, 1)),
279
- s(:lasgn, :baz, s(:lit, 2))),
280
- s(:nil))
281
- end
282
-
283
- it 'works with parentheses around the parameter list' do
284
- 'def foo(bar); end'.
285
- must_be_parsed_as s(:defn, :foo, s(:args, :bar), s(:nil))
286
- end
287
-
288
- it 'works with a simple splat' do
289
- 'def foo *bar; end'.
290
- must_be_parsed_as s(:defn, :foo, s(:args, :"*bar"), s(:nil))
291
- end
292
-
293
- it 'works with a regular argument plus splat' do
294
- 'def foo bar, *baz; end'.
295
- must_be_parsed_as s(:defn, :foo, s(:args, :bar, :"*baz"), s(:nil))
296
- end
297
-
298
- it 'works with a nameless splat' do
299
- 'def foo *; end'.
300
- must_be_parsed_as s(:defn,
301
- :foo,
302
- s(:args, :"*"),
303
- s(:nil))
304
- end
305
-
306
- it 'works for a simple case with explicit block parameter' do
307
- 'def foo &bar; end'.
308
- must_be_parsed_as s(:defn,
309
- :foo,
310
- s(:args, :"&bar"),
311
- s(:nil))
312
- end
313
-
314
- it 'works with a regular argument plus explicit block parameter' do
315
- 'def foo bar, &baz; end'.
316
- must_be_parsed_as s(:defn,
317
- :foo,
318
- s(:args, :bar, :"&baz"),
319
- s(:nil))
320
- end
321
-
322
- it 'works with a default value plus explicit block parameter' do
323
- 'def foo bar=1, &baz; end'.
324
- must_be_parsed_as s(:defn,
325
- :foo,
326
- s(:args,
327
- s(:lasgn, :bar, s(:lit, 1)),
328
- :"&baz"),
329
- s(:nil))
330
- end
331
-
332
- it 'works with a default value plus mandatory argument' do
333
- 'def foo bar=1, baz; end'.
334
- must_be_parsed_as s(:defn,
335
- :foo,
336
- s(:args,
337
- s(:lasgn, :bar, s(:lit, 1)),
338
- :baz),
339
- s(:nil))
340
- end
341
-
342
- it 'works with a splat plus explicit block parameter' do
343
- 'def foo *bar, &baz; end'.
344
- must_be_parsed_as s(:defn,
345
- :foo,
346
- s(:args, :"*bar", :"&baz"),
347
- s(:nil))
348
- end
349
-
350
- it 'works with a default value plus splat' do
351
- 'def foo bar=1, *baz; end'.
352
- must_be_parsed_as s(:defn,
353
- :foo,
354
- s(:args,
355
- s(:lasgn, :bar, s(:lit, 1)),
356
- :"*baz"),
357
- s(:nil))
358
- end
359
-
360
- it 'works with a default value, splat, plus final mandatory arguments' do
361
- 'def foo bar=1, *baz, qux, quuz; end'.
362
- must_be_parsed_as s(:defn,
363
- :foo,
364
- s(:args,
365
- s(:lasgn, :bar, s(:lit, 1)),
366
- :"*baz", :qux, :quuz),
367
- s(:nil))
368
- end
369
-
370
- it 'works with a named argument with a default value' do
371
- 'def foo bar: 1; end'.
372
- must_be_parsed_as s(:defn,
373
- :foo,
374
- s(:args,
375
- s(:kwarg, :bar, s(:lit, 1))),
376
- s(:nil))
377
- end
378
-
379
- it 'works with a named argument with no default value' do
380
- 'def foo bar:; end'.
381
- must_be_parsed_as s(:defn,
382
- :foo,
383
- s(:args,
384
- s(:kwarg, :bar)),
385
- s(:nil))
386
- end
387
-
388
- it 'works with a double splat' do
389
- 'def foo **bar; end'.
390
- must_be_parsed_as s(:defn,
391
- :foo,
392
- s(:args, :'**bar'),
393
- s(:nil))
394
- end
395
-
396
- it 'works when the method name is an operator' do
397
- 'def +; end'.
398
- must_be_parsed_as s(:defn, :+, s(:args),
399
- s(:nil))
400
- end
401
- end
402
-
403
- describe 'for yield' do
404
- it 'works with no arguments and no parentheses' do
405
- 'yield'.
406
- must_be_parsed_as s(:yield)
407
- end
408
-
409
- it 'works with parentheses but no arguments' do
410
- 'yield()'.
411
- must_be_parsed_as s(:yield)
412
- end
413
-
414
- it 'works with one argument and no parentheses' do
415
- 'yield foo'.
416
- must_be_parsed_as s(:yield, s(:call, nil, :foo))
417
- end
418
-
419
- it 'works with one argument and parentheses' do
420
- 'yield(foo)'.
421
- must_be_parsed_as s(:yield, s(:call, nil, :foo))
422
- end
423
-
424
- it 'works with multiple arguments and no parentheses' do
425
- 'yield foo, bar'.
426
- must_be_parsed_as s(:yield,
427
- s(:call, nil, :foo),
428
- s(:call, nil, :bar))
429
- end
430
-
431
- it 'works with multiple arguments and parentheses' do
432
- 'yield(foo, bar)'.
433
- must_be_parsed_as s(:yield,
434
- s(:call, nil, :foo),
435
- s(:call, nil, :bar))
436
- end
437
-
438
- it 'works with splat' do
439
- 'yield foo, *bar'.
440
- must_be_parsed_as s(:yield,
441
- s(:call, nil, :foo),
442
- s(:splat, s(:call, nil, :bar)))
443
- end
444
-
445
- it 'works with a function call with parentheses' do
446
- 'yield foo(bar)'.
447
- must_be_parsed_as s(:yield,
448
- s(:call, nil, :foo,
449
- s(:call, nil, :bar)))
450
- end
451
-
452
- it 'works with a function call without parentheses' do
453
- 'yield foo bar'.
454
- must_be_parsed_as s(:yield,
455
- s(:call, nil, :foo,
456
- s(:call, nil, :bar)))
457
- end
458
- end
459
-
460
104
  describe 'for the __ENCODING__ keyword' do
461
105
  it 'evaluates to the equivalent of Encoding::UTF_8' do
462
106
  '__ENCODING__'.
@@ -494,6 +138,11 @@ describe RipperRubyParser::Parser do
494
138
  'END { foo }'.
495
139
  must_be_parsed_as s(:iter, s(:postexe), 0, s(:call, nil, :foo))
496
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
497
146
  end
498
147
 
499
148
  describe 'for the BEGIN keyword' do
@@ -501,6 +150,11 @@ describe RipperRubyParser::Parser do
501
150
  'BEGIN { foo }'.
502
151
  must_be_parsed_as s(:iter, s(:preexe), s(:args), s(:call, nil, :foo))
503
152
  end
153
+
154
+ it 'works with an empty block' do
155
+ 'BEGIN { }'.
156
+ must_be_parsed_as s(:iter, s(:preexe), s(:args))
157
+ end
504
158
  end
505
159
 
506
160
  describe 'for constant lookups' do
@@ -553,307 +207,6 @@ describe RipperRubyParser::Parser do
553
207
  end
554
208
  end
555
209
 
556
- describe 'for single assignment' do
557
- it 'works when assigning to an instance variable' do
558
- '@foo = bar'.
559
- must_be_parsed_as s(:iasgn,
560
- :@foo,
561
- s(:call, nil, :bar))
562
- end
563
-
564
- it 'works when assigning to a constant' do
565
- 'FOO = bar'.
566
- must_be_parsed_as s(:cdecl,
567
- :FOO,
568
- s(:call, nil, :bar))
569
- end
570
-
571
- it 'works when assigning to a collection element' do
572
- 'foo[bar] = baz'.
573
- must_be_parsed_as s(:attrasgn,
574
- s(:call, nil, :foo),
575
- :[]=,
576
- s(:call, nil, :bar),
577
- s(:call, nil, :baz))
578
- end
579
-
580
- it 'works when assigning to an attribute' do
581
- 'foo.bar = baz'.
582
- must_be_parsed_as s(:attrasgn,
583
- s(:call, nil, :foo),
584
- :bar=,
585
- s(:call, nil, :baz))
586
- end
587
-
588
- it 'works when assigning to a class variable' do
589
- '@@foo = bar'.
590
- must_be_parsed_as s(:cvdecl,
591
- :@@foo,
592
- s(:call, nil, :bar))
593
- end
594
-
595
- it 'works when assigning to a class variable inside a method' do
596
- 'def foo; @@bar = baz; end'.
597
- must_be_parsed_as s(:defn,
598
- :foo, s(:args),
599
- s(:cvasgn, :@@bar, s(:call, nil, :baz)))
600
- end
601
-
602
- it 'works when assigning to a class variable inside a method with a receiver' do
603
- 'def self.foo; @@bar = baz; end'.
604
- must_be_parsed_as s(:defs,
605
- s(:self),
606
- :foo, s(:args),
607
- s(:cvasgn, :@@bar, s(:call, nil, :baz)))
608
- end
609
-
610
- it 'works when assigning to a global variable' do
611
- '$foo = bar'.
612
- must_be_parsed_as s(:gasgn,
613
- :$foo,
614
- s(:call, nil, :bar))
615
- end
616
- end
617
-
618
- describe 'for operator assignment' do
619
- it 'works with +=' do
620
- 'foo += bar'.
621
- must_be_parsed_as s(:lasgn,
622
- :foo,
623
- s(:call,
624
- s(:lvar, :foo),
625
- :+,
626
- s(:call, nil, :bar)))
627
- end
628
-
629
- it 'works with -=' do
630
- 'foo -= bar'.
631
- must_be_parsed_as s(:lasgn,
632
- :foo,
633
- s(:call,
634
- s(:lvar, :foo),
635
- :-,
636
- s(:call, nil, :bar)))
637
- end
638
-
639
- it 'works with ||=' do
640
- 'foo ||= bar'.
641
- must_be_parsed_as s(:op_asgn_or,
642
- s(:lvar, :foo),
643
- s(:lasgn, :foo,
644
- s(:call, nil, :bar)))
645
- end
646
-
647
- it 'works when assigning to an instance variable' do
648
- '@foo += bar'.
649
- must_be_parsed_as s(:iasgn,
650
- :@foo,
651
- s(:call,
652
- s(:ivar, :@foo),
653
- :+,
654
- s(:call, nil, :bar)))
655
- end
656
-
657
- it 'works when assigning to a collection element' do
658
- 'foo[bar] += baz'.
659
- must_be_parsed_as s(:op_asgn1,
660
- s(:call, nil, :foo),
661
- s(:arglist, s(:call, nil, :bar)),
662
- :+,
663
- s(:call, nil, :baz))
664
- end
665
-
666
- it 'works with ||= when assigning to a collection element' do
667
- 'foo[bar] ||= baz'.
668
- must_be_parsed_as s(:op_asgn1,
669
- s(:call, nil, :foo),
670
- s(:arglist, s(:call, nil, :bar)),
671
- :"||",
672
- s(:call, nil, :baz))
673
- end
674
-
675
- it 'works when assigning to an attribute' do
676
- 'foo.bar += baz'.
677
- must_be_parsed_as s(:op_asgn2,
678
- s(:call, nil, :foo),
679
- :bar=,
680
- :+,
681
- s(:call, nil, :baz))
682
- end
683
-
684
- it 'works with ||= when assigning to an attribute' do
685
- 'foo.bar ||= baz'.
686
- must_be_parsed_as s(:op_asgn2,
687
- s(:call, nil, :foo),
688
- :bar=,
689
- :"||",
690
- s(:call, nil, :baz))
691
- end
692
- end
693
-
694
- describe 'for multiple assignment' do
695
- it 'works the same number of items on each side' do
696
- 'foo, bar = baz, qux'.
697
- must_be_parsed_as s(:masgn,
698
- s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
699
- s(:array,
700
- s(:call, nil, :baz),
701
- s(:call, nil, :qux)))
702
- end
703
-
704
- it 'works with a single item on the right-hand side' do
705
- 'foo, bar = baz'.
706
- must_be_parsed_as s(:masgn,
707
- s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
708
- s(:to_ary,
709
- s(:call, nil, :baz)))
710
- end
711
-
712
- it 'works with left-hand splat' do
713
- 'foo, *bar = baz, qux'.
714
- must_be_parsed_as s(:masgn,
715
- s(:array, s(:lasgn, :foo), s(:splat, s(:lasgn, :bar))),
716
- s(:array,
717
- s(:call, nil, :baz),
718
- s(:call, nil, :qux)))
719
- end
720
-
721
- it 'works with parentheses around the left-hand side' do
722
- '(foo, bar) = baz'.
723
- must_be_parsed_as s(:masgn,
724
- s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
725
- s(:to_ary, s(:call, nil, :baz)))
726
- end
727
-
728
- it 'works with complex destructuring' do
729
- 'foo, (bar, baz) = qux'.
730
- must_be_parsed_as s(:masgn,
731
- s(:array,
732
- s(:lasgn, :foo),
733
- s(:masgn,
734
- s(:array, s(:lasgn, :bar), s(:lasgn, :baz)))),
735
- s(:to_ary, s(:call, nil, :qux)))
736
- end
737
-
738
- it 'works with complex destructuring of the value' do
739
- 'foo, (bar, baz) = [qux, [quz, quuz]]'.
740
- must_be_parsed_as s(:masgn,
741
- s(:array,
742
- s(:lasgn, :foo),
743
- s(:masgn, s(:array, s(:lasgn, :bar), s(:lasgn, :baz)))),
744
- s(:to_ary,
745
- s(:array,
746
- s(:call, nil, :qux),
747
- s(:array, s(:call, nil, :quz), s(:call, nil, :quuz)))))
748
- end
749
-
750
- it 'works with instance variables' do
751
- '@foo, @bar = baz'.
752
- must_be_parsed_as s(:masgn,
753
- s(:array, s(:iasgn, :@foo), s(:iasgn, :@bar)),
754
- s(:to_ary, s(:call, nil, :baz)))
755
- end
756
-
757
- it 'works with class variables' do
758
- '@@foo, @@bar = baz'.
759
- must_be_parsed_as s(:masgn,
760
- s(:array, s(:cvdecl, :@@foo), s(:cvdecl, :@@bar)),
761
- s(:to_ary, s(:call, nil, :baz)))
762
- end
763
-
764
- it 'works with attributes' do
765
- 'foo.bar, foo.baz = qux'.
766
- must_be_parsed_as s(:masgn,
767
- s(:array,
768
- s(:attrasgn, s(:call, nil, :foo), :bar=),
769
- s(:attrasgn, s(:call, nil, :foo), :baz=)),
770
- s(:to_ary, s(:call, nil, :qux)))
771
- end
772
-
773
- it 'works with collection elements' do
774
- 'foo[1], bar[2] = baz'.
775
- must_be_parsed_as s(:masgn,
776
- s(:array,
777
- s(:attrasgn,
778
- s(:call, nil, :foo), :[]=, s(:lit, 1)),
779
- s(:attrasgn,
780
- s(:call, nil, :bar), :[]=, s(:lit, 2))),
781
- s(:to_ary, s(:call, nil, :baz)))
782
- end
783
-
784
- it 'works with constants' do
785
- 'Foo, Bar = baz'.
786
- must_be_parsed_as s(:masgn,
787
- s(:array, s(:cdecl, :Foo), s(:cdecl, :Bar)),
788
- s(:to_ary, s(:call, nil, :baz)))
789
- end
790
-
791
- it 'works with instance variables and splat' do
792
- '@foo, *@bar = baz'.
793
- must_be_parsed_as s(:masgn,
794
- s(:array,
795
- s(:iasgn, :@foo),
796
- s(:splat, s(:iasgn, :@bar))),
797
- s(:to_ary,
798
- s(:call, nil, :baz)))
799
- end
800
- end
801
-
802
- describe 'for operators' do
803
- it 'handles :!=' do
804
- 'foo != bar'.
805
- must_be_parsed_as s(:call,
806
- s(:call, nil, :foo),
807
- :!=,
808
- s(:call, nil, :bar))
809
- end
810
-
811
- it 'handles :=~ with two non-literals' do
812
- 'foo =~ bar'.
813
- must_be_parsed_as s(:call,
814
- s(:call, nil, :foo),
815
- :=~,
816
- s(:call, nil, :bar))
817
- end
818
-
819
- it 'handles :=~ with literal regexp on the left hand side' do
820
- '/foo/ =~ bar'.
821
- must_be_parsed_as s(:match2,
822
- s(:lit, /foo/),
823
- s(:call, nil, :bar))
824
- end
825
-
826
- it 'handles :=~ with literal regexp on the right hand side' do
827
- 'foo =~ /bar/'.
828
- must_be_parsed_as s(:match3,
829
- s(:lit, /bar/),
830
- s(:call, nil, :foo))
831
- end
832
-
833
- it 'handles unary !' do
834
- '!foo'.
835
- must_be_parsed_as s(:call, s(:call, nil, :foo), :!)
836
- end
837
-
838
- it 'converts :not to :!' do
839
- 'not foo'.
840
- must_be_parsed_as s(:call, s(:call, nil, :foo), :!)
841
- end
842
-
843
- it 'handles unary ! with a number literal' do
844
- '!1'.
845
- must_be_parsed_as s(:call, s(:lit, 1), :!)
846
- end
847
-
848
- it 'handles the ternary operator' do
849
- 'foo ? bar : baz'.
850
- must_be_parsed_as s(:if,
851
- s(:call, nil, :foo),
852
- s(:call, nil, :bar),
853
- s(:call, nil, :baz))
854
- end
855
- end
856
-
857
210
  describe 'for expressions' do
858
211
  it 'handles assignment inside binary operator expressions' do
859
212
  'foo + (bar = baz)'.
@@ -938,15 +291,6 @@ describe RipperRubyParser::Parser do
938
291
  result[4].comments.must_equal "# bar\n"
939
292
  end
940
293
 
941
- it 'handles the use of symbols that are keywords' do
942
- result = parser.parse "# Foo\ndef bar\n:class\nend"
943
- result.must_equal s(:defn,
944
- :bar,
945
- s(:args),
946
- s(:lit, :class))
947
- result.comments.must_equal "# Foo\n"
948
- end
949
-
950
294
  it 'handles use of singleton class inside methods' do
951
295
  result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
952
296
  result.must_equal s(:defn,
@@ -1052,11 +396,6 @@ describe RipperRubyParser::Parser do
1052
396
  result.line.must_equal 1
1053
397
  end
1054
398
 
1055
- it 'works for a symbol literal' do
1056
- result = parser.parse ':foo'
1057
- result.line.must_equal 1
1058
- end
1059
-
1060
399
  it 'works for a class definition' do
1061
400
  result = parser.parse 'class Foo; end'
1062
401
  result.line.must_equal 1
@@ -1072,16 +411,6 @@ describe RipperRubyParser::Parser do
1072
411
  result.line.must_equal 1
1073
412
  end
1074
413
 
1075
- it 'works for assignment of the empty hash' do
1076
- result = parser.parse 'foo = {}'
1077
- result.line.must_equal 1
1078
- end
1079
-
1080
- it 'works for multiple assignment of empty hashes' do
1081
- result = parser.parse 'foo, bar = {}, {}'
1082
- result.line.must_equal 1
1083
- end
1084
-
1085
414
  it 'assigns line numbers to nested sexps without their own line numbers' do
1086
415
  result = parser.parse "foo(bar) do\nnext baz\nend\n"
1087
416
  result.must_equal s(:iter,