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