unparser 0.1.7 → 0.1.8

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/.rubocop.yml +7 -0
  3. data/.travis.yml +3 -0
  4. data/Changelog.md +4 -0
  5. data/README.md +4 -2
  6. data/config/flay.yml +1 -1
  7. data/config/flog.yml +1 -1
  8. data/config/reek.yml +24 -19
  9. data/config/rubocop.yml +2 -3
  10. data/lib/unparser.rb +8 -22
  11. data/lib/unparser/ast.rb +232 -0
  12. data/lib/unparser/ast/local_variable_scope.rb +198 -0
  13. data/lib/unparser/cli.rb +41 -24
  14. data/lib/unparser/cli/differ.rb +38 -16
  15. data/lib/unparser/cli/source.rb +46 -17
  16. data/lib/unparser/constants.rb +23 -6
  17. data/lib/unparser/emitter.rb +32 -0
  18. data/lib/unparser/emitter/argument.rb +30 -4
  19. data/lib/unparser/emitter/assignment.rb +12 -1
  20. data/lib/unparser/emitter/begin.rb +23 -2
  21. data/lib/unparser/emitter/case.rb +1 -1
  22. data/lib/unparser/emitter/class.rb +1 -0
  23. data/lib/unparser/emitter/def.rb +28 -1
  24. data/lib/unparser/emitter/defined.rb +3 -1
  25. data/lib/unparser/emitter/flow_modifier.rb +63 -0
  26. data/lib/unparser/emitter/if.rb +44 -0
  27. data/lib/unparser/emitter/literal/dynamic.rb +25 -1
  28. data/lib/unparser/emitter/literal/hash.rb +3 -3
  29. data/lib/unparser/emitter/literal/primitive.rb +9 -47
  30. data/lib/unparser/emitter/literal/regexp.rb +5 -16
  31. data/lib/unparser/emitter/module.rb +1 -0
  32. data/lib/unparser/emitter/repetition.rb +52 -0
  33. data/lib/unparser/emitter/resbody.rb +4 -2
  34. data/lib/unparser/emitter/rescue.rb +12 -2
  35. data/lib/unparser/emitter/root.rb +2 -11
  36. data/lib/unparser/emitter/send.rb +19 -2
  37. data/lib/unparser/emitter/send/index.rb +42 -4
  38. data/lib/unparser/emitter/send/unary.rb +4 -0
  39. data/lib/unparser/emitter/undef.rb +1 -3
  40. data/lib/unparser/node_helpers.rb +13 -1
  41. data/lib/unparser/preprocessor.rb +226 -0
  42. data/lib/unparser/strip_helper.rb +23 -0
  43. data/rubyspec.sh +20 -0
  44. data/spec/spec_helper.rb +2 -0
  45. data/spec/unit/unparser_spec.rb +390 -151
  46. data/unparser.gemspec +1 -1
  47. metadata +27 -24
  48. data/lib/unparser/cli/preprocessor.rb +0 -197
  49. data/lib/unparser/emitter/break.rb +0 -27
  50. data/lib/unparser/emitter/next.rb +0 -28
  51. data/lib/unparser/emitter/return.rb +0 -41
@@ -7,8 +7,6 @@ module Unparser
7
7
 
8
8
  handle :undef
9
9
 
10
- children :subject
11
-
12
10
  private
13
11
 
14
12
  # Perform dispatch
@@ -19,7 +17,7 @@ module Unparser
19
17
  #
20
18
  def dispatch
21
19
  write(K_UNDEF, WS)
22
- visit(subject)
20
+ delimited(children)
23
21
  end
24
22
 
25
23
  end # Undef
@@ -11,7 +11,19 @@ module Unparser
11
11
  #
12
12
  # @api private
13
13
  #
14
- def s(type, children = [])
14
+ def s(type, *children)
15
+ Parser::AST::Node.new(type, children)
16
+ end
17
+
18
+ # Helper for building nodes
19
+ #
20
+ # @param [Symbol]
21
+ #
22
+ # @return [Parser::AST::Node]
23
+ #
24
+ # @api private
25
+ #
26
+ def n(type, children = [])
15
27
  Parser::AST::Node.new(type, children)
16
28
  end
17
29
 
