unparser 0.4.7 → 0.6.7
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 +40 -9
- data/bin/unparser +2 -2
- data/lib/unparser/abstract_type.rb +121 -0
- data/lib/unparser/adamantium/method_builder.rb +111 -0
- data/lib/unparser/adamantium.rb +150 -0
- data/lib/unparser/anima/attribute.rb +59 -0
- data/lib/unparser/anima/error.rb +23 -0
- data/lib/unparser/anima.rb +184 -0
- data/lib/unparser/ast/local_variable_scope.rb +6 -76
- data/lib/unparser/ast.rb +1 -3
- data/lib/unparser/buffer.rb +14 -25
- data/lib/unparser/cli.rb +85 -77
- data/lib/unparser/{cli/color.rb → color.rb} +4 -14
- data/lib/unparser/comments.rb +0 -26
- data/lib/unparser/concord.rb +114 -0
- data/lib/unparser/constants.rb +4 -53
- data/lib/unparser/diff.rb +98 -0
- data/lib/unparser/dsl.rb +0 -32
- data/lib/unparser/either.rb +153 -0
- data/lib/unparser/emitter/alias.rb +2 -8
- data/lib/unparser/emitter/args.rb +45 -0
- data/lib/unparser/emitter/argument.rb +13 -169
- data/lib/unparser/emitter/array.rb +27 -0
- data/lib/unparser/emitter/array_pattern.rb +29 -0
- data/lib/unparser/emitter/assignment.rb +36 -127
- data/lib/unparser/emitter/begin.rb +9 -84
- data/lib/unparser/emitter/binary.rb +7 -20
- data/lib/unparser/emitter/block.rb +57 -41
- data/lib/unparser/emitter/case.rb +6 -48
- data/lib/unparser/emitter/case_guard.rb +27 -0
- data/lib/unparser/emitter/case_match.rb +40 -0
- data/lib/unparser/emitter/cbase.rb +1 -3
- data/lib/unparser/emitter/class.rb +6 -26
- data/lib/unparser/emitter/const_pattern.rb +24 -0
- data/lib/unparser/emitter/def.rb +7 -51
- data/lib/unparser/emitter/defined.rb +2 -12
- data/lib/unparser/emitter/dstr.rb +22 -0
- data/lib/unparser/emitter/dsym.rb +41 -0
- data/lib/unparser/emitter/find_pattern.rb +18 -0
- data/lib/unparser/emitter/flipflop.rb +11 -10
- data/lib/unparser/emitter/float.rb +29 -0
- data/lib/unparser/emitter/flow_modifier.rb +15 -53
- data/lib/unparser/emitter/for.rb +5 -19
- data/lib/unparser/emitter/hash.rb +36 -0
- data/lib/unparser/emitter/hash_pattern.rb +67 -0
- data/lib/unparser/emitter/hookexe.rb +5 -11
- data/lib/unparser/emitter/if.rb +15 -71
- data/lib/unparser/emitter/in_match.rb +21 -0
- data/lib/unparser/emitter/in_pattern.rb +36 -0
- data/lib/unparser/emitter/index.rb +22 -89
- data/lib/unparser/emitter/kwargs.rb +13 -0
- data/lib/unparser/emitter/kwbegin.rb +31 -0
- data/lib/unparser/emitter/lambda.rb +0 -8
- data/lib/unparser/emitter/masgn.rb +20 -0
- data/lib/unparser/emitter/match.rb +3 -17
- data/lib/unparser/emitter/match_alt.rb +23 -0
- data/lib/unparser/emitter/match_as.rb +21 -0
- data/lib/unparser/emitter/match_pattern.rb +30 -0
- data/lib/unparser/emitter/match_pattern_p.rb +20 -0
- data/lib/unparser/emitter/match_rest.rb +33 -0
- data/lib/unparser/emitter/match_var.rb +19 -0
- data/lib/unparser/emitter/mlhs.rb +40 -0
- data/lib/unparser/emitter/module.rb +3 -9
- data/lib/unparser/emitter/op_assign.rb +14 -29
- data/lib/unparser/emitter/pair.rb +33 -0
- data/lib/unparser/emitter/pin.rb +19 -0
- data/lib/unparser/emitter/primitive.rb +93 -0
- data/lib/unparser/emitter/range.rb +35 -0
- data/lib/unparser/emitter/regexp.rb +35 -0
- data/lib/unparser/emitter/repetition.rb +17 -57
- data/lib/unparser/emitter/rescue.rb +1 -97
- data/lib/unparser/emitter/root.rb +17 -1
- data/lib/unparser/emitter/send.rb +10 -219
- data/lib/unparser/emitter/simple.rb +33 -0
- data/lib/unparser/emitter/splat.rb +13 -19
- data/lib/unparser/emitter/super.rb +1 -29
- data/lib/unparser/emitter/undef.rb +1 -9
- data/lib/unparser/emitter/variable.rb +1 -31
- data/lib/unparser/emitter/xstr.rb +72 -0
- data/lib/unparser/emitter/yield.rb +1 -9
- data/lib/unparser/emitter.rb +24 -425
- data/lib/unparser/equalizer.rb +98 -0
- data/lib/unparser/generation.rb +252 -0
- data/lib/unparser/node_details/send.rb +65 -0
- data/lib/unparser/node_details.rb +21 -0
- data/lib/unparser/node_helpers.rb +48 -6
- data/lib/unparser/validation.rb +172 -0
- data/lib/unparser/writer/binary.rb +99 -0
- data/lib/unparser/writer/dynamic_string.rb +211 -0
- data/lib/unparser/writer/resbody.rb +40 -0
- data/lib/unparser/writer/rescue.rb +43 -0
- data/lib/unparser/{emitter → writer}/send/attribute_assignment.rb +11 -26
- data/lib/unparser/writer/send/binary.rb +27 -0
- data/lib/unparser/writer/send/conditional.rb +25 -0
- data/lib/unparser/writer/send/regular.rb +33 -0
- data/lib/unparser/{emitter → writer}/send/unary.rb +10 -17
- data/lib/unparser/writer/send.rb +115 -0
- data/lib/unparser/writer.rb +15 -0
- data/lib/unparser.rb +161 -77
- metadata +100 -157
- data/.circleci/config.yml +0 -49
- data/.gitignore +0 -37
- data/.rspec +0 -4
- data/.rubocop.yml +0 -9
- data/Changelog.md +0 -156
- data/Gemfile +0 -9
- data/Gemfile.lock +0 -181
- data/LICENSE +0 -20
- data/Rakefile +0 -22
- data/config/devtools.yml +0 -2
- data/config/flay.yml +0 -3
- data/config/flog.yml +0 -2
- data/config/mutant.yml +0 -6
- data/config/reek.yml +0 -98
- data/config/rubocop.yml +0 -122
- data/config/yardstick.yml +0 -2
- data/lib/unparser/cli/differ.rb +0 -152
- data/lib/unparser/cli/source.rb +0 -267
- data/lib/unparser/emitter/empty.rb +0 -23
- data/lib/unparser/emitter/ensure.rb +0 -37
- data/lib/unparser/emitter/literal/array.rb +0 -29
- data/lib/unparser/emitter/literal/dynamic.rb +0 -53
- data/lib/unparser/emitter/literal/dynamic_body.rb +0 -132
- data/lib/unparser/emitter/literal/execute_string.rb +0 -38
- data/lib/unparser/emitter/literal/hash.rb +0 -156
- data/lib/unparser/emitter/literal/primitive.rb +0 -145
- data/lib/unparser/emitter/literal/range.rb +0 -36
- data/lib/unparser/emitter/literal/regexp.rb +0 -114
- data/lib/unparser/emitter/literal/singleton.rb +0 -26
- data/lib/unparser/emitter/literal.rb +0 -10
- data/lib/unparser/emitter/meta.rb +0 -16
- data/lib/unparser/emitter/redo.rb +0 -25
- data/lib/unparser/emitter/resbody.rb +0 -76
- data/lib/unparser/emitter/retry.rb +0 -25
- data/lib/unparser/emitter/send/binary.rb +0 -57
- data/lib/unparser/emitter/send/conditional.rb +0 -40
- data/lib/unparser/emitter/send/regular.rb +0 -40
- data/lib/unparser/preprocessor.rb +0 -159
- data/spec/integration/unparser/corpus_spec.rb +0 -111
- data/spec/integrations.yml +0 -92
- data/spec/spec_helper.rb +0 -20
- data/spec/unit/unparser/buffer/append_spec.rb +0 -24
- data/spec/unit/unparser/buffer/append_without_prefix_spec.rb +0 -23
- data/spec/unit/unparser/buffer/capture_content_spec.rb +0 -17
- data/spec/unit/unparser/buffer/content_spec.rb +0 -38
- data/spec/unit/unparser/buffer/fresh_line_spec.rb +0 -20
- data/spec/unit/unparser/buffer/indent_spec.rb +0 -20
- data/spec/unit/unparser/buffer/nl_spec.rb +0 -16
- data/spec/unit/unparser/buffer/unindent_spec.rb +0 -20
- data/spec/unit/unparser/comments/consume_spec.rb +0 -22
- data/spec/unit/unparser/comments/take_all_spec.rb +0 -19
- data/spec/unit/unparser/comments/take_before_spec.rb +0 -46
- data/spec/unit/unparser/comments/take_eol_comments_spec.rb +0 -32
- data/spec/unit/unparser/emitter/class_methods/handle_spec.rb +0 -17
- data/spec/unit/unparser_spec.rb +0 -1849
- data/unparser.gemspec +0 -32
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
class DynamicString
|
|
6
|
+
include Writer, Adamantium
|
|
7
|
+
|
|
8
|
+
PATTERNS_2 =
|
|
9
|
+
[
|
|
10
|
+
%i[str_empty begin].freeze,
|
|
11
|
+
%i[begin str_nl].freeze
|
|
12
|
+
].freeze
|
|
13
|
+
|
|
14
|
+
PATTERNS_3 =
|
|
15
|
+
[
|
|
16
|
+
%i[begin str_nl_eol str_nl_eol].freeze,
|
|
17
|
+
%i[str_nl_eol begin str_nl_eol].freeze,
|
|
18
|
+
%i[str_ws begin str_nl_eol].freeze
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
FLAT_INTERPOLATION = %i[ivar cvar gvar nth_ref].to_set.freeze
|
|
22
|
+
|
|
23
|
+
private_constant(*constants(false))
|
|
24
|
+
|
|
25
|
+
def emit_heredoc_reminder
|
|
26
|
+
return unless heredoc?
|
|
27
|
+
|
|
28
|
+
emit_heredoc_body
|
|
29
|
+
emit_heredoc_footer
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def dispatch
|
|
33
|
+
if heredoc?
|
|
34
|
+
emit_heredoc_header
|
|
35
|
+
else
|
|
36
|
+
emit_dstr
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def heredoc_header
|
|
43
|
+
'<<-HEREDOC'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def heredoc?
|
|
47
|
+
!children.empty? && (nl_last_child? && heredoc_pattern?)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def emit_heredoc_header
|
|
51
|
+
write(heredoc_header)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def emit_heredoc_body
|
|
55
|
+
nl
|
|
56
|
+
emit_normal_heredoc_body
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def emit_heredoc_footer
|
|
60
|
+
write('HEREDOC')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def classify(node)
|
|
64
|
+
if n_str?(node)
|
|
65
|
+
classify_str(node)
|
|
66
|
+
else
|
|
67
|
+
node.type
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def classify_str(node)
|
|
72
|
+
if str_nl?(node)
|
|
73
|
+
:str_nl
|
|
74
|
+
elsif node.children.first.end_with?("\n")
|
|
75
|
+
:str_nl_eol
|
|
76
|
+
elsif str_ws?(node)
|
|
77
|
+
:str_ws
|
|
78
|
+
elsif str_empty?(node)
|
|
79
|
+
:str_empty
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def str_nl?(node)
|
|
84
|
+
node.eql?(s(:str, "\n"))
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def str_empty?(node)
|
|
88
|
+
node.eql?(s(:str, ''))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def str_ws?(node)
|
|
92
|
+
/\A( |\t)+\z/.match?(node.children.first)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def heredoc_pattern?
|
|
96
|
+
heredoc_pattern_2? || heredoc_pattern_3?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def heredoc_pattern_3?
|
|
100
|
+
children.each_cons(3).any? do |group|
|
|
101
|
+
PATTERNS_3.include?(group.map(&method(:classify)))
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def heredoc_pattern_2?
|
|
106
|
+
children.each_cons(2).any? do |group|
|
|
107
|
+
PATTERNS_2.include?(group.map(&method(:classify)))
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def nl_last_child?
|
|
112
|
+
last = children.last
|
|
113
|
+
n_str?(last) && last.children.first[-1].eql?("\n")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def emit_normal_heredoc_body
|
|
117
|
+
buffer.root_indent do
|
|
118
|
+
children.each do |child|
|
|
119
|
+
if n_str?(child)
|
|
120
|
+
write(escape_dynamic(child.children.first))
|
|
121
|
+
else
|
|
122
|
+
emit_dynamic(child)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def escape_dynamic(string)
|
|
129
|
+
string.gsub('#', '\#')
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def emit_dynamic(child)
|
|
133
|
+
if FLAT_INTERPOLATION.include?(child.type)
|
|
134
|
+
write('#')
|
|
135
|
+
visit(child)
|
|
136
|
+
elsif n_dstr?(child)
|
|
137
|
+
emit_body(child.children)
|
|
138
|
+
else
|
|
139
|
+
write('#{')
|
|
140
|
+
emit_dynamic_component(child.children.first)
|
|
141
|
+
write('}')
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def emit_dynamic_component(node)
|
|
146
|
+
visit(node) if node
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def emit_dstr
|
|
150
|
+
if children.empty?
|
|
151
|
+
write('%()')
|
|
152
|
+
else
|
|
153
|
+
segments.each_with_index do |children, index|
|
|
154
|
+
emit_segment(children, index)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def breakpoint?(child, current)
|
|
160
|
+
last_type = current.last&.type
|
|
161
|
+
|
|
162
|
+
[
|
|
163
|
+
n_str?(child) && last_type.equal?(:str) && current.none?(&method(:n_begin?)),
|
|
164
|
+
last_type.equal?(:dstr),
|
|
165
|
+
n_dstr?(child) && last_type
|
|
166
|
+
].any?
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def segments
|
|
170
|
+
segments = []
|
|
171
|
+
|
|
172
|
+
segments << current = []
|
|
173
|
+
|
|
174
|
+
children.each do |child|
|
|
175
|
+
if breakpoint?(child, current)
|
|
176
|
+
segments << current = []
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
current << child
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
segments
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def emit_segment(children, index)
|
|
186
|
+
write(' ') unless index.zero?
|
|
187
|
+
|
|
188
|
+
write('"')
|
|
189
|
+
emit_body(children)
|
|
190
|
+
write('"')
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def emit_body(children)
|
|
194
|
+
buffer.root_indent do
|
|
195
|
+
children.each_with_index do |child, index|
|
|
196
|
+
if n_str?(child)
|
|
197
|
+
string = child.children.first
|
|
198
|
+
if string.eql?("\n") && children.fetch(index.pred).type.equal?(:begin)
|
|
199
|
+
write("\n")
|
|
200
|
+
else
|
|
201
|
+
write(string.inspect[1..-2])
|
|
202
|
+
end
|
|
203
|
+
else
|
|
204
|
+
emit_dynamic(child)
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end # DynamicString
|
|
210
|
+
end # Writer
|
|
211
|
+
end # Unparser
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
# Writer for rescue bodies
|
|
6
|
+
class Resbody
|
|
7
|
+
include Writer
|
|
8
|
+
|
|
9
|
+
children :exception, :assignment, :body
|
|
10
|
+
|
|
11
|
+
def emit_postcontrol
|
|
12
|
+
write(' rescue ')
|
|
13
|
+
visit(body)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def emit_regular
|
|
17
|
+
write('rescue')
|
|
18
|
+
emit_exception
|
|
19
|
+
emit_assignment
|
|
20
|
+
emit_optional_body(body)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def emit_exception
|
|
26
|
+
return unless exception
|
|
27
|
+
|
|
28
|
+
ws
|
|
29
|
+
delimited(exception.children)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def emit_assignment
|
|
33
|
+
return unless assignment
|
|
34
|
+
|
|
35
|
+
write(' => ')
|
|
36
|
+
visit(assignment)
|
|
37
|
+
end
|
|
38
|
+
end # Resbody
|
|
39
|
+
end # Writer
|
|
40
|
+
end # Unparser
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
class Rescue
|
|
6
|
+
include Writer, Adamantium
|
|
7
|
+
|
|
8
|
+
children :body, :rescue_body
|
|
9
|
+
|
|
10
|
+
define_group :rescue_bodies, 1..-2
|
|
11
|
+
|
|
12
|
+
def emit_regular
|
|
13
|
+
emit_optional_body(body)
|
|
14
|
+
|
|
15
|
+
rescue_bodies.each(&method(:emit_rescue_body))
|
|
16
|
+
|
|
17
|
+
if else_node
|
|
18
|
+
write('else')
|
|
19
|
+
emit_body(else_node)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def emit_heredoc_reminders
|
|
24
|
+
emitter(body).emit_heredoc_reminders
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def emit_postcontrol
|
|
28
|
+
visit(body)
|
|
29
|
+
writer_with(Resbody, rescue_body).emit_postcontrol
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def else_node
|
|
35
|
+
children.last
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def emit_rescue_body(node)
|
|
39
|
+
writer_with(Resbody, node).emit_regular
|
|
40
|
+
end
|
|
41
|
+
end # Rescue
|
|
42
|
+
end # Writer
|
|
43
|
+
end # Unparser
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
|
-
|
|
4
|
+
module Writer
|
|
5
5
|
class Send
|
|
6
|
-
#
|
|
6
|
+
# Writer for send as attribute assignment
|
|
7
7
|
class AttributeAssignment < self
|
|
8
|
-
include Unterminated
|
|
9
|
-
|
|
10
8
|
children :receiver, :selector, :first_argument
|
|
11
9
|
|
|
12
|
-
# Perform regular dispatch
|
|
13
|
-
#
|
|
14
|
-
# @return [undefined]
|
|
15
|
-
#
|
|
16
|
-
# @api private
|
|
17
|
-
#
|
|
18
10
|
def dispatch
|
|
19
11
|
emit_receiver
|
|
20
12
|
emit_attribute
|
|
21
|
-
write(
|
|
13
|
+
write('=')
|
|
22
14
|
|
|
23
15
|
if arguments.one?
|
|
24
16
|
visit(first_argument)
|
|
@@ -27,29 +19,22 @@ module Unparser
|
|
|
27
19
|
end
|
|
28
20
|
end
|
|
29
21
|
|
|
22
|
+
def emit_send_mlhs
|
|
23
|
+
emit_receiver
|
|
24
|
+
write(details.non_assignment_selector)
|
|
25
|
+
end
|
|
26
|
+
|
|
30
27
|
private
|
|
31
28
|
|
|
32
|
-
# Emit receiver
|
|
33
|
-
#
|
|
34
|
-
# @return [Parser::AST::Node]
|
|
35
|
-
#
|
|
36
|
-
# @api private
|
|
37
|
-
#
|
|
38
29
|
def emit_receiver
|
|
39
30
|
visit(receiver)
|
|
40
|
-
|
|
31
|
+
emit_operator
|
|
41
32
|
end
|
|
42
33
|
|
|
43
|
-
# Emit attribute
|
|
44
|
-
#
|
|
45
|
-
# @return [undefined]
|
|
46
|
-
#
|
|
47
|
-
# @api private
|
|
48
|
-
#
|
|
49
34
|
def emit_attribute
|
|
50
|
-
write(non_assignment_selector)
|
|
35
|
+
write(details.non_assignment_selector)
|
|
51
36
|
end
|
|
52
37
|
end # AttributeAssignment
|
|
53
38
|
end # Send
|
|
54
|
-
end #
|
|
39
|
+
end # Writer
|
|
55
40
|
end # Unparser
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
class Send
|
|
6
|
+
# Writer for binary sends
|
|
7
|
+
class Binary < self
|
|
8
|
+
def dispatch
|
|
9
|
+
visit(receiver)
|
|
10
|
+
emit_operator
|
|
11
|
+
emit_right
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def emit_operator
|
|
17
|
+
write(' ', details.string_selector, ' ')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def emit_right
|
|
21
|
+
emit_send_regular(children.fetch(2))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # Binary
|
|
25
|
+
end # Send
|
|
26
|
+
end # Writer
|
|
27
|
+
end # Unparser
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
class Send
|
|
6
|
+
# Writer for "conditional" receiver&.selector(arguments...) case
|
|
7
|
+
class Conditional < self
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
def dispatch
|
|
12
|
+
emit_receiver
|
|
13
|
+
emit_selector
|
|
14
|
+
emit_arguments
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def emit_receiver
|
|
18
|
+
visit(receiver)
|
|
19
|
+
write('&.')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end # Regular
|
|
23
|
+
end # Send
|
|
24
|
+
end # Writer
|
|
25
|
+
end # Unparser
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
class Send
|
|
6
|
+
# Writer for "regular" receiver.selector(arguments...) case
|
|
7
|
+
class Regular < self
|
|
8
|
+
def dispatch
|
|
9
|
+
emit_receiver
|
|
10
|
+
emit_selector
|
|
11
|
+
emit_arguments
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def emit_send_mlhs
|
|
15
|
+
dispatch
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def emit_arguments_without_heredoc_body
|
|
19
|
+
emit_normal_arguments if arguments.any?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def emit_receiver
|
|
23
|
+
return unless receiver
|
|
24
|
+
|
|
25
|
+
emit_send_regular(receiver)
|
|
26
|
+
|
|
27
|
+
emit_operator
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end # Regular
|
|
31
|
+
end # Send
|
|
32
|
+
end # Writer
|
|
33
|
+
end # Unparser
|
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
|
-
|
|
4
|
+
module Writer
|
|
5
5
|
class Send
|
|
6
|
-
#
|
|
6
|
+
# Writer for unary sends
|
|
7
7
|
class Unary < self
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
MAP = IceNine.deep_freeze(
|
|
8
|
+
MAP = {
|
|
13
9
|
'-@': '-',
|
|
14
10
|
'+@': '+'
|
|
15
|
-
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
private_constant(*constants(false))
|
|
16
14
|
|
|
17
|
-
# Perform dispatch
|
|
18
|
-
#
|
|
19
|
-
# @return [undefined]
|
|
20
|
-
#
|
|
21
|
-
# @api private
|
|
22
|
-
#
|
|
23
15
|
def dispatch
|
|
24
16
|
name = selector
|
|
17
|
+
|
|
25
18
|
write(MAP.fetch(name, name).to_s)
|
|
26
|
-
|
|
19
|
+
|
|
20
|
+
if n_int?(receiver) && selector.equal?(:+@)
|
|
27
21
|
write('+')
|
|
28
22
|
end
|
|
29
23
|
|
|
30
24
|
visit(receiver)
|
|
31
25
|
end
|
|
32
|
-
|
|
33
26
|
end # Unary
|
|
34
27
|
end # Send
|
|
35
|
-
end #
|
|
28
|
+
end # Writer
|
|
36
29
|
end # Unparser
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
# Writer for send
|
|
6
|
+
class Send
|
|
7
|
+
include Writer, Adamantium, Constants, Generation
|
|
8
|
+
|
|
9
|
+
INDEX_ASSIGN = :[]=
|
|
10
|
+
INDEX_REFERENCE = :[]
|
|
11
|
+
|
|
12
|
+
OPERATORS = {
|
|
13
|
+
csend: '&.',
|
|
14
|
+
send: '.'
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
private_constant(*constants(false))
|
|
18
|
+
|
|
19
|
+
children :receiver, :selector
|
|
20
|
+
|
|
21
|
+
def dispatch
|
|
22
|
+
effective_writer.dispatch
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def emit_mlhs
|
|
26
|
+
effective_writer.emit_send_mlhs
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def emit_selector
|
|
30
|
+
write(details.string_selector)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def emit_heredoc_reminders
|
|
34
|
+
emitter(receiver).emit_heredoc_reminders if receiver
|
|
35
|
+
arguments.each(&method(:emit_heredoc_reminder))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def effective_writer
|
|
41
|
+
writer_with(effective_writer_class, node)
|
|
42
|
+
end
|
|
43
|
+
memoize :effective_writer
|
|
44
|
+
|
|
45
|
+
def effective_writer_class
|
|
46
|
+
if details.binary_syntax_allowed?
|
|
47
|
+
Binary
|
|
48
|
+
elsif details.selector_unary_operator? && n_send?(node) && arguments.empty?
|
|
49
|
+
Unary
|
|
50
|
+
elsif write_as_attribute_assignment?
|
|
51
|
+
AttributeAssignment
|
|
52
|
+
else
|
|
53
|
+
Regular
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def write_as_attribute_assignment?
|
|
58
|
+
details.assignment_operator?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def emit_operator
|
|
62
|
+
write(OPERATORS.fetch(node.type))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def emit_arguments
|
|
66
|
+
if arguments.empty?
|
|
67
|
+
write('()') if receiver.nil? && avoid_clash?
|
|
68
|
+
else
|
|
69
|
+
emit_normal_arguments
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def arguments
|
|
74
|
+
details.arguments
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def emit_normal_arguments
|
|
78
|
+
parentheses { delimited(arguments) }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def emit_heredoc_reminder(argument)
|
|
82
|
+
emitter(argument).emit_heredoc_reminders
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def avoid_clash?
|
|
86
|
+
local_variable_clash? || parses_as_constant?
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def local_variable_clash?
|
|
90
|
+
local_variable_scope.local_variable_defined_for_node?(node, selector)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def parses_as_constant?
|
|
94
|
+
test = Unparser.parse_either(selector.to_s).from_right do
|
|
95
|
+
fail InvalidNodeError.new("Invalid selector for send node: #{selector.inspect}", node)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
n_const?(test)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def details
|
|
102
|
+
NodeDetails::Send.new(node)
|
|
103
|
+
end
|
|
104
|
+
memoize :details
|
|
105
|
+
|
|
106
|
+
def emit_send_regular(node)
|
|
107
|
+
if n_send?(node)
|
|
108
|
+
writer_with(Regular, node).dispatch
|
|
109
|
+
else
|
|
110
|
+
visit(node)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end # Send
|
|
114
|
+
end # Writer
|
|
115
|
+
end # Unparser
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
module Writer
|
|
5
|
+
include Generation, NodeHelpers
|
|
6
|
+
|
|
7
|
+
def self.included(descendant)
|
|
8
|
+
descendant.class_eval do
|
|
9
|
+
include Anima.new(:buffer, :comments, :node, :local_variable_scope)
|
|
10
|
+
|
|
11
|
+
extend DSL
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end # Writer
|
|
15
|
+
end # Unparser
|