unparser 0.1.7 → 0.1.8

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/.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