unparser 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/.travis.yml +3 -0
- data/Changelog.md +4 -0
- data/README.md +4 -2
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +24 -19
- data/config/rubocop.yml +2 -3
- data/lib/unparser.rb +8 -22
- data/lib/unparser/ast.rb +232 -0
- data/lib/unparser/ast/local_variable_scope.rb +198 -0
- data/lib/unparser/cli.rb +41 -24
- data/lib/unparser/cli/differ.rb +38 -16
- data/lib/unparser/cli/source.rb +46 -17
- data/lib/unparser/constants.rb +23 -6
- data/lib/unparser/emitter.rb +32 -0
- data/lib/unparser/emitter/argument.rb +30 -4
- data/lib/unparser/emitter/assignment.rb +12 -1
- data/lib/unparser/emitter/begin.rb +23 -2
- data/lib/unparser/emitter/case.rb +1 -1
- data/lib/unparser/emitter/class.rb +1 -0
- data/lib/unparser/emitter/def.rb +28 -1
- data/lib/unparser/emitter/defined.rb +3 -1
- data/lib/unparser/emitter/flow_modifier.rb +63 -0
- data/lib/unparser/emitter/if.rb +44 -0
- data/lib/unparser/emitter/literal/dynamic.rb +25 -1
- data/lib/unparser/emitter/literal/hash.rb +3 -3
- data/lib/unparser/emitter/literal/primitive.rb +9 -47
- data/lib/unparser/emitter/literal/regexp.rb +5 -16
- data/lib/unparser/emitter/module.rb +1 -0
- data/lib/unparser/emitter/repetition.rb +52 -0
- data/lib/unparser/emitter/resbody.rb +4 -2
- data/lib/unparser/emitter/rescue.rb +12 -2
- data/lib/unparser/emitter/root.rb +2 -11
- data/lib/unparser/emitter/send.rb +19 -2
- data/lib/unparser/emitter/send/index.rb +42 -4
- data/lib/unparser/emitter/send/unary.rb +4 -0
- data/lib/unparser/emitter/undef.rb +1 -3
- data/lib/unparser/node_helpers.rb +13 -1
- data/lib/unparser/preprocessor.rb +226 -0
- data/lib/unparser/strip_helper.rb +23 -0
- data/rubyspec.sh +20 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/unparser_spec.rb +390 -151
- data/unparser.gemspec +1 -1
- metadata +27 -24
- data/lib/unparser/cli/preprocessor.rb +0 -197
- data/lib/unparser/emitter/break.rb +0 -27
- data/lib/unparser/emitter/next.rb +0 -28
- data/lib/unparser/emitter/return.rb +0 -41
@@ -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
data/spec/unit/unparser_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
235
|
-
|
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 '
|
255
|
-
assert_source 'a
|
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
|
-
|
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
|
-
|
276
|
-
|
277
|
-
|
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
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
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
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
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
|
480
|
-
assert_source 'self.foo
|
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
|
640
|
-
assert_source 'x = foo rescue(return
|
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
|
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 '
|
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
|
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
|
1183
|
+
end
|
954
1184
|
RUBY
|
955
1185
|
|
956
1186
|
assert_source <<-'RUBY'
|
957
1187
|
class Some::Name::Space::TestClass
|
958
|
-
end
|
1188
|
+
end
|
959
1189
|
RUBY
|
960
1190
|
|
961
1191
|
assert_source <<-'RUBY'
|
962
1192
|
class TestClass < Object
|
963
|
-
end
|
1193
|
+
end
|
964
1194
|
RUBY
|
965
1195
|
|
966
1196
|
assert_source <<-'RUBY'
|
967
1197
|
class TestClass < SomeNameSpace::Object
|
968
|
-
end
|
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
|
1206
|
+
end
|
977
1207
|
RUBY
|
978
1208
|
|
979
1209
|
assert_source <<-'RUBY'
|
980
1210
|
class ::TestClass
|
981
|
-
end
|
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
|
1219
|
+
end
|
990
1220
|
RUBY
|
991
1221
|
|
992
1222
|
assert_source <<-'RUBY'
|
993
1223
|
module SomeNameSpace::TestModule
|
994
|
-
end
|
1224
|
+
end
|
995
1225
|
RUBY
|
996
1226
|
|
997
1227
|
assert_source <<-'RUBY'
|
998
1228
|
module Some::Name::Space::TestModule
|
999
|
-
end
|
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
|
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 || (
|
1086
|
-
assert_source '(
|
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}
|
1093
|
-
assert_generates "a #{word}
|
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 '
|
1203
|
-
assert_source '
|
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
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
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
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
end
|
1299
|
-
RUBY
|
1512
|
+
assert_source <<-'RUBY'
|
1513
|
+
a_line_of_code # comment after
|
1514
|
+
RUBY
|
1300
1515
|
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
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
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
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
|