@@ -0,0 +1,226 @@
1
+ # encoding: UTF-8
2
+
3
+ module Unparser
4
+ # Preprocessor to normalize AST generated by parser
5
+ class Preprocessor
6
+ include Adamantium::Flat, NodeHelpers, AbstractType, Concord.new(:node), Procto.call(:result)
7
+
8
+ # Return preprocessor result
9
+ #
10
+ # @return [Parser::AST::Node]
11
+ #
12
+ # @api private
13
+ #
14
+ abstract_method :result
15
+
16
+ EMPTY = Parser::AST::Node.new(:empty)
17
+
18
+ # Run preprocessor for node
19
+ #
20
+ # @param [Parser::AST::Node, nil] node
21
+ #
22
+ # @return [Parser::AST::Node, nil]
23
+ #
24
+ # @api private
25
+ #
26
+ def self.run(node)
27
+ return EMPTY if node.nil?
28
+ REGISTRY.fetch(node.type, [Noop]).reduce(node) do |current, processor|
29
+ processor.call(current)
30
+ end
31
+ end
32
+
33
+ REGISTRY = Hash.new { |hash, key| hash[key] = [] }
34
+
35
+ # Register preprocessor
36
+ #
37
+ # @param [Symbol] type
38
+ #
39
+ # @return [undefined]
40
+ #
41
+ # @api private
42
+ #
43
+ def self.register(type)
44
+ REGISTRY[type] << self
45
+ end
46
+ private_class_method :register
47
+
48
+ private
49
+
50
+ # Visit node
51
+ #
52
+ # @param [Parser::AST::Node]
53
+ #
54
+ # @return [undefined]
55
+ #
56
+ # @api private
57
+ #
58
+ def visit(node)
59
+ self.class.run(node)
60
+ end
61
+
62
+ # Return children
63
+ #
64
+ # @return [Array<Parser::AST::Node>]
65
+ #
66
+ # @api private
67
+ #
68
+ def children
69
+ node.children
70
+ end
71
+
72
+ # Return visited children
73
+ #
74
+ # @return [Array<Parser::Ast::Node>]
75
+ #
76
+ # @api private
77
+ #
78
+ def visited_children
79
+ children.map do |node|
80
+ if node.kind_of?(Parser::AST::Node)
81
+ visit(node)
82
+ else
83
+ node
84
+ end
85
+ end
86
+ end
87
+
88
+ # Noop preprocessor that just passes through noode.
89
+ class Noop < self
90
+
91
+ register :int
92
+ register :str
93
+
94
+ # Return preprocessor result
95
+ #
96
+ # @return [Parser::AST::Node]
97
+ #
98
+ # @api private
99
+ #
100
+ def result
101
+ node.updated(nil, visited_children)
102
+ end
103
+
104
+ end # Noop
105
+
106
+ # Preprocessor for dynamic string regexp and xtr nodes. Collapses adjacent string segments into one.
107
+ class CollapseStrChildren < self
108
+
109
+ register :dstr
110
+ register :regexp
111
+ register :xstr
112
+
113
+ # Return preprocessor result
114
+ #
115
+ # @return [Parser::AST::Node]
116
+ #
117
+ # @api private
118
+ #
119
+ def result
120
+ node.updated(nil, collapsed_children)
121
+ end
122
+
123
+ private
124
+
125
+ # Return collapsed children
126
+ #
127
+ # @return [Array<Parser::AST::Node>]
128
+ #
129
+ # @api private
130
+ #
131
+ def collapsed_children
132
+ chunked_children.each_with_object([]) do |(type, nodes), aggregate|
133
+ if type == :str
134
+ aggregate << s(:str, nodes.map { |node| node.children.first }.join)
135
+ else
136
+ aggregate.concat(nodes)
137
+ end
138
+ end
139
+ end
140
+ memoize :collapsed_children
141
+
142
+ # Return chunked children
143
+ #
144
+ # @return [Array<Parser::AST::Node>]
145
+ #
146
+ # @api private
147
+ #
148
+ def chunked_children
149
+ visited_children.chunk(&:type)
150
+ end
151
+
152
+ end # CollapseStrChildren
153
+
154
+ # Preprocessor eliminating unneded dstr nodes
155
+ class CompactDSTR < self
156
+
157
+ register :dstr
158
+
159
+ # Return preprocessor result
160
+ #
161
+ # @return [Parser::AST::Node]
162
+ #
163
+ # @api private
164
+ #
165
+ def result
166
+ if children.all? { |child| child.type == :str }
167
+ node.updated(:str, [children.map { |child| child.children.first }.join])
168
+ else
169
+ node
170
+ end
171
+ end
172
+
173
+ end # CompactDSTR
174
+
175
+ # Preprocessor transforming numeric nodes with infinity as value to round trippable aequivalent.
176
+ class Infinity < self
177
+
178
+ register :float
179
+ register :int
180
+
181
+ NEG_INFINITY = Float::INFINITY - 1
182
+
183
+ # Return preprocessor result
184
+ #
185
+ # @param [Parser::AST::Node]
186
+ #
187
+ # @api pirvate
188
+ #
189
+ def result
190
+ value = node.children.first
191
+ case value
192
+ when Float::INFINITY
193
+ s(:const, s(:const, nil, :Float), :INFINITY)
194
+ when -NEG_INFINITY
195
+ s(:send, s(:const, s(:const, nil, :Float), :INFINITY), :-@)
196
+ else
197
+ node
198
+ end
199
+ end
200
+ end
201
+
202
+ # Preprocessor for begin nodes. Removes begin nodes with one child.
203
+ #
204
+ # These superflownosely currently get generated by unparser.
205
+ #
206
+ class Begin < self
207
+
208
+ register :begin
209
+
210
+ # Return preprocessor result
211
+ #
212
+ # @return [Parser::AST::Node]
213
+ #
214
+ # @api private
215
+ #
216
+ def result
217
+ if children.one?
218
+ visit(children.first)
219
+ else
220
+ Noop.call(node)
221
+ end
222
+ end
223
+
224
+ end # Begin
225
+ end # Preprocessor
226
+ end # Unparser
@@ -0,0 +1,23 @@
1
+ # encoding: UTF-8
2
+
3
+ module Unparser
4
+ # Helpers for stripping source
5
+ module StripHelper
6
+
7
+ INDENT_PATTERN = /^\s*/.freeze
8
+
9
+ # String indentation of source away
10
+ #
11
+ # @param [String] source
12
+ #
13
+ # @return [String]
14
+ #
15
+ # @api private
16
+ #
17
+ def strip(source)
18
+ indent = source.rstrip.scan(INDENT_PATTERN).min_by(&:length)
19
+ source.gsub(/^#{indent}/, '')
20
+ end
21
+
22
+ end # StripHelper
23
+ end # Unparser
data/rubyspec.sh ADDED
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+ exec bundle exec bin/unparser ../rubyspec --fail-fast \
3
+ --ignore '../rubyspec/core/array/pack/{b,h,u}_spec.rb' \
4
+ --ignore '../rubyspec/language/versions/*1.8*' \
5
+ --ignore '../rubyspec/core/array/pack/shared/float.rb' \
6
+ --ignore '../rubyspec/core/array/pack/shared/integer.rb' \
7
+ --ignore '../rubyspec/core/array/pack/{c,m,w}_spec.rb' \
8
+ --ignore '../rubyspec/core/regexp/shared/new.rb' \
9
+ --ignore '../rubyspec/core/regexp/shared/quote.rb' \
10
+ --ignore '../rubyspec/core/encoding/compatible_spec.rb' \
11
+ --ignore '../rubyspec/core/io/readpartial_spec.rb' \
12
+ --ignore '../rubyspec/core/env/element_reference_spec.rb' \
13
+ --ignore '../rubyspec/core/dir/pwd_spec.rb' \
14
+ --ignore '../rubyspec/core/string/casecmp_spec.rb' \
15
+ --ignore '../rubyspec/core/string/unpack/{b,c,h,m,u,w}_spec.rb' \
16
+ --ignore '../rubyspec/core/string/unpack/b_spec.rb' \
17
+ --ignore '../rubyspec/core/string/unpack/shared/float.rb' \
18
+ --ignore '../rubyspec/core/string/unpack/shared/integer.rb' \
19
+ --ignore '../rubyspec/core/symbol/casecmp_spec.rb' \
20
+ $*
data/spec/spec_helper.rb CHANGED
@@ -20,6 +20,8 @@ module SpecHelper
20
20
  end
21
21
 
22
22
  RSpec.configure do |config|
23
+ config.extend(Unparser::StripHelper)
24
+ config.include(Unparser::StripHelper)
23
25
  config.include(SpecHelper)
24
26
  config.extend(SpecHelper)
25
27
  end
@@ -29,6 +29,8 @@ describe Unparser do
29
29
  ast, comments = parser.parse_with_comments(input)
30
30
  generated = Unparser.unparse(ast, comments)
31
31
  generated.should eql(input)
32
+ generated_ast, _ = parser.parse_with_comments(generated)
33
+ expect(ast == generated_ast).to be(true)
32
34
  end
33
35
 
34
36
  def assert_generates_from_string(parser, string, expected)
@@ -74,14 +76,17 @@ describe Unparser do
74
76
  assert_generates s(:int, 1), '1'
75
77
  assert_generates s(:int, -1), '-1'
76
78
  assert_source '1'
79
+ assert_source '++1'
77
80
  assert_generates '0x1', '1'
78
81
  assert_generates '1_000', '1000'
79
82
  assert_generates '1e10', '10000000000.0'
83
+ assert_generates '10e10000000000', 'Float::INFINITY'
84
+ assert_generates '-10e10000000000', '-Float::INFINITY'
80
85
  end
81
86
 
82
87
  context 'string' do
83
88
  assert_generates '?c', '"c"'
84
- assert_source %q("foo" "bar")
89
+ assert_generates %q("foo" "bar"), %q("foobar")
85
90
  assert_generates %q(%Q(foo"#{@bar})), %q("foo\\"#{@bar}")
86
91
  assert_source %q("\"")
87
92
  assert_source %q("foo#{1}bar")
@@ -125,6 +130,7 @@ describe Unparser do
125
130
  assert_source ':foo'
126
131
  assert_source ':"A B"'
127
132
  assert_source ':"A\"B"'
133
+ assert_source ':""'
128
134
  end
129
135
 
130
136
  context 'regexp' do
@@ -169,12 +175,16 @@ describe Unparser do
169
175
  context 'float' do
170
176
  assert_source '-0.1'
171
177
  assert_source '0.1'
178
+ assert_source '0.1'
179
+ assert_generates '10.2e10000000000', 'Float::INFINITY'
180
+ assert_generates '-10.2e10000000000', '-Float::INFINITY'
172
181
  assert_generates s(:float, -0.1), '-0.1'
173
182
  assert_generates s(:float, 0.1), '0.1'
174
183
  end
175
184
 
176
185
  context 'array' do
177
186
  assert_source '[1, 2]'
187
+ assert_source '[1, (), n2]'
178
188
  assert_source '[1]'
179
189
  assert_source '[]'
180
190
  assert_source '[1, *@foo]'
@@ -185,10 +195,12 @@ describe Unparser do
185
195
 
186
196
  context 'hash' do
187
197
  assert_source '{}'
198
+ assert_source '{ () => () }'
188
199
  assert_source '{ 1 => 2 }'
189
200
  assert_source '{ 1 => 2, 3 => 4 }'
190
201
 
191
202
  context 'with symbol keys' do
203
+ assert_source '{ a: (1 rescue(foo)), b: 2 }'
192
204
  assert_source '{ a: 1, b: 2 }'
193
205
  assert_source '{ a: :a }'
194
206
  assert_source '{ :"a b" => 1 }'
@@ -209,11 +221,6 @@ describe Unparser do
209
221
  assert_source '::TOPLEVEL::CONST'
210
222
  end
211
223
 
212
- context 'next' do
213
- assert_source 'next'
214
- assert_source 'next(bar)'
215
- end
216
-
217
224
  context 'retry' do
218
225
  assert_source 'retry'
219
226
  end
@@ -231,8 +238,8 @@ describe Unparser do
231
238
 
232
239
  context 'magic keywords' do
233
240
  assert_generates '__ENCODING__', 'Encoding::UTF_8'
234
- assert_source '__FILE__'
235
- assert_source '__LINE__'
241
+ assert_generates '__FILE__', '"(string)"'
242
+ assert_generates '__LINE__', '1'
236
243
  end
237
244
 
238
245
  context 'assignment' do
@@ -246,51 +253,122 @@ describe Unparser do
246
253
  assert_source '::Foo = ::Bar'
247
254
  end
248
255
 
256
+ context 'lvar assigned from method with same name' do
257
+ assert_source 'foo = foo()'
258
+ end
259
+
260
+ context 'lvar introduction from condition' do
261
+ assert_source 'foo = bar while foo'
262
+ assert_source 'foo = bar until foo'
263
+ assert_source <<-'RUBY'
264
+ foo = exp
265
+ while foo
266
+ foo = bar
267
+ end
268
+ RUBY
269
+
270
+ # Ugly I know. But its correct :D
271
+ #
272
+ # if foo { |pair| }
273
+ # pair = :foo
274
+ # foo
275
+ # end
276
+ assert_source <<-'RUBY'
277
+ if foo do |pair|
278
+ pair
279
+ end
280
+ pair = :foo
281
+ foo
282
+ end
283
+ RUBY
284
+
285
+ assert_source <<-'RUBY'
286
+ while foo
287
+ foo = bar
288
+ end
289
+ RUBY
290
+
291
+ assert_source <<-'RUBY'
292
+ each do |bar|
293
+ while foo
294
+ foo = bar
295
+ end
296
+ end
297
+ RUBY
298
+
299
+ assert_source <<-'RUBY'
300
+ def foo
301
+ foo = bar while foo != baz
302
+ end
303
+ RUBY
304
+
305
+ assert_source <<-'RUBY'
306
+ each do |baz|
307
+ while foo
308
+ foo = bar
309
+ end
310
+ end
311
+ RUBY
312
+
313
+ assert_source <<-'RUBY'
314
+ each do |foo|
315
+ while foo
316
+ foo = bar
317
+ end
318
+ end
319
+ RUBY
320
+ end
321
+
249
322
  context 'multiple' do
250
- assert_source 'a, b = 1, 2'
251
- assert_source 'a, *foo = 1, 2'
252
- assert_source 'a, * = 1, 2'
253
- assert_source '*foo = 1, 2'
254
- assert_source '@a, @b = 1, 2'
255
- assert_source 'a.foo, a.bar = 1, 2'
323
+ assert_source 'a, b = [1, 2]'
324
+ assert_source 'a, *foo = [1, 2]'
325
+ assert_source 'a, * = [1, 2]'
326
+ assert_source '*foo = [1, 2]'
327
+ assert_source '*a = []'
328
+ assert_source '@a, @b = [1, 2]'
329
+ assert_source 'a.foo, a.bar = [1, 2]'
256
330
  assert_source 'a[0, 2]'
257
- assert_source 'a[0], a[1] = 1, 2'
258
- assert_source 'a[*foo], a[1] = 1, 2'
259
- assert_source '@@a, @@b = 1, 2'
260
- assert_source '$a, $b = 1, 2'
331
+ assert_source 'a[0], a[1] = [1, 2]'
332
+ assert_source 'a[*foo], a[1] = [1, 2]'
333
+ assert_source '@@a, @@b = [1, 2]'
334
+ assert_source '$a, $b = [1, 2]'
261
335
  assert_source 'a, b = foo'
262
- assert_source 'a, (b, c) = 1, [2, 3]'
336
+ assert_source 'a, (b, c) = [1, [2, 3]]'
337
+ assert_source 'a, = foo'
263
338
  end
264
339
  end
265
340
 
266
- context 'return' do
267
- assert_source <<-'RUBY'
268
- return
269
- RUBY
270
-
271
- assert_source <<-'RUBY'
272
- return(1)
273
- RUBY
341
+ %w(next return break).each do |keyword|
274
342
 
275
- assert_source <<-'RUBY'
276
- return(1), (2)
277
- RUBY
343
+ context keyword do
344
+ assert_source "#{keyword}"
345
+ assert_source "#{keyword} 1"
346
+ assert_source "#{keyword} 2, 3"
347
+ assert_source "#{keyword} *nil"
348
+ assert_source "#{keyword} *foo, bar"
278
349
 
279
- assert_generates <<-'RUBY', <<-'RUBY'
280
- return(a ? b : c)
281
- RUBY
282
- return(if a
283
- b
284
- else
285
- c
286
- end)
287
- RUBY
288
- end
350
+ assert_generates <<-RUBY, <<-RUBY
351
+ foo do |bar|
352
+ bar =~ // || #{keyword}
353
+ baz
354
+ end
355
+ RUBY
356
+ foo do |bar|
357
+ (bar =~ //) || #{keyword}
358
+ baz
359
+ end
360
+ RUBY
289
361
 
290
- context 'break' do
291
- assert_source 'break'
292
- assert_source 'break(a)'
293
- assert_source 'break(a), (b)'
362
+ assert_generates <<-RUBY, <<-RUBY
363
+ #{keyword}(a ? b : c)
364
+ RUBY
365
+ #{keyword} (if a
366
+ b
367
+ else
368
+ c
369
+ end)
370
+ RUBY
371
+ end
294
372
  end
295
373
 
296
374
  context 'send' do
@@ -303,6 +381,7 @@ describe Unparser do
303
381
  assert_source 'foo(1)'
304
382
  assert_source 'foo(bar)'
305
383
  assert_source 'foo(&block)'
384
+ assert_source 'foo(&(foo || bar))'
306
385
  assert_source 'foo(*arguments)'
307
386
  assert_source 'foo(*arguments)'
308
387
  assert_source <<-'RUBY'
@@ -350,6 +429,33 @@ describe Unparser do
350
429
  end
351
430
  RUBY
352
431
 
432
+ assert_source <<-'RUBY'
433
+ foo.bar do |*a; b|
434
+ end
435
+ RUBY
436
+
437
+ assert_source <<-'RUBY'
438
+ foo.bar do |a; b|
439
+ end
440
+ RUBY
441
+
442
+ assert_source <<-'RUBY'
443
+ foo.bar do |; a, b|
444
+ end
445
+ RUBY
446
+
447
+ assert_source <<-'RUBY'
448
+ foo.bar do |((*))|
449
+ d
450
+ end
451
+ RUBY
452
+
453
+ assert_source <<-'RUBY'
454
+ foo.bar do |(a, (*))|
455
+ d
456
+ end
457
+ RUBY
458
+
353
459
  assert_source <<-'RUBY'
354
460
  foo.bar do |(a, b)|
355
461
  d
@@ -405,6 +511,14 @@ describe Unparser do
405
511
  end.bar
406
512
  RUBY
407
513
 
514
+ assert_source <<-'RUBY'
515
+ case (def foo
516
+ end
517
+ :bar)
518
+ when bar
519
+ end.baz
520
+ RUBY
521
+
408
522
  assert_source <<-'RUBY'
409
523
  case foo
410
524
  when bar
@@ -476,8 +590,8 @@ describe Unparser do
476
590
 
477
591
  assert_source 'foo.bar(&baz)'
478
592
  assert_source 'foo.bar(:baz, &baz)'
479
- assert_source 'foo.bar=(:baz)'
480
- assert_source 'self.foo=(:bar)'
593
+ assert_source 'foo.bar=:baz'
594
+ assert_source 'self.foo=:bar'
481
595
 
482
596
  assert_source 'foo.bar(baz: boz)'
483
597
  assert_source 'foo.bar(foo, "baz" => boz)'
@@ -488,6 +602,11 @@ describe Unparser do
488
602
  context 'begin; end' do
489
603
  assert_generates s(:begin), ''
490
604
 
605
+ assert_source <<-'RUBY'
606
+ begin
607
+ end
608
+ RUBY
609
+
491
610
  assert_source <<-'RUBY'
492
611
  foo
493
612
  bar
@@ -532,6 +651,13 @@ describe Unparser do
532
651
  end
533
652
  RUBY
534
653
 
654
+ assert_source <<-'RUBY'
655
+ begin
656
+ raise(Exception) rescue(foo = bar)
657
+ rescue Exception
658
+ end
659
+ RUBY
660
+
535
661
  assert_source <<-'RUBY'
536
662
  begin
537
663
  foo
@@ -566,6 +692,24 @@ describe Unparser do
566
692
  end
567
693
  RUBY
568
694
 
695
+ assert_source <<-'RUBY'
696
+ class << self
697
+ undef :bar rescue(nil)
698
+ end
699
+ RUBY
700
+
701
+ assert_source <<-'RUBY'
702
+ module Foo
703
+ undef :bar rescue(nil)
704
+ end
705
+ RUBY
706
+
707
+ assert_source <<-'RUBY'
708
+ class Foo
709
+ undef :bar rescue(nil)
710
+ end
711
+ RUBY
712
+
569
713
  assert_source <<-'RUBY'
570
714
  begin
571
715
  rescue Exception => e
@@ -636,36 +780,42 @@ describe Unparser do
636
780
  RUBY
637
781
 
638
782
  assert_source 'foo rescue(bar)'
639
- assert_source 'foo rescue(return(bar))'
640
- assert_source 'x = foo rescue(return(bar))'
783
+ assert_source 'foo rescue(return bar)'
784
+ assert_source 'x = foo rescue(return bar)'
641
785
  end
642
786
 
643
787
  context 'super' do
644
788
  assert_source 'super'
645
789
 
790
+ assert_source 'super()'
791
+ assert_source 'super(a)'
792
+ assert_source 'super(a, b)'
793
+ assert_source 'super(&block)'
794
+ assert_source 'super(a, &block)'
795
+
646
796
  assert_source <<-'RUBY'
647
- super do
797
+ super(a do
648
798
  foo
649
- end
799
+ end)
650
800
  RUBY
651
801
 
652
- assert_source 'super()'
653
-
654
802
  assert_source <<-'RUBY'
655
- super() do
803
+ super do
656
804
  foo
657
805
  end
658
806
  RUBY
659
807
 
660
- assert_source 'super(a)'
661
-
662
808
  assert_source <<-'RUBY'
663
809
  super(a) do
664
810
  foo
665
811
  end
666
812
  RUBY
667
813
 
668
- assert_source 'super(a, b)'
814
+ assert_source <<-'RUBY'
815
+ super() do
816
+ foo
817
+ end
818
+ RUBY
669
819
 
670
820
  assert_source <<-'RUBY'
671
821
  super(a, b) do
@@ -673,12 +823,11 @@ describe Unparser do
673
823
  end
674
824
  RUBY
675
825
 
676
- assert_source 'super(&block)'
677
- assert_source 'super(a, &block)'
678
826
  end
679
827
 
680
828
  context 'undef' do
681
829
  assert_source 'undef :foo'
830
+ assert_source 'undef :foo, :bar'
682
831
  end
683
832
 
684
833
  context 'BEGIN' do
@@ -758,6 +907,30 @@ describe Unparser do
758
907
  if foo
759
908
  end
760
909
  RUBY
910
+
911
+ assert_source <<-'RUBY'
912
+ foo = bar if foo
913
+ RUBY
914
+
915
+ assert_source <<-'RUBY'
916
+ foo = bar unless foo
917
+ RUBY
918
+
919
+ assert_source <<-'RUBY'
920
+ def foo(*foo)
921
+ unless foo
922
+ foo = bar
923
+ end
924
+ end
925
+ RUBY
926
+
927
+ assert_source <<-'RUBY'
928
+ each do |foo|
929
+ unless foo
930
+ foo = bar
931
+ end
932
+ end
933
+ RUBY
761
934
  end
762
935
 
763
936
  context 'def' do
@@ -784,6 +957,14 @@ describe Unparser do
784
957
  end
785
958
  RUBY
786
959
 
960
+ assert_source <<-'RUBY'
961
+ begin
962
+ foo
963
+ ensure
964
+ bar rescue(nil)
965
+ end
966
+ RUBY
967
+
787
968
  assert_source <<-'RUBY'
788
969
  def foo
789
970
  bar
@@ -820,6 +1001,18 @@ describe Unparser do
820
1001
  end
821
1002
  RUBY
822
1003
 
1004
+ assert_source <<-'RUBY'
1005
+ def foo(bar = ())
1006
+ bar
1007
+ end
1008
+ RUBY
1009
+
1010
+ assert_source <<-'RUBY'
1011
+ def foo(bar = (baz
1012
+ nil))
1013
+ end
1014
+ RUBY
1015
+
823
1016
  assert_source <<-'RUBY'
824
1017
  def foo(bar = true)
825
1018
  bar
@@ -902,6 +1095,43 @@ describe Unparser do
902
1095
  baz
903
1096
  end
904
1097
  RUBY
1098
+
1099
+ assert_source <<-'RUBY'
1100
+ def (foo do |bar|
1101
+ end).bar
1102
+ bar
1103
+ end
1104
+ RUBY
1105
+
1106
+ assert_source <<-'RUBY'
1107
+ def (foo(1)).bar
1108
+ bar
1109
+ end
1110
+ RUBY
1111
+
1112
+ assert_source <<-'RUBY'
1113
+ def (Foo::Bar.baz).bar
1114
+ baz
1115
+ end
1116
+ RUBY
1117
+
1118
+ assert_source <<-'RUBY'
1119
+ def (Foo::Bar).bar
1120
+ baz
1121
+ end
1122
+ RUBY
1123
+
1124
+ assert_source <<-'RUBY'
1125
+ def Foo.bar
1126
+ baz
1127
+ end
1128
+ RUBY
1129
+
1130
+ assert_source <<-'RUBY'
1131
+ def foo.bar
1132
+ baz
1133
+ end
1134
+ RUBY
905
1135
  end
906
1136
 
907
1137
  context 'on singleton' do
@@ -934,7 +1164,7 @@ describe Unparser do
934
1164
  context 'class' do
935
1165
  assert_source <<-'RUBY'
936
1166
  class TestClass
937
- end # TestClass
1167
+ end
938
1168
  RUBY
939
1169
 
940
1170
  assert_source <<-'RUBY'
@@ -950,22 +1180,22 @@ describe Unparser do
950
1180
 
951
1181
  assert_source <<-'RUBY'
952
1182
  class SomeNameSpace::TestClass
953
- end # SomeNameSpace::TestClass
1183
+ end
954
1184
  RUBY
955
1185
 
956
1186
  assert_source <<-'RUBY'
957
1187
  class Some::Name::Space::TestClass
958
- end # Some::Name::Space::TestClass
1188
+ end
959
1189
  RUBY
960
1190
 
961
1191
  assert_source <<-'RUBY'
962
1192
  class TestClass < Object
963
- end # TestClass
1193
+ end
964
1194
  RUBY
965
1195
 
966
1196
  assert_source <<-'RUBY'
967
1197
  class TestClass < SomeNameSpace::Object
968
- end # TestClass
1198
+ end
969
1199
  RUBY
970
1200
 
971
1201
  assert_source <<-'RUBY'
@@ -973,12 +1203,12 @@ describe Unparser do
973
1203
  def foo
974
1204
  :bar
975
1205
  end
976
- end # TestClass
1206
+ end
977
1207
  RUBY
978
1208
 
979
1209
  assert_source <<-'RUBY'
980
1210
  class ::TestClass
981
- end # ::TestClass
1211
+ end
982
1212
  RUBY
983
1213
  end
984
1214
 
@@ -986,17 +1216,17 @@ describe Unparser do
986
1216
 
987
1217
  assert_source <<-'RUBY'
988
1218
  module TestModule
989
- end # TestModule
1219
+ end
990
1220
  RUBY
991
1221
 
992
1222
  assert_source <<-'RUBY'
993
1223
  module SomeNameSpace::TestModule
994
- end # SomeNameSpace::TestModule
1224
+ end
995
1225
  RUBY
996
1226
 
997
1227
  assert_source <<-'RUBY'
998
1228
  module Some::Name::Space::TestModule
999
- end # Some::Name::Space::TestModule
1229
+ end
1000
1230
  RUBY
1001
1231
 
1002
1232
  assert_source <<-'RUBY'
@@ -1004,7 +1234,7 @@ describe Unparser do
1004
1234
  def foo
1005
1235
  :bar
1006
1236
  end
1007
- end # TestModule
1237
+ end
1008
1238
  RUBY
1009
1239
 
1010
1240
  end
@@ -1019,6 +1249,8 @@ describe Unparser do
1019
1249
  context 'element assignment' do
1020
1250
  assert_source 'array[index] = value'
1021
1251
  assert_source 'array[*index] = value'
1252
+ assert_source 'array[a, b] = value'
1253
+ assert_source 'array.[]=()'
1022
1254
 
1023
1255
  %w(+ - * / % & | || &&).each do |operator|
1024
1256
  context "with #{operator}" do
@@ -1036,6 +1268,10 @@ describe Unparser do
1036
1268
  assert_source <<-'RUBY'
1037
1269
  defined?(Foo)
1038
1270
  RUBY
1271
+
1272
+ assert_source <<-'RUBY'
1273
+ defined?((a, b = [1, 2]))
1274
+ RUBY
1039
1275
  end
1040
1276
  end
1041
1277
 
@@ -1064,7 +1300,8 @@ describe Unparser do
1064
1300
 
1065
1301
  context 'binary operator methods' do
1066
1302
  %w(+ - * / & | << >> == === != <= < <=> > >= =~ !~ ^ **).each do |operator|
1067
- assert_source "1 #{operator} 2"
1303
+ assert_source "(-1) #{operator} 2"
1304
+ assert_source "(-1.2) #{operator} 2"
1068
1305
  assert_source "left.#{operator}(*foo)"
1069
1306
  assert_source "left.#{operator}(a, b)"
1070
1307
  assert_source "self #{operator} b"
@@ -1082,15 +1319,18 @@ describe Unparser do
1082
1319
  end
1083
1320
 
1084
1321
  context 'binary operator' do
1085
- assert_source 'a || (break(foo))'
1086
- assert_source '(break(foo)) || a'
1322
+ assert_source 'a || (return foo)'
1323
+ assert_source '(return foo) || a'
1324
+ assert_source 'a || (break foo)'
1325
+ assert_source '(break foo) || a'
1087
1326
  assert_source '(a || b).foo'
1088
1327
  assert_source 'a || (b || c)'
1089
1328
  end
1090
1329
 
1091
1330
  { or: :'||', and: :'&&' }.each do |word, symbol|
1092
- assert_generates "a #{word} break foo", "a #{symbol} (break(foo))"
1093
- assert_generates "a #{word} next foo", "a #{symbol} (next(foo))"
1331
+ assert_generates "a #{word} return foo", "a #{symbol} (return foo)"
1332
+ assert_generates "a #{word} break foo", "a #{symbol} (break foo)"
1333
+ assert_generates "a #{word} next foo", "a #{symbol} (next foo)"
1094
1334
  end
1095
1335
 
1096
1336
  context 'expansion of shortcuts' do
@@ -1199,12 +1439,13 @@ describe Unparser do
1199
1439
 
1200
1440
  context 'unary operators' do
1201
1441
  assert_source '!1'
1202
- assert_source '!!1'
1203
- assert_source '!!(foo || bar)'
1442
+ assert_source '!(!1)'
1443
+ assert_source '!(!(foo || bar))'
1204
1444
  assert_source '!(!1).baz'
1205
1445
  assert_source '~a'
1206
1446
  assert_source '-a'
1207
1447
  assert_source '+a'
1448
+ assert_source '-(-a).foo'
1208
1449
  end
1209
1450
 
1210
1451
  context 'loop' do
@@ -1263,84 +1504,82 @@ describe Unparser do
1263
1504
  RUBY
1264
1505
  end
1265
1506
 
1266
- context 'comments' do
1267
- assert_source <<-'RUBY'
1268
- # comment before
1269
- a_line_of_code
1270
- RUBY
1271
-
1272
- assert_source <<-'RUBY'
1273
- a_line_of_code # comment after
1274
- RUBY
1275
-
1276
- assert_source <<-'RUBY'
1277
- nested do # first
1278
- # second
1279
- something # comment
1280
- # another
1281
- end
1282
- # last
1283
- RUBY
1284
-
1285
- assert_generates <<-'RUBY', <<-'RUBY'
1286
- foo if bar
1287
- # comment
1288
- RUBY
1289
- if bar
1290
- foo
1291
- end
1292
- # comment
1293
- RUBY
1507
+ assert_source <<-'RUBY'
1508
+ # comment before
1509
+ a_line_of_code
1510
+ RUBY
1294
1511
 
1295
- assert_source <<-'RUBY'
1296
- def noop
1297
- # do nothing
1298
- end
1299
- RUBY
1512
+ assert_source <<-'RUBY'
1513
+ a_line_of_code # comment after
1514
+ RUBY
1300
1515
 
1301
- assert_source <<-'RUBY'
1302
- =begin
1303
- block comment
1304
- =end
1305
- nested do
1306
- =begin
1307
- another block comment
1308
- =end
1309
- something
1310
- =begin
1311
- last block comment
1312
- =end
1313
- end
1314
- RUBY
1315
-
1316
- assert_generates(<<-'RUBY', <<-'RUBY')
1317
- 1 + # first
1318
- 2 # second
1319
- RUBY
1320
- 1 + 2 # first # second
1321
- RUBY
1322
-
1323
- assert_generates(<<-'RUBY', <<-'RUBY')
1324
- 1 +
1325
- # first
1326
- 2 # second
1327
- RUBY
1328
- 1 + 2 # first # second
1329
- RUBY
1516
+ assert_source <<-'RUBY'
1517
+ nested do # first
1518
+ # second
1519
+ something # comment
1520
+ # another
1521
+ end
1522
+ # last
1523
+ RUBY
1524
+
1525
+ assert_generates <<-'RUBY', <<-'RUBY'
1526
+ foo if bar
1527
+ # comment
1528
+ RUBY
1529
+ if bar
1530
+ foo
1531
+ end
1532
+ # comment
1533
+ RUBY
1330
1534
 
1331
- assert_generates(<<-'RUBY', <<-'RUBY')
1332
- 1 +
1333
- =begin
1334
- block comment
1335
- =end
1336
- 2
1337
- RUBY
1338
- 1 + 2
1339
- =begin
1340
- block comment
1341
- =end
1342
- RUBY
1535
+ assert_source <<-'RUBY'
1536
+ def noop
1537
+ # do nothing
1538
+ end
1539
+ RUBY
1540
+
1541
+ assert_source <<-'RUBY'
1542
+ =begin
1543
+ block comment
1544
+ =end
1545
+ nested do
1546
+ =begin
1547
+ another block comment
1548
+ =end
1549
+ something
1550
+ =begin
1551
+ last block comment
1552
+ =end
1553
+ end
1554
+ RUBY
1555
+
1556
+ assert_generates(<<-'RUBY', <<-'RUBY')
1557
+ 1 + # first
1558
+ 2 # second
1559
+ RUBY
1560
+ 1 + 2 # first # second
1561
+ RUBY
1562
+
1563
+ assert_generates(<<-'RUBY', <<-'RUBY')
1564
+ 1 +
1565
+ # first
1566
+ 2 # second
1567
+ RUBY
1568
+ 1 + 2 # first # second
1569
+ RUBY
1570
+
1571
+ assert_generates(<<-'RUBY', <<-'RUBY')
1572
+ 1 +
1573
+ =begin
1574
+ block comment
1575
+ =end
1576
+ 2
1577
+ RUBY
1578
+ 1 + 2
1579
+ =begin
1580
+ block comment
1581
+ =end
1582
+ RUBY
1343
1583
 
1344
- end
1345
1584
  end
1346
1585
  end