unparser 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +6 -0
- data/circle.yml +1 -1
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +1 -0
- data/lib/unparser/ast.rb +1 -1
- data/lib/unparser/ast/local_variable_scope.rb +1 -1
- data/lib/unparser/cli/differ.rb +1 -1
- data/lib/unparser/cli/source.rb +2 -0
- data/lib/unparser/constants.rb +0 -11
- data/lib/unparser/dsl.rb +1 -1
- data/lib/unparser/emitter.rb +41 -13
- data/lib/unparser/emitter/argument.rb +22 -34
- data/lib/unparser/emitter/assignment.rb +29 -6
- data/lib/unparser/emitter/begin.rb +10 -8
- data/lib/unparser/emitter/binary.rb +3 -12
- data/lib/unparser/emitter/block.rb +1 -0
- data/lib/unparser/emitter/case.rb +4 -2
- data/lib/unparser/emitter/cbase.rb +1 -0
- data/lib/unparser/emitter/class.rb +2 -1
- data/lib/unparser/emitter/def.rb +1 -1
- data/lib/unparser/emitter/defined.rb +2 -1
- data/lib/unparser/emitter/flipflop.rb +3 -2
- data/lib/unparser/emitter/flow_modifier.rb +22 -5
- data/lib/unparser/emitter/for.rb +2 -1
- data/lib/unparser/emitter/if.rb +10 -3
- data/lib/unparser/emitter/literal.rb +1 -0
- data/lib/unparser/emitter/literal/dynamic_body.rb +1 -1
- data/lib/unparser/emitter/literal/hash.rb +1 -1
- data/lib/unparser/emitter/literal/primitive.rb +83 -1
- data/lib/unparser/emitter/literal/range.rb +3 -2
- data/lib/unparser/emitter/match.rb +1 -0
- data/lib/unparser/emitter/module.rb +1 -1
- data/lib/unparser/emitter/op_assign.rb +3 -1
- data/lib/unparser/emitter/redo.rb +1 -0
- data/lib/unparser/emitter/repetition.rb +5 -3
- data/lib/unparser/emitter/resbody.rb +2 -2
- data/lib/unparser/emitter/rescue.rb +2 -1
- data/lib/unparser/emitter/retry.rb +1 -0
- data/lib/unparser/emitter/send.rb +13 -14
- data/lib/unparser/emitter/send/arguments.rb +1 -2
- data/lib/unparser/emitter/send/attribute_assignment.rb +3 -2
- data/lib/unparser/emitter/send/binary.rb +3 -2
- data/lib/unparser/emitter/send/index.rb +16 -2
- data/lib/unparser/emitter/send/regular.rb +2 -1
- data/lib/unparser/emitter/send/unary.rb +2 -1
- data/lib/unparser/emitter/splat.rb +2 -0
- data/lib/unparser/emitter/super.rb +2 -0
- data/lib/unparser/emitter/undef.rb +1 -0
- data/lib/unparser/emitter/variable.rb +4 -0
- data/lib/unparser/emitter/yield.rb +1 -0
- data/lib/unparser/preprocessor.rb +19 -12
- data/spec/integration/unparser/corpus_spec.rb +3 -2
- data/spec/integrations.yml +11 -1
- data/spec/unit/unparser_spec.rb +190 -183
- data/unparser.gemspec +2 -2
- metadata +5 -4
@@ -5,6 +5,7 @@ module Unparser
|
|
5
5
|
|
6
6
|
# Emitter for postconditions
|
7
7
|
class Post < self
|
8
|
+
include Unterminated
|
8
9
|
|
9
10
|
handle :while_post, :until_post
|
10
11
|
|
@@ -32,6 +33,7 @@ module Unparser
|
|
32
33
|
|
33
34
|
# Base class for while and until emitters
|
34
35
|
class Repetition < self
|
36
|
+
include Terminated
|
35
37
|
|
36
38
|
MAP = {
|
37
39
|
while: K_WHILE,
|
@@ -87,7 +89,7 @@ module Unparser
|
|
87
89
|
#
|
88
90
|
def emit_normal
|
89
91
|
emit_keyword
|
90
|
-
|
92
|
+
visit(condition)
|
91
93
|
emit_body
|
92
94
|
k_end
|
93
95
|
end
|
@@ -99,10 +101,10 @@ module Unparser
|
|
99
101
|
# @api private
|
100
102
|
#
|
101
103
|
def emit_postcontrol
|
102
|
-
|
104
|
+
visit_plain(body)
|
103
105
|
ws
|
104
106
|
emit_keyword
|
105
|
-
|
107
|
+
visit_plain(condition)
|
106
108
|
end
|
107
109
|
|
108
110
|
end # Repetition
|
@@ -4,6 +4,7 @@ module Unparser
|
|
4
4
|
class Emitter
|
5
5
|
# Emitter for rescue nodes
|
6
6
|
class Rescue < self
|
7
|
+
include Unterminated
|
7
8
|
|
8
9
|
handle :rescue
|
9
10
|
|
@@ -56,7 +57,7 @@ module Unparser
|
|
56
57
|
# @api private
|
57
58
|
#
|
58
59
|
def emit_standalone
|
59
|
-
|
60
|
+
visit_plain(body)
|
60
61
|
ws
|
61
62
|
run(Resbody::Standalone, rescue_body)
|
62
63
|
end
|
@@ -16,17 +16,8 @@ module Unparser
|
|
16
16
|
|
17
17
|
children :receiver, :selector
|
18
18
|
|
19
|
-
# Test for terminated expression
|
20
|
-
#
|
21
|
-
# @return [Boolean]
|
22
|
-
#
|
23
|
-
# @api private
|
24
|
-
#
|
25
19
|
def terminated?
|
26
|
-
|
27
|
-
Index::Reference,
|
28
|
-
Regular
|
29
|
-
].include?(effective_emitter)
|
20
|
+
effective_emitter.terminated?
|
30
21
|
end
|
31
22
|
|
32
23
|
private
|
@@ -38,16 +29,26 @@ module Unparser
|
|
38
29
|
# @api private
|
39
30
|
#
|
40
31
|
def dispatch
|
41
|
-
effective_emitter.
|
32
|
+
effective_emitter.write_to_buffer
|
42
33
|
end
|
43
34
|
|
44
35
|
# Return effective emitter
|
45
36
|
#
|
46
|
-
# @return [
|
37
|
+
# @return [Emitter]
|
47
38
|
#
|
48
39
|
# @api private
|
49
40
|
#
|
50
41
|
def effective_emitter
|
42
|
+
effective_emitter_class.new(node, parent)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return effective emitter
|
46
|
+
#
|
47
|
+
# @return [Class:Emitter]
|
48
|
+
#
|
49
|
+
# @api private
|
50
|
+
#
|
51
|
+
def effective_emitter_class
|
51
52
|
case selector
|
52
53
|
when INDEX_REFERENCE
|
53
54
|
Index::Reference
|
@@ -57,7 +58,6 @@ module Unparser
|
|
57
58
|
non_index_emitter
|
58
59
|
end
|
59
60
|
end
|
60
|
-
memoize :effective_emitter
|
61
61
|
|
62
62
|
# Return non index emitter
|
63
63
|
#
|
@@ -86,7 +86,6 @@ module Unparser
|
|
86
86
|
def string_selector
|
87
87
|
selector.to_s
|
88
88
|
end
|
89
|
-
memoize :string_selector
|
90
89
|
|
91
90
|
# Test for unary operator implemented as method
|
92
91
|
#
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Unparser
|
4
4
|
class Emitter
|
5
5
|
class Send
|
6
|
-
|
7
6
|
# Emitter for arguments of send nodes
|
8
7
|
class Arguments < Emitter
|
9
8
|
|
@@ -19,7 +18,7 @@ module Unparser
|
|
19
18
|
return if children.empty?
|
20
19
|
|
21
20
|
parentheses do
|
22
|
-
|
21
|
+
delimited_plain(effective_arguments)
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
@@ -5,6 +5,7 @@ module Unparser
|
|
5
5
|
class Send
|
6
6
|
# Emitter for send as attribute assignment
|
7
7
|
class AttributeAssignment < self
|
8
|
+
include Unterminated
|
8
9
|
|
9
10
|
# Perform regular dispatch
|
10
11
|
#
|
@@ -16,7 +17,7 @@ module Unparser
|
|
16
17
|
emit_receiver
|
17
18
|
emit_attribute
|
18
19
|
emit_operator
|
19
|
-
|
20
|
+
visit(arguments.first)
|
20
21
|
end
|
21
22
|
|
22
23
|
private
|
@@ -28,7 +29,7 @@ module Unparser
|
|
28
29
|
# @api private
|
29
30
|
#
|
30
31
|
def emit_receiver
|
31
|
-
|
32
|
+
visit(receiver)
|
32
33
|
write(T_DOT)
|
33
34
|
end
|
34
35
|
|
@@ -5,6 +5,7 @@ module Unparser
|
|
5
5
|
class Send
|
6
6
|
# Emitter for binary sends
|
7
7
|
class Binary < self
|
8
|
+
include Unterminated
|
8
9
|
|
9
10
|
private
|
10
11
|
|
@@ -15,7 +16,7 @@ module Unparser
|
|
15
16
|
# @api private
|
16
17
|
#
|
17
18
|
def dispatch
|
18
|
-
|
19
|
+
visit(receiver)
|
19
20
|
emit_operator
|
20
21
|
emit_right
|
21
22
|
end
|
@@ -47,7 +48,7 @@ module Unparser
|
|
47
48
|
# @api private
|
48
49
|
#
|
49
50
|
def emit_right
|
50
|
-
|
51
|
+
visit(right_node)
|
51
52
|
end
|
52
53
|
|
53
54
|
end # Binary
|
@@ -26,11 +26,12 @@ module Unparser
|
|
26
26
|
# @api private
|
27
27
|
#
|
28
28
|
def emit_receiver
|
29
|
-
|
29
|
+
visit(first_child)
|
30
30
|
end
|
31
31
|
|
32
32
|
# Emitter for index reference nodes
|
33
33
|
class Reference < self
|
34
|
+
include Terminated
|
34
35
|
|
35
36
|
private
|
36
37
|
|
@@ -42,13 +43,26 @@ module Unparser
|
|
42
43
|
#
|
43
44
|
def emit_operation
|
44
45
|
parentheses(*INDEX_PARENS) do
|
45
|
-
|
46
|
+
delimited_plain(arguments)
|
46
47
|
end
|
47
48
|
end
|
48
49
|
end # Reference
|
49
50
|
|
50
51
|
# Emitter for assign to index nodes
|
51
52
|
class Assign < self
|
53
|
+
include Unterminated
|
54
|
+
|
55
|
+
# Test if assign will be emitted terminated
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
#
|
61
|
+
def terminated?
|
62
|
+
mlhs?
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
52
66
|
|
53
67
|
define_group(:indices, 2..-2)
|
54
68
|
define_child(:value, -1)
|
@@ -5,6 +5,7 @@ module Unparser
|
|
5
5
|
class Send
|
6
6
|
# Emitter for "regular" receiver.selector(arguments...) case
|
7
7
|
class Regular < self
|
8
|
+
include Terminated
|
8
9
|
|
9
10
|
private
|
10
11
|
|
@@ -28,7 +29,7 @@ module Unparser
|
|
28
29
|
#
|
29
30
|
def emit_receiver
|
30
31
|
return unless first_child
|
31
|
-
|
32
|
+
visit(receiver)
|
32
33
|
write(T_DOT)
|
33
34
|
end
|
34
35
|
|
@@ -5,6 +5,7 @@ module Unparser
|
|
5
5
|
class Send
|
6
6
|
# Emitter for unary sends
|
7
7
|
class Unary < self
|
8
|
+
include Unterminated
|
8
9
|
|
9
10
|
private
|
10
11
|
|
@@ -26,7 +27,7 @@ module Unparser
|
|
26
27
|
write('+')
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
visit(receiver)
|
30
31
|
end
|
31
32
|
|
32
33
|
end # Unary
|
@@ -5,6 +5,7 @@ module Unparser
|
|
5
5
|
|
6
6
|
# Emitter for various variable accesses
|
7
7
|
class Variable < self
|
8
|
+
include Terminated
|
8
9
|
|
9
10
|
handle :ivar, :lvar, :cvar, :gvar, :back_ref
|
10
11
|
|
@@ -26,6 +27,7 @@ module Unparser
|
|
26
27
|
|
27
28
|
# Emitter for constant access
|
28
29
|
class Const < self
|
30
|
+
include Terminated
|
29
31
|
|
30
32
|
handle :const
|
31
33
|
|
@@ -59,6 +61,8 @@ module Unparser
|
|
59
61
|
|
60
62
|
# Emitter for nth_ref nodes (regexp captures)
|
61
63
|
class NthRef < self
|
64
|
+
include Terminated
|
65
|
+
|
62
66
|
PREFIX = '$'.freeze
|
63
67
|
handle :nth_ref
|
64
68
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Unparser
|
4
4
|
# Preprocessor to normalize AST generated by parser
|
5
5
|
class Preprocessor
|
6
|
-
include Adamantium::Flat, NodeHelpers, AbstractType, Concord.new(:node), Procto.call(:result)
|
6
|
+
include Adamantium::Flat, NodeHelpers, AbstractType, Concord.new(:node, :parent_type), Procto.call(:result)
|
7
7
|
|
8
8
|
# Return preprocessor result
|
9
9
|
#
|
@@ -23,10 +23,10 @@ module Unparser
|
|
23
23
|
#
|
24
24
|
# @api private
|
25
25
|
#
|
26
|
-
def self.run(node)
|
26
|
+
def self.run(node, parent_type = nil)
|
27
27
|
return EMPTY if node.nil?
|
28
28
|
REGISTRY.fetch(node.type, [Noop]).reduce(node) do |current, processor|
|
29
|
-
processor.call(current)
|
29
|
+
processor.call(current, parent_type)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -49,14 +49,14 @@ module Unparser
|
|
49
49
|
|
50
50
|
# Visit node
|
51
51
|
#
|
52
|
-
# @param [Parser::AST::Node]
|
52
|
+
# @param [Parser::AST::Node] child
|
53
53
|
#
|
54
54
|
# @return [undefined]
|
55
55
|
#
|
56
56
|
# @api private
|
57
57
|
#
|
58
|
-
def visit(
|
59
|
-
self.class.run(node)
|
58
|
+
def visit(child)
|
59
|
+
self.class.run(child, node.type)
|
60
60
|
end
|
61
61
|
|
62
62
|
# Return children
|
@@ -77,7 +77,7 @@ module Unparser
|
|
77
77
|
#
|
78
78
|
def visited_children
|
79
79
|
children.map do |node|
|
80
|
-
if node.
|
80
|
+
if node.is_a?(Parser::AST::Node)
|
81
81
|
visit(node)
|
82
82
|
else
|
83
83
|
node
|
@@ -155,6 +155,12 @@ module Unparser
|
|
155
155
|
class CompactDSTR < self
|
156
156
|
|
157
157
|
register :dstr
|
158
|
+
register :dsym
|
159
|
+
|
160
|
+
MAP = IceNine.deep_freeze(
|
161
|
+
dstr: :str,
|
162
|
+
dsym: :sym
|
163
|
+
)
|
158
164
|
|
159
165
|
# Return preprocessor result
|
160
166
|
#
|
@@ -163,8 +169,8 @@ module Unparser
|
|
163
169
|
# @api private
|
164
170
|
#
|
165
171
|
def result
|
166
|
-
if children.all? { |child| child.type.equal?(:str) }
|
167
|
-
node.updated(
|
172
|
+
if children.any? && children.all? { |child| child.type.equal?(:str) }
|
173
|
+
node.updated(MAP.fetch(node.type), [children.map { |child| child.children.first }.join])
|
168
174
|
else
|
169
175
|
node
|
170
176
|
end
|
@@ -201,7 +207,8 @@ module Unparser
|
|
201
207
|
|
202
208
|
# Preprocessor for begin nodes. Removes begin nodes with one child.
|
203
209
|
#
|
204
|
-
#
|
210
|
+
# This reduces the amount of complex logic needed inside unparser to emit "nice" syntax with minimal
|
211
|
+
# tokens.
|
205
212
|
#
|
206
213
|
class Begin < self
|
207
214
|
|
@@ -214,10 +221,10 @@ module Unparser
|
|
214
221
|
# @api private
|
215
222
|
#
|
216
223
|
def result
|
217
|
-
if children.one?
|
224
|
+
if children.one? && !parent_type.equal?(:regexp)
|
218
225
|
visit(children.first)
|
219
226
|
else
|
220
|
-
Noop.call(node)
|
227
|
+
Noop.call(node, parent_type)
|
221
228
|
end
|
222
229
|
end
|
223
230
|
|