unparser 0.6.5 → 0.8.0
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/README.md +11 -6
- data/bin/unparser +1 -1
- data/lib/unparser/adamantium.rb +3 -1
- data/lib/unparser/anima.rb +11 -0
- data/lib/unparser/ast/local_variable_scope.rb +28 -25
- data/lib/unparser/ast.rb +18 -22
- data/lib/unparser/buffer.rb +43 -15
- data/lib/unparser/cli.rb +30 -7
- data/lib/unparser/color.rb +5 -0
- data/lib/unparser/either.rb +6 -6
- data/lib/unparser/emitter/args.rb +5 -1
- data/lib/unparser/emitter/argument.rb +6 -4
- data/lib/unparser/emitter/array.rb +0 -4
- data/lib/unparser/emitter/array_pattern.rb +1 -9
- data/lib/unparser/emitter/assignment.rb +17 -8
- data/lib/unparser/emitter/begin.rb +0 -6
- data/lib/unparser/emitter/binary.rb +1 -1
- data/lib/unparser/emitter/block.rb +13 -6
- data/lib/unparser/emitter/def.rb +1 -1
- data/lib/unparser/emitter/dstr.rb +6 -5
- data/lib/unparser/emitter/dsym.rb +1 -1
- data/lib/unparser/emitter/ensure.rb +16 -0
- data/lib/unparser/emitter/flipflop.rb +7 -2
- data/lib/unparser/emitter/flow_modifier.rb +1 -7
- data/lib/unparser/emitter/for.rb +1 -1
- data/lib/unparser/emitter/hash.rb +0 -16
- data/lib/unparser/emitter/hash_pattern.rb +1 -1
- data/lib/unparser/emitter/in_pattern.rb +9 -1
- data/lib/unparser/emitter/index.rb +0 -4
- data/lib/unparser/emitter/kwbegin.rb +1 -1
- data/lib/unparser/emitter/match_pattern.rb +7 -11
- data/lib/unparser/emitter/match_pattern_p.rb +6 -1
- data/lib/unparser/emitter/mlhs.rb +7 -1
- data/lib/unparser/emitter/op_assign.rb +0 -5
- data/lib/unparser/emitter/pair.rb +31 -5
- data/lib/unparser/emitter/primitive.rb +19 -6
- data/lib/unparser/emitter/range.rb +23 -2
- data/lib/unparser/emitter/regexp.rb +5 -17
- data/lib/unparser/emitter/rescue.rb +7 -1
- data/lib/unparser/emitter/root.rb +2 -9
- data/lib/unparser/emitter/send.rb +1 -5
- data/lib/unparser/emitter/string.rb +31 -0
- data/lib/unparser/emitter/xstr.rb +8 -1
- data/lib/unparser/emitter.rb +9 -10
- data/lib/unparser/generation.rb +33 -29
- data/lib/unparser/node_details/send.rb +4 -3
- data/lib/unparser/node_details.rb +1 -0
- data/lib/unparser/node_helpers.rb +19 -9
- data/lib/unparser/util.rb +23 -0
- data/lib/unparser/validation.rb +70 -28
- data/lib/unparser/writer/array.rb +51 -0
- data/lib/unparser/writer/binary.rb +8 -4
- data/lib/unparser/writer/dynamic_string.rb +127 -146
- data/lib/unparser/writer/regexp.rb +101 -0
- data/lib/unparser/writer/resbody.rb +37 -3
- data/lib/unparser/writer/rescue.rb +3 -7
- data/lib/unparser/writer/send/unary.rb +9 -4
- data/lib/unparser/writer/send.rb +8 -14
- data/lib/unparser/writer.rb +31 -1
- data/lib/unparser.rb +149 -38
- metadata +38 -20
data/lib/unparser/emitter.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Unparser
|
|
|
6
6
|
# Emitter base class
|
|
7
7
|
class Emitter
|
|
8
8
|
include Adamantium, AbstractType, Constants, Generation, NodeHelpers
|
|
9
|
-
include Anima.new(:buffer, :comments, :
|
|
9
|
+
include Anima.new(:buffer, :comments, :explicit_encoding, :local_variable_scope, :node)
|
|
10
10
|
|
|
11
11
|
public :node
|
|
12
12
|
|
|
@@ -22,10 +22,9 @@ module Unparser
|
|
|
22
22
|
#
|
|
23
23
|
# @return [Parser::AST::Node]
|
|
24
24
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
25
|
+
# mutant:disable
|
|
27
26
|
def local_variable_scope
|
|
28
|
-
AST::LocalVariableScope.new(node)
|
|
27
|
+
AST::LocalVariableScope.new(node: node, static_local_variables: Set.new)
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
def self.included(descendant)
|
|
@@ -67,7 +66,7 @@ module Unparser
|
|
|
67
66
|
# @api private
|
|
68
67
|
#
|
|
69
68
|
# rubocop:disable Metrics/ParameterLists
|
|
70
|
-
def self.emitter(buffer:, comments:, node:, local_variable_scope:)
|
|
69
|
+
def self.emitter(buffer:, explicit_encoding:, comments:, node:, local_variable_scope:)
|
|
71
70
|
type = node.type
|
|
72
71
|
|
|
73
72
|
klass = REGISTRY.fetch(type) do
|
|
@@ -75,10 +74,11 @@ module Unparser
|
|
|
75
74
|
end
|
|
76
75
|
|
|
77
76
|
klass.new(
|
|
78
|
-
buffer
|
|
79
|
-
comments
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
buffer:,
|
|
78
|
+
comments:,
|
|
79
|
+
explicit_encoding:,
|
|
80
|
+
local_variable_scope:,
|
|
81
|
+
node:
|
|
82
82
|
)
|
|
83
83
|
end
|
|
84
84
|
# rubocop:enable Metrics/ParameterLists
|
|
@@ -90,6 +90,5 @@ module Unparser
|
|
|
90
90
|
# @api private
|
|
91
91
|
#
|
|
92
92
|
abstract_method :dispatch
|
|
93
|
-
|
|
94
93
|
end # Emitter
|
|
95
94
|
end # Unparser
|
data/lib/unparser/generation.rb
CHANGED
|
@@ -7,8 +7,6 @@ module Unparser
|
|
|
7
7
|
|
|
8
8
|
private_constant(*constants(false))
|
|
9
9
|
|
|
10
|
-
def emit_heredoc_reminders; end
|
|
11
|
-
|
|
12
10
|
def symbol_name; end
|
|
13
11
|
|
|
14
12
|
def write_to_buffer
|
|
@@ -121,40 +119,50 @@ module Unparser
|
|
|
121
119
|
end
|
|
122
120
|
|
|
123
121
|
def emit_body(node, indent: true)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
122
|
+
with_indent(indent: indent) do
|
|
123
|
+
if n_begin?(node)
|
|
124
|
+
if node.children.empty?
|
|
125
|
+
write('()')
|
|
126
|
+
elsif node.children.one?
|
|
127
|
+
visit_deep(node)
|
|
128
|
+
else
|
|
129
|
+
emit_body_inner(node)
|
|
130
|
+
end
|
|
132
131
|
else
|
|
133
|
-
|
|
132
|
+
visit_deep(node)
|
|
134
133
|
end
|
|
135
|
-
else
|
|
136
|
-
visit_deep(node)
|
|
137
134
|
end
|
|
135
|
+
end
|
|
138
136
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
def with_indent(indent:)
|
|
138
|
+
return yield unless indent
|
|
139
|
+
|
|
140
|
+
buffer.indent
|
|
141
|
+
nl
|
|
142
|
+
yield
|
|
143
|
+
buffer.unindent
|
|
144
|
+
nl
|
|
143
145
|
end
|
|
144
146
|
|
|
145
147
|
def emit_body_inner(node)
|
|
146
148
|
head, *tail = node.children
|
|
147
149
|
emit_body_member(head)
|
|
150
|
+
write(';') if requires_explicit_statement_terminator?(head, tail)
|
|
148
151
|
|
|
149
152
|
tail.each do |child|
|
|
150
|
-
|
|
153
|
+
buffer.ensure_nl
|
|
151
154
|
|
|
152
155
|
nl if EXTRA_NL.include?(child.type)
|
|
153
156
|
|
|
154
157
|
emit_body_member(child)
|
|
158
|
+
write(';') if requires_explicit_statement_terminator?(child, tail)
|
|
155
159
|
end
|
|
156
160
|
end
|
|
157
161
|
|
|
162
|
+
def requires_explicit_statement_terminator?(node, nodes_group)
|
|
163
|
+
n_range?(node) && node.children.fetch(1).nil? && !node.eql?(nodes_group.fetch(-1))
|
|
164
|
+
end
|
|
165
|
+
|
|
158
166
|
def emit_body_member(node)
|
|
159
167
|
if n_rescue?(node)
|
|
160
168
|
emit_rescue_postcontrol(node)
|
|
@@ -204,21 +212,20 @@ module Unparser
|
|
|
204
212
|
end
|
|
205
213
|
|
|
206
214
|
def emit_rescue_postcontrol(node)
|
|
207
|
-
writer = writer_with(Writer::Rescue, node)
|
|
215
|
+
writer = writer_with(Writer::Rescue, node:)
|
|
208
216
|
writer.emit_postcontrol
|
|
209
|
-
writer.emit_heredoc_reminders
|
|
210
217
|
end
|
|
211
218
|
|
|
212
219
|
def emit_rescue_regular(node)
|
|
213
|
-
writer_with(Writer::Rescue, node).emit_regular
|
|
220
|
+
writer_with(Writer::Rescue, node:).emit_regular
|
|
214
221
|
end
|
|
215
222
|
|
|
216
|
-
def
|
|
217
|
-
|
|
223
|
+
def emitter(node)
|
|
224
|
+
Emitter.emitter(**to_h, node: node)
|
|
218
225
|
end
|
|
219
226
|
|
|
220
|
-
def
|
|
221
|
-
|
|
227
|
+
def writer_with(klass, node:, **attributes)
|
|
228
|
+
klass.new(to_h.merge(node: node, **attributes))
|
|
222
229
|
end
|
|
223
230
|
|
|
224
231
|
def visit(node)
|
|
@@ -226,10 +233,7 @@ module Unparser
|
|
|
226
233
|
end
|
|
227
234
|
|
|
228
235
|
def visit_deep(node)
|
|
229
|
-
emitter(node).tap
|
|
230
|
-
emitter.write_to_buffer
|
|
231
|
-
emitter.emit_heredoc_reminders
|
|
232
|
-
end
|
|
236
|
+
emitter(node).tap(&:write_to_buffer)
|
|
233
237
|
end
|
|
234
238
|
|
|
235
239
|
def first_child
|
|
@@ -19,9 +19,10 @@ module Unparser
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def binary_syntax_allowed?
|
|
22
|
-
selector_binary_operator?
|
|
23
|
-
&&
|
|
24
|
-
&&
|
|
22
|
+
selector_binary_operator? \
|
|
23
|
+
&& n_send?(node) \
|
|
24
|
+
&& arguments.one? \
|
|
25
|
+
&& !n_splat?(arguments.first) \
|
|
25
26
|
&& !n_kwargs?(arguments.first)
|
|
26
27
|
end
|
|
27
28
|
|
|
@@ -31,7 +31,16 @@ module Unparser
|
|
|
31
31
|
node.type.equal?(type)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def n_flipflop?(node)
|
|
35
|
+
n_iflipflop?(node) || n_eflipflop?(node)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def n_range?(node)
|
|
39
|
+
n_irange?(node) || n_erange?(node)
|
|
40
|
+
end
|
|
41
|
+
|
|
34
42
|
%i[
|
|
43
|
+
and
|
|
35
44
|
arg
|
|
36
45
|
args
|
|
37
46
|
array
|
|
@@ -41,18 +50,26 @@ module Unparser
|
|
|
41
50
|
cbase
|
|
42
51
|
const
|
|
43
52
|
dstr
|
|
53
|
+
eflipflop
|
|
44
54
|
empty_else
|
|
55
|
+
erange
|
|
45
56
|
ensure
|
|
57
|
+
gvar
|
|
46
58
|
hash
|
|
47
59
|
hash_pattern
|
|
48
60
|
if
|
|
61
|
+
iflipflop
|
|
49
62
|
in_pattern
|
|
50
63
|
int
|
|
64
|
+
irange
|
|
51
65
|
kwarg
|
|
52
66
|
kwargs
|
|
53
67
|
kwsplat
|
|
54
68
|
lambda
|
|
69
|
+
lvar
|
|
55
70
|
match_rest
|
|
71
|
+
mlhs
|
|
72
|
+
or
|
|
56
73
|
pair
|
|
57
74
|
rescue
|
|
58
75
|
send
|
|
@@ -60,20 +77,13 @@ module Unparser
|
|
|
60
77
|
splat
|
|
61
78
|
str
|
|
62
79
|
sym
|
|
63
|
-
|
|
80
|
+
xstr
|
|
81
|
+
].to_set.each do |type|
|
|
64
82
|
name = "n_#{type}?"
|
|
65
83
|
define_method(name) do |node|
|
|
66
84
|
n?(type, node)
|
|
67
85
|
end
|
|
68
86
|
private(name)
|
|
69
87
|
end
|
|
70
|
-
|
|
71
|
-
def unwrap_single_begin(node)
|
|
72
|
-
if n_begin?(node) && node.children.one?
|
|
73
|
-
node.children.first
|
|
74
|
-
else
|
|
75
|
-
node
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
88
|
end # NodeHelpers
|
|
79
89
|
end # Unparser
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
# Original code before vendoring and reduction from: https://github.com/mbj/mutant/blob/main/lib/mutant/util.rb
|
|
5
|
+
module Util
|
|
6
|
+
# Error raised by `Util.one` if size is not exactly one
|
|
7
|
+
SizeError = Class.new(IndexError)
|
|
8
|
+
|
|
9
|
+
# Return only element in array if it contains exactly one member
|
|
10
|
+
#
|
|
11
|
+
# @param array [Array]
|
|
12
|
+
#
|
|
13
|
+
# @return [Object] first entry
|
|
14
|
+
def self.one(array)
|
|
15
|
+
case array
|
|
16
|
+
in [value]
|
|
17
|
+
value
|
|
18
|
+
else
|
|
19
|
+
fail SizeError, "expected size to be exactly 1 but size was #{array.size}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/unparser/validation.rb
CHANGED
|
@@ -7,31 +7,38 @@ module Unparser
|
|
|
7
7
|
:generated_node,
|
|
8
8
|
:generated_source,
|
|
9
9
|
:identification,
|
|
10
|
-
:
|
|
10
|
+
:original_ast,
|
|
11
11
|
:original_source
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
+
class PhaseException
|
|
15
|
+
include Anima.new(:exception, :phase)
|
|
16
|
+
end
|
|
17
|
+
|
|
14
18
|
# Test if source could be unparsed successfully
|
|
15
19
|
#
|
|
16
20
|
# @return [Boolean]
|
|
17
21
|
#
|
|
18
22
|
# @api private
|
|
19
23
|
#
|
|
24
|
+
# rubocop:disable Style/OperatorMethodCall
|
|
25
|
+
# mutant:disable
|
|
20
26
|
def success?
|
|
21
27
|
[
|
|
22
28
|
original_source,
|
|
23
|
-
|
|
29
|
+
original_ast,
|
|
24
30
|
generated_source,
|
|
25
31
|
generated_node
|
|
26
32
|
].all?(&:right?) && generated_node.from_right.==(original_node.from_right)
|
|
27
33
|
end
|
|
34
|
+
# rubocop:enable Style/OperatorMethodCall
|
|
28
35
|
|
|
29
36
|
# Return error report
|
|
30
37
|
#
|
|
31
38
|
# @return [String]
|
|
32
39
|
#
|
|
33
40
|
# @api private
|
|
34
|
-
#
|
|
41
|
+
# mutant:disable
|
|
35
42
|
def report
|
|
36
43
|
message = [identification]
|
|
37
44
|
|
|
@@ -45,48 +52,57 @@ module Unparser
|
|
|
45
52
|
end
|
|
46
53
|
memoize :report
|
|
47
54
|
|
|
55
|
+
# mutant:disable
|
|
56
|
+
def original_node
|
|
57
|
+
original_ast.fmap(&:node)
|
|
58
|
+
end
|
|
59
|
+
|
|
48
60
|
# Create validator from string
|
|
49
61
|
#
|
|
50
62
|
# @param [String] original_source
|
|
51
63
|
#
|
|
52
64
|
# @return [Validator]
|
|
65
|
+
# mutant:disable
|
|
53
66
|
def self.from_string(original_source)
|
|
54
|
-
|
|
55
|
-
.parse_either(original_source)
|
|
67
|
+
original_ast = parse_ast_either(original_source)
|
|
56
68
|
|
|
57
|
-
generated_source =
|
|
69
|
+
generated_source = original_ast
|
|
58
70
|
.lmap(&method(:const_unit))
|
|
59
|
-
.bind(&
|
|
71
|
+
.bind(&method(:unparse_ast_either))
|
|
60
72
|
|
|
61
73
|
generated_node = generated_source
|
|
62
74
|
.lmap(&method(:const_unit))
|
|
63
|
-
.bind(&
|
|
75
|
+
.bind(&method(:parse_ast_either))
|
|
76
|
+
.fmap(&:node)
|
|
64
77
|
|
|
65
78
|
new(
|
|
66
|
-
|
|
67
|
-
original_source: Either::Right.new(original_source),
|
|
68
|
-
original_node: original_node,
|
|
79
|
+
generated_node: generated_node,
|
|
69
80
|
generated_source: generated_source,
|
|
70
|
-
|
|
81
|
+
identification: '(string)',
|
|
82
|
+
original_ast: original_ast,
|
|
83
|
+
original_source: Either::Right.new(original_source)
|
|
71
84
|
)
|
|
72
85
|
end
|
|
73
86
|
|
|
74
|
-
# Create validator from
|
|
87
|
+
# Create validator from ast
|
|
75
88
|
#
|
|
76
|
-
# @param [
|
|
89
|
+
# @param [Unparser::AST] ast
|
|
77
90
|
#
|
|
78
91
|
# @return [Validator]
|
|
79
|
-
|
|
80
|
-
|
|
92
|
+
#
|
|
93
|
+
# mutant:disable
|
|
94
|
+
def self.from_ast(ast:)
|
|
95
|
+
generated_source = Unparser.unparse_ast_either(ast)
|
|
81
96
|
|
|
82
97
|
generated_node = generated_source
|
|
83
98
|
.lmap(&method(:const_unit))
|
|
84
|
-
.bind(&
|
|
99
|
+
.bind(&method(:parse_ast_either))
|
|
100
|
+
.fmap(&:node)
|
|
85
101
|
|
|
86
102
|
new(
|
|
87
103
|
identification: '(string)',
|
|
88
104
|
original_source: generated_source,
|
|
89
|
-
|
|
105
|
+
original_ast: Either::Right.new(ast),
|
|
90
106
|
generated_source: generated_source,
|
|
91
107
|
generated_node: generated_node
|
|
92
108
|
)
|
|
@@ -97,24 +113,45 @@ module Unparser
|
|
|
97
113
|
# @param [Pathname] path
|
|
98
114
|
#
|
|
99
115
|
# @return [Validator]
|
|
116
|
+
#
|
|
117
|
+
# mutant:disable
|
|
100
118
|
def self.from_path(path)
|
|
101
|
-
from_string(path.read).with(identification: path.to_s)
|
|
119
|
+
from_string(path.read.freeze).with(identification: path.to_s)
|
|
102
120
|
end
|
|
103
121
|
|
|
122
|
+
# mutant:disable
|
|
123
|
+
def self.unparse_ast_either(ast)
|
|
124
|
+
Unparser.unparse_ast_either(ast)
|
|
125
|
+
end
|
|
126
|
+
private_class_method :unparse_ast_either
|
|
127
|
+
|
|
128
|
+
# mutant:disable
|
|
129
|
+
def self.parse_ast_either(source)
|
|
130
|
+
Unparser.parse_ast_either(source)
|
|
131
|
+
end
|
|
132
|
+
private_class_method :parse_ast_either
|
|
133
|
+
|
|
134
|
+
# mutant:disable
|
|
135
|
+
def self.const_unit(_); end
|
|
136
|
+
private_class_method :const_unit
|
|
137
|
+
|
|
104
138
|
private
|
|
105
139
|
|
|
140
|
+
# mutant:disable
|
|
106
141
|
def make_report(label, attribute_name)
|
|
107
142
|
["#{label}:"].concat(public_send(attribute_name).either(method(:report_exception), ->(value) { [value] }))
|
|
108
143
|
end
|
|
109
144
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
145
|
+
# mutant:disable
|
|
146
|
+
def report_exception(phase_exception)
|
|
147
|
+
if phase_exception
|
|
148
|
+
[phase_exception.inspect].concat(phase_exception.backtrace.take(20))
|
|
113
149
|
else
|
|
114
|
-
[
|
|
150
|
+
%w[undefined]
|
|
115
151
|
end
|
|
116
152
|
end
|
|
117
153
|
|
|
154
|
+
# mutant:disable
|
|
118
155
|
def node_diff_report
|
|
119
156
|
diff = nil
|
|
120
157
|
|
|
@@ -130,14 +167,13 @@ module Unparser
|
|
|
130
167
|
diff ? ['Node-Diff:', diff] : []
|
|
131
168
|
end
|
|
132
169
|
|
|
133
|
-
def self.const_unit(_value); end
|
|
134
|
-
private_class_method :const_unit
|
|
135
|
-
|
|
136
170
|
class Literal < self
|
|
171
|
+
# mutant:disable
|
|
137
172
|
def success?
|
|
138
173
|
original_source.eql?(generated_source)
|
|
139
174
|
end
|
|
140
175
|
|
|
176
|
+
# mutant:disable
|
|
141
177
|
def report
|
|
142
178
|
message = [identification]
|
|
143
179
|
|
|
@@ -153,20 +189,26 @@ module Unparser
|
|
|
153
189
|
|
|
154
190
|
private
|
|
155
191
|
|
|
192
|
+
# mutant:disable
|
|
156
193
|
def source_diff_report
|
|
157
194
|
diff = nil
|
|
158
195
|
|
|
159
196
|
original_source.fmap do |original|
|
|
160
197
|
generated_source.fmap do |generated|
|
|
161
198
|
diff = Diff.new(
|
|
162
|
-
original.split("\n", -1),
|
|
163
|
-
generated.split("\n", -1)
|
|
199
|
+
encode(original).split("\n", -1),
|
|
200
|
+
encode(generated).split("\n", -1)
|
|
164
201
|
).colorized_diff
|
|
165
202
|
end
|
|
166
203
|
end
|
|
167
204
|
|
|
168
205
|
diff ? ['Source-Diff:', diff] : []
|
|
169
206
|
end
|
|
207
|
+
|
|
208
|
+
# mutant:disable
|
|
209
|
+
def encode(string)
|
|
210
|
+
string.encode('UTF-8', invalid: :replace, undef: :replace)
|
|
211
|
+
end
|
|
170
212
|
end # Literal
|
|
171
213
|
end # Validation
|
|
172
214
|
end # Unparser
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
class Array
|
|
6
|
+
include Writer, Adamantium
|
|
7
|
+
|
|
8
|
+
MAP = {
|
|
9
|
+
dsym: '%I',
|
|
10
|
+
sym: '%i',
|
|
11
|
+
dstr: '%W',
|
|
12
|
+
str: '%w'
|
|
13
|
+
}.freeze
|
|
14
|
+
private_constant(*constants(false))
|
|
15
|
+
|
|
16
|
+
def emit_compact # rubocop:disable Metrics/AbcSize
|
|
17
|
+
children_generic_type = array_elements_generic_type
|
|
18
|
+
|
|
19
|
+
write(MAP.fetch(children_generic_type))
|
|
20
|
+
|
|
21
|
+
parentheses('[', ']') do
|
|
22
|
+
delimited(children, ' ') do |child|
|
|
23
|
+
if n_sym?(child) || n_str?(child)
|
|
24
|
+
write(Util.one(child.children).to_s)
|
|
25
|
+
else
|
|
26
|
+
write('#{')
|
|
27
|
+
emitter(Util.one(Util.one(child.children).children)).write_to_buffer
|
|
28
|
+
write('}')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def array_elements_generic_type
|
|
37
|
+
children_types = children.to_set(&:type)
|
|
38
|
+
|
|
39
|
+
if children_types == Set[:sym, :dsym]
|
|
40
|
+
:dsym
|
|
41
|
+
elsif children_types == Set[:str, :dstr]
|
|
42
|
+
:dstr
|
|
43
|
+
elsif children_types == Set[]
|
|
44
|
+
:sym
|
|
45
|
+
else
|
|
46
|
+
Util.one(children_types.to_a)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end # Array
|
|
50
|
+
end # Writer
|
|
51
|
+
end # Unparser
|
|
@@ -39,7 +39,7 @@ module Unparser
|
|
|
39
39
|
tANDOP: '&&'
|
|
40
40
|
}.freeze
|
|
41
41
|
|
|
42
|
-
NEED_KEYWORD = %i[return break next].freeze
|
|
42
|
+
NEED_KEYWORD = %i[return break next match_pattern_p].freeze
|
|
43
43
|
|
|
44
44
|
private_constant(*constants(false))
|
|
45
45
|
|
|
@@ -52,9 +52,13 @@ module Unparser
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def dispatch
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if node.type.eql?(:and) && left.type.equal?(:or)
|
|
56
|
+
emit_with(KEYWORD_TOKENS)
|
|
57
|
+
else
|
|
58
|
+
left_emitter.write_to_buffer
|
|
59
|
+
write(' ', MAP.fetch(effective_symbol), ' ')
|
|
60
|
+
visit(right)
|
|
61
|
+
end
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
private
|