unparser 0.0.1
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 +7 -0
- data/.circle.yml +4 -0
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.travis.yml +16 -0
- data/Changelog.md +3 -0
- data/Gemfile +6 -0
- data/Gemfile.devtools +60 -0
- data/Guardfile +18 -0
- data/README.md +41 -0
- data/Rakefile +24 -0
- data/TODO +1 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/mutant.yml +3 -0
- data/config/reek.yml +107 -0
- data/config/yardstick.yml +2 -0
- data/lib/unparser/buffer.rb +93 -0
- data/lib/unparser/constants.rb +87 -0
- data/lib/unparser/emitter/alias.rb +27 -0
- data/lib/unparser/emitter/argument.rb +154 -0
- data/lib/unparser/emitter/assignment.rb +140 -0
- data/lib/unparser/emitter/begin.rb +179 -0
- data/lib/unparser/emitter/binary.rb +52 -0
- data/lib/unparser/emitter/block.rb +53 -0
- data/lib/unparser/emitter/break.rb +28 -0
- data/lib/unparser/emitter/case.rb +97 -0
- data/lib/unparser/emitter/cbase.rb +22 -0
- data/lib/unparser/emitter/class.rb +72 -0
- data/lib/unparser/emitter/def.rb +107 -0
- data/lib/unparser/emitter/defined.rb +27 -0
- data/lib/unparser/emitter/for.rb +50 -0
- data/lib/unparser/emitter/hookexe.rb +42 -0
- data/lib/unparser/emitter/if.rb +85 -0
- data/lib/unparser/emitter/literal/composed.rb +64 -0
- data/lib/unparser/emitter/literal/dynamic.rb +54 -0
- data/lib/unparser/emitter/literal/dynamic_body.rb +109 -0
- data/lib/unparser/emitter/literal/execute_string.rb +38 -0
- data/lib/unparser/emitter/literal/primitive.rb +49 -0
- data/lib/unparser/emitter/literal/range.rb +33 -0
- data/lib/unparser/emitter/literal/regexp.rb +96 -0
- data/lib/unparser/emitter/literal/singleton.rb +24 -0
- data/lib/unparser/emitter/literal.rb +7 -0
- data/lib/unparser/emitter/module.rb +37 -0
- data/lib/unparser/emitter/next.rb +22 -0
- data/lib/unparser/emitter/not.rb +25 -0
- data/lib/unparser/emitter/op_assign.rb +63 -0
- data/lib/unparser/emitter/redo.rb +22 -0
- data/lib/unparser/emitter/repetition.rb +33 -0
- data/lib/unparser/emitter/retry.rb +22 -0
- data/lib/unparser/emitter/return.rb +38 -0
- data/lib/unparser/emitter/root.rb +7 -0
- data/lib/unparser/emitter/send/binary.rb +100 -0
- data/lib/unparser/emitter/send/index.rb +82 -0
- data/lib/unparser/emitter/send/unary.rb +29 -0
- data/lib/unparser/emitter/send.rb +273 -0
- data/lib/unparser/emitter/splat.rb +24 -0
- data/lib/unparser/emitter/super.rb +46 -0
- data/lib/unparser/emitter/undef.rb +25 -0
- data/lib/unparser/emitter/variable.rb +83 -0
- data/lib/unparser/emitter/yield.rb +28 -0
- data/lib/unparser/emitter.rb +308 -0
- data/lib/unparser.rb +87 -0
- data/spec/integration/unparser/spike_spec.rb +914 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/unit/unparser/buffer/append_spec.rb +23 -0
- data/spec/unit/unparser/buffer/content_spec.rb +38 -0
- data/spec/unit/unparser/buffer/indent_spec.rb +18 -0
- data/spec/unit/unparser/buffer/nl_spec.rb +16 -0
- data/spec/unit/unparser/buffer/unindent_spec.rb +18 -0
- data/spec/unit/unparser/class_methods/unparse_spec.rb +16 -0
- data/spec/unit/unparser/emitter/class_methods/handle_spec.rb +17 -0
- data/spec/unit/unparser/emitter/class_methods/visit_spec.rb +37 -0
- data/spec/unit/unparser/emitter/source_map/class_methods/emit_spec.rb +20 -0
- data/unparser.gemspec +24 -0
- metadata +201 -0
@@ -0,0 +1,273 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
# Emitter for send
|
4
|
+
class Send < self
|
5
|
+
|
6
|
+
handle :send
|
7
|
+
|
8
|
+
INDEX_PARENS = IceNine.deep_freeze(%w([ ]))
|
9
|
+
NORMAL_PARENS = IceNine.deep_freeze(%w[( )])
|
10
|
+
|
11
|
+
INDEX_REFERENCE = '[]'.freeze
|
12
|
+
INDEX_ASSIGN = '[]='.freeze
|
13
|
+
ASSIGN_SUFFIX = '='.freeze
|
14
|
+
|
15
|
+
AMBIGOUS = [:irange, :erange].to_set.freeze
|
16
|
+
|
17
|
+
# Tell node needs begin
|
18
|
+
#
|
19
|
+
# @return [true]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
#
|
23
|
+
def needs_begin?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Perform dispatch
|
30
|
+
#
|
31
|
+
# @return [undefined]
|
32
|
+
#
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
def dispatch
|
36
|
+
case selector
|
37
|
+
when INDEX_REFERENCE
|
38
|
+
run(Index::Reference)
|
39
|
+
when INDEX_ASSIGN
|
40
|
+
run(Index::Assign)
|
41
|
+
else
|
42
|
+
non_index_dispatch
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Emit unambiguous receiver
|
47
|
+
#
|
48
|
+
# @return [undefined]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
def emit_unambiguous_receiver
|
53
|
+
receiver = effective_receiver
|
54
|
+
if AMBIGOUS.include?(receiver.type) or binary_receiver?
|
55
|
+
parentheses { visit(receiver) }
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
visit(receiver)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return effective receiver
|
63
|
+
#
|
64
|
+
# @return [Parser::AST::Node]
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
#
|
68
|
+
def effective_receiver
|
69
|
+
receiver = first_child
|
70
|
+
children = receiver.children
|
71
|
+
if receiver.type == :begin && children.length == 1
|
72
|
+
receiver = children.first
|
73
|
+
end
|
74
|
+
receiver
|
75
|
+
end
|
76
|
+
|
77
|
+
# Test for binary receiver
|
78
|
+
#
|
79
|
+
# @return [true]
|
80
|
+
# if receiver is a binary operation implemented by a method
|
81
|
+
#
|
82
|
+
# @return [false]
|
83
|
+
# otherwise
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
#
|
87
|
+
def binary_receiver?
|
88
|
+
receiver = effective_receiver
|
89
|
+
case receiver.type
|
90
|
+
when :or_asgn, :and_asgn
|
91
|
+
true
|
92
|
+
when :send
|
93
|
+
BINARY_OPERATORS.include?(receiver.children[1])
|
94
|
+
else
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Delegate to emitter
|
100
|
+
#
|
101
|
+
# @param [Class:Emitter] emitter
|
102
|
+
#
|
103
|
+
# @return [undefined]
|
104
|
+
#
|
105
|
+
# @api private
|
106
|
+
#
|
107
|
+
def run(emitter)
|
108
|
+
emitter.emit(node, buffer, self)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Perform non index dispatch
|
112
|
+
#
|
113
|
+
# @return [undefined]
|
114
|
+
#
|
115
|
+
# @api private
|
116
|
+
#
|
117
|
+
def non_index_dispatch
|
118
|
+
if binary?
|
119
|
+
run(Binary)
|
120
|
+
return
|
121
|
+
elsif unary?
|
122
|
+
run(Unary)
|
123
|
+
return
|
124
|
+
end
|
125
|
+
regular_dispatch
|
126
|
+
end
|
127
|
+
|
128
|
+
# Perform regular dispatch
|
129
|
+
#
|
130
|
+
# @return [undefined]
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
#
|
134
|
+
def regular_dispatch
|
135
|
+
emit_receiver
|
136
|
+
emit_selector
|
137
|
+
emit_arguments
|
138
|
+
end
|
139
|
+
|
140
|
+
# Return receiver
|
141
|
+
#
|
142
|
+
# @return [Parser::AST::Node]
|
143
|
+
#
|
144
|
+
# @api private
|
145
|
+
#
|
146
|
+
def emit_receiver
|
147
|
+
return unless first_child
|
148
|
+
emit_unambiguous_receiver
|
149
|
+
write(O_DOT)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Test for unary operator implemented as method
|
153
|
+
#
|
154
|
+
# @return [true]
|
155
|
+
# if node is a unary operator
|
156
|
+
#
|
157
|
+
# @return [false]
|
158
|
+
# otherwise
|
159
|
+
#
|
160
|
+
# @api private
|
161
|
+
#
|
162
|
+
def unary?
|
163
|
+
UNARY_OPERATORS.include?(children[1])
|
164
|
+
end
|
165
|
+
|
166
|
+
# Test for binary operator implemented as method
|
167
|
+
#
|
168
|
+
# @return [true]
|
169
|
+
# if node is a binary operator
|
170
|
+
#
|
171
|
+
# @return [false]
|
172
|
+
# otherwise
|
173
|
+
#
|
174
|
+
# @api private
|
175
|
+
#
|
176
|
+
def binary?
|
177
|
+
BINARY_OPERATORS.include?(children[1])
|
178
|
+
end
|
179
|
+
|
180
|
+
# Emit selector
|
181
|
+
#
|
182
|
+
# @return [undefined]
|
183
|
+
#
|
184
|
+
# @api private
|
185
|
+
#
|
186
|
+
def emit_selector
|
187
|
+
name = selector
|
188
|
+
if mlhs?
|
189
|
+
name = name[0..-2]
|
190
|
+
end
|
191
|
+
write(name)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Test for mlhs
|
195
|
+
#
|
196
|
+
# @return [true]
|
197
|
+
# if node is within an mlhs
|
198
|
+
#
|
199
|
+
# @return [false]
|
200
|
+
# otherwise
|
201
|
+
#
|
202
|
+
# @api private
|
203
|
+
#
|
204
|
+
def mlhs?
|
205
|
+
assignment? && !arguments?
|
206
|
+
end
|
207
|
+
|
208
|
+
# Test for assigment
|
209
|
+
#
|
210
|
+
# @return [true]
|
211
|
+
# if node represents attribute / element assignment
|
212
|
+
#
|
213
|
+
# @return [false]
|
214
|
+
# otherwise
|
215
|
+
#
|
216
|
+
# @api private
|
217
|
+
#
|
218
|
+
def assignment?
|
219
|
+
selector[-1] == ASSIGN_SUFFIX
|
220
|
+
end
|
221
|
+
|
222
|
+
# Return selector
|
223
|
+
#
|
224
|
+
# @return [String]
|
225
|
+
#
|
226
|
+
# @api private
|
227
|
+
#
|
228
|
+
def selector
|
229
|
+
children[1].to_s
|
230
|
+
end
|
231
|
+
memoize :selector
|
232
|
+
|
233
|
+
# Test for empty arguments
|
234
|
+
#
|
235
|
+
# @return [true]
|
236
|
+
# if arguments are empty
|
237
|
+
#
|
238
|
+
# @return [false]
|
239
|
+
# otherwise
|
240
|
+
#
|
241
|
+
# @api private
|
242
|
+
#
|
243
|
+
def arguments?
|
244
|
+
arguments.any?
|
245
|
+
end
|
246
|
+
|
247
|
+
# Return argument nodes
|
248
|
+
#
|
249
|
+
# @return [Array<Parser::AST::Node>]
|
250
|
+
#
|
251
|
+
# @api private
|
252
|
+
#
|
253
|
+
def arguments
|
254
|
+
children[2..-1]
|
255
|
+
end
|
256
|
+
|
257
|
+
# Emit arguments
|
258
|
+
#
|
259
|
+
# @return [undefined]
|
260
|
+
#
|
261
|
+
# @api private
|
262
|
+
#
|
263
|
+
def emit_arguments
|
264
|
+
args = arguments
|
265
|
+
return if args.empty?
|
266
|
+
parentheses do
|
267
|
+
delimited(args)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
end # Send
|
272
|
+
end # Emitter
|
273
|
+
end # Unparser
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
# Emitter for splats
|
4
|
+
class Splat < self
|
5
|
+
|
6
|
+
handle :splat
|
7
|
+
|
8
|
+
children :subject
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# Perform dispatch
|
13
|
+
#
|
14
|
+
# @return [undefined]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
def dispatch
|
19
|
+
write(O_SPLAT)
|
20
|
+
visit(subject) if subject
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end # Unparser
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
|
4
|
+
# Emitter for zsuper nodes
|
5
|
+
class ZSuper < self
|
6
|
+
|
7
|
+
handle :zsuper
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Perform dispatch
|
12
|
+
#
|
13
|
+
# @return [undefined]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
def dispatch
|
18
|
+
write(K_SUPER)
|
19
|
+
end
|
20
|
+
|
21
|
+
end # ZSuper
|
22
|
+
|
23
|
+
# Emitter for super nodes
|
24
|
+
class Super < self
|
25
|
+
|
26
|
+
handle :super
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Perform dispatch
|
31
|
+
#
|
32
|
+
# @return [undefined]
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
#
|
36
|
+
def dispatch
|
37
|
+
write(K_SUPER)
|
38
|
+
parentheses do
|
39
|
+
delimited(children)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end # Super
|
44
|
+
|
45
|
+
end # Emitter
|
46
|
+
end # Unparser
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
# Emitter for undef nodes
|
4
|
+
class Undef < self
|
5
|
+
|
6
|
+
handle :undef
|
7
|
+
|
8
|
+
children :subject
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# Perform dispatch
|
13
|
+
#
|
14
|
+
# @return [undefined]
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
def dispatch
|
19
|
+
write(K_UNDEF, WS)
|
20
|
+
visit(subject)
|
21
|
+
end
|
22
|
+
|
23
|
+
end # Undef
|
24
|
+
end # Emitter
|
25
|
+
end # Unparser
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
|
4
|
+
# Emitter for various variable accesses
|
5
|
+
class Variable < self
|
6
|
+
|
7
|
+
handle :ivar, :lvar, :cvar, :gvar, :back_ref
|
8
|
+
|
9
|
+
children :name
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Perform dispatch
|
14
|
+
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def dispatch
|
20
|
+
write(name.to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
end # Access
|
24
|
+
|
25
|
+
# Emitter for constant access
|
26
|
+
class Const < self
|
27
|
+
|
28
|
+
handle :const
|
29
|
+
|
30
|
+
children :parent, :name
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Perform dispatch
|
35
|
+
#
|
36
|
+
# @return [undefined]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
#
|
40
|
+
def dispatch
|
41
|
+
emit_parent
|
42
|
+
write(name.to_s)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Emit parent
|
46
|
+
#
|
47
|
+
# @return [undefined]
|
48
|
+
#
|
49
|
+
# @api private
|
50
|
+
#
|
51
|
+
def emit_parent
|
52
|
+
return unless parent
|
53
|
+
visit(parent)
|
54
|
+
if parent.type != :cbase
|
55
|
+
write(O_DCL)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Emitter for nth_ref nodes (regexp captures)
|
61
|
+
class NthRef < self
|
62
|
+
PREFIX = '$'.freeze
|
63
|
+
handle :nth_ref
|
64
|
+
|
65
|
+
children :name
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Perform dispatch
|
70
|
+
#
|
71
|
+
# @return [undefined]
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
def dispatch
|
76
|
+
write(PREFIX)
|
77
|
+
write(name.to_s)
|
78
|
+
end
|
79
|
+
|
80
|
+
end # NthRef
|
81
|
+
|
82
|
+
end # Emitter
|
83
|
+
end # Unparser
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
|
4
|
+
# Emitter for yield node
|
5
|
+
class Yield < self
|
6
|
+
|
7
|
+
handle :yield
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# Perform dispatch
|
12
|
+
#
|
13
|
+
# @return [undefined]
|
14
|
+
#
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
def dispatch
|
18
|
+
write(K_YIELD)
|
19
|
+
return if children.empty?
|
20
|
+
parentheses do
|
21
|
+
delimited(children)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Yield
|
26
|
+
|
27
|
+
end # Emitter
|
28
|
+
end # Unparser
|