refract 0.0.2 → 1.0.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.
Files changed (164) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE.txt +21 -0
  3. data/README.md +7 -0
  4. data/lib/refract/basic_visitor.rb +45 -0
  5. data/lib/refract/converter.rb +1204 -0
  6. data/lib/refract/formatter.rb +1304 -0
  7. data/lib/refract/mutation_visitor.rb +895 -0
  8. data/lib/refract/nodes/alias_global_variable_node.rb +14 -0
  9. data/lib/refract/nodes/alias_method_node.rb +14 -0
  10. data/lib/refract/nodes/alternation_pattern_node.rb +14 -0
  11. data/lib/refract/nodes/and_node.rb +15 -0
  12. data/lib/refract/nodes/arguments_node.rb +13 -0
  13. data/lib/refract/nodes/array_node.rb +13 -0
  14. data/lib/refract/nodes/array_pattern_node.rb +16 -0
  15. data/lib/refract/nodes/assoc_node.rb +14 -0
  16. data/lib/refract/nodes/assoc_splat_node.rb +13 -0
  17. data/lib/refract/nodes/back_reference_read_node.rb +13 -0
  18. data/lib/refract/nodes/begin_node.rb +16 -0
  19. data/lib/refract/nodes/block_argument_node.rb +13 -0
  20. data/lib/refract/nodes/block_local_variable_node.rb +13 -0
  21. data/lib/refract/nodes/block_node.rb +14 -0
  22. data/lib/refract/nodes/block_parameter_node.rb +13 -0
  23. data/lib/refract/nodes/block_parameters_node.rb +14 -0
  24. data/lib/refract/nodes/break_node.rb +13 -0
  25. data/lib/refract/nodes/call_and_write_node.rb +15 -0
  26. data/lib/refract/nodes/call_node.rb +16 -0
  27. data/lib/refract/nodes/call_operator_write_node.rb +16 -0
  28. data/lib/refract/nodes/call_or_write_node.rb +15 -0
  29. data/lib/refract/nodes/call_target_node.rb +14 -0
  30. data/lib/refract/nodes/capture_pattern_node.rb +14 -0
  31. data/lib/refract/nodes/case_match_node.rb +15 -0
  32. data/lib/refract/nodes/case_node.rb +15 -0
  33. data/lib/refract/nodes/class_node.rb +15 -0
  34. data/lib/refract/nodes/class_variable_and_write_node.rb +14 -0
  35. data/lib/refract/nodes/class_variable_operator_write_node.rb +15 -0
  36. data/lib/refract/nodes/class_variable_or_write_node.rb +14 -0
  37. data/lib/refract/nodes/class_variable_read_node.rb +13 -0
  38. data/lib/refract/nodes/class_variable_target_node.rb +13 -0
  39. data/lib/refract/nodes/class_variable_write_node.rb +14 -0
  40. data/lib/refract/nodes/constant_and_write_node.rb +14 -0
  41. data/lib/refract/nodes/constant_operator_write_node.rb +15 -0
  42. data/lib/refract/nodes/constant_or_write_node.rb +14 -0
  43. data/lib/refract/nodes/constant_path_and_write_node.rb +14 -0
  44. data/lib/refract/nodes/constant_path_node.rb +14 -0
  45. data/lib/refract/nodes/constant_path_operator_write_node.rb +15 -0
  46. data/lib/refract/nodes/constant_path_or_write_node.rb +14 -0
  47. data/lib/refract/nodes/constant_path_target_node.rb +14 -0
  48. data/lib/refract/nodes/constant_path_write_node.rb +14 -0
  49. data/lib/refract/nodes/constant_read_node.rb +13 -0
  50. data/lib/refract/nodes/constant_target_node.rb +13 -0
  51. data/lib/refract/nodes/constant_write_node.rb +14 -0
  52. data/lib/refract/nodes/def_node.rb +16 -0
  53. data/lib/refract/nodes/defined_node.rb +13 -0
  54. data/lib/refract/nodes/else_node.rb +13 -0
  55. data/lib/refract/nodes/embedded_statements_node.rb +13 -0
  56. data/lib/refract/nodes/embedded_variable_node.rb +13 -0
  57. data/lib/refract/nodes/ensure_node.rb +13 -0
  58. data/lib/refract/nodes/false_node.rb +9 -0
  59. data/lib/refract/nodes/find_pattern_node.rb +16 -0
  60. data/lib/refract/nodes/flip_flop_node.rb +15 -0
  61. data/lib/refract/nodes/float_node.rb +13 -0
  62. data/lib/refract/nodes/for_node.rb +15 -0
  63. data/lib/refract/nodes/forwarding_arguments_node.rb +9 -0
  64. data/lib/refract/nodes/forwarding_parameter_node.rb +9 -0
  65. data/lib/refract/nodes/forwarding_super_node.rb +13 -0
  66. data/lib/refract/nodes/global_variable_and_write_node.rb +14 -0
  67. data/lib/refract/nodes/global_variable_operator_write_node.rb +15 -0
  68. data/lib/refract/nodes/global_variable_or_write_node.rb +14 -0
  69. data/lib/refract/nodes/global_variable_read_node.rb +13 -0
  70. data/lib/refract/nodes/global_variable_target_node.rb +13 -0
  71. data/lib/refract/nodes/global_variable_write_node.rb +14 -0
  72. data/lib/refract/nodes/hash_node.rb +13 -0
  73. data/lib/refract/nodes/hash_pattern_node.rb +14 -0
  74. data/lib/refract/nodes/if_node.rb +16 -0
  75. data/lib/refract/nodes/imaginary_node.rb +13 -0
  76. data/lib/refract/nodes/implicit_node.rb +13 -0
  77. data/lib/refract/nodes/implicit_rest_node.rb +9 -0
  78. data/lib/refract/nodes/in_node.rb +14 -0
  79. data/lib/refract/nodes/index_and_write_node.rb +16 -0
  80. data/lib/refract/nodes/index_operator_write_node.rb +17 -0
  81. data/lib/refract/nodes/index_or_write_node.rb +16 -0
  82. data/lib/refract/nodes/index_target_node.rb +15 -0
  83. data/lib/refract/nodes/instance_variable_and_write_node.rb +14 -0
  84. data/lib/refract/nodes/instance_variable_operator_write_node.rb +15 -0
  85. data/lib/refract/nodes/instance_variable_or_write_node.rb +14 -0
  86. data/lib/refract/nodes/instance_variable_read_node.rb +13 -0
  87. data/lib/refract/nodes/instance_variable_target_node.rb +13 -0
  88. data/lib/refract/nodes/instance_variable_write_node.rb +14 -0
  89. data/lib/refract/nodes/integer_node.rb +13 -0
  90. data/lib/refract/nodes/interpolated_match_last_line_node.rb +17 -0
  91. data/lib/refract/nodes/interpolated_regular_expression_node.rb +17 -0
  92. data/lib/refract/nodes/interpolated_string_node.rb +13 -0
  93. data/lib/refract/nodes/interpolated_symbol_node.rb +13 -0
  94. data/lib/refract/nodes/interpolated_x_string_node.rb +13 -0
  95. data/lib/refract/nodes/it_local_variable_read_node.rb +9 -0
  96. data/lib/refract/nodes/it_parameters_node.rb +9 -0
  97. data/lib/refract/nodes/keyword_hash_node.rb +13 -0
  98. data/lib/refract/nodes/keyword_rest_parameter_node.rb +13 -0
  99. data/lib/refract/nodes/lambda_node.rb +14 -0
  100. data/lib/refract/nodes/local_variable_and_write_node.rb +15 -0
  101. data/lib/refract/nodes/local_variable_operator_write_node.rb +16 -0
  102. data/lib/refract/nodes/local_variable_or_write_node.rb +15 -0
  103. data/lib/refract/nodes/local_variable_read_node.rb +13 -0
  104. data/lib/refract/nodes/local_variable_target_node.rb +13 -0
  105. data/lib/refract/nodes/local_variable_write_node.rb +14 -0
  106. data/lib/refract/nodes/match_last_line_node.rb +17 -0
  107. data/lib/refract/nodes/match_predicate_node.rb +14 -0
  108. data/lib/refract/nodes/match_required_node.rb +14 -0
  109. data/lib/refract/nodes/match_write_node.rb +14 -0
  110. data/lib/refract/nodes/missing_node.rb +9 -0
  111. data/lib/refract/nodes/module_node.rb +14 -0
  112. data/lib/refract/nodes/multi_target_node.rb +15 -0
  113. data/lib/refract/nodes/multi_write_node.rb +16 -0
  114. data/lib/refract/nodes/next_node.rb +13 -0
  115. data/lib/refract/nodes/nil_node.rb +9 -0
  116. data/lib/refract/nodes/no_keywords_parameter_node.rb +9 -0
  117. data/lib/refract/nodes/numbered_parameters_node.rb +9 -0
  118. data/lib/refract/nodes/numbered_reference_read_node.rb +13 -0
  119. data/lib/refract/nodes/optional_keyword_parameter_node.rb +14 -0
  120. data/lib/refract/nodes/optional_parameter_node.rb +14 -0
  121. data/lib/refract/nodes/or_node.rb +15 -0
  122. data/lib/refract/nodes/parameters_node.rb +19 -0
  123. data/lib/refract/nodes/parentheses_node.rb +13 -0
  124. data/lib/refract/nodes/pinned_expression_node.rb +13 -0
  125. data/lib/refract/nodes/pinned_variable_node.rb +13 -0
  126. data/lib/refract/nodes/post_execution_node.rb +13 -0
  127. data/lib/refract/nodes/pre_execution_node.rb +13 -0
  128. data/lib/refract/nodes/program_node.rb +13 -0
  129. data/lib/refract/nodes/range_node.rb +15 -0
  130. data/lib/refract/nodes/rational_node.rb +14 -0
  131. data/lib/refract/nodes/redo_node.rb +9 -0
  132. data/lib/refract/nodes/regular_expression_node.rb +17 -0
  133. data/lib/refract/nodes/required_keyword_parameter_node.rb +13 -0
  134. data/lib/refract/nodes/required_parameter_node.rb +13 -0
  135. data/lib/refract/nodes/rescue_modifier_node.rb +14 -0
  136. data/lib/refract/nodes/rescue_node.rb +16 -0
  137. data/lib/refract/nodes/rest_parameter_node.rb +13 -0
  138. data/lib/refract/nodes/retry_node.rb +9 -0
  139. data/lib/refract/nodes/return_node.rb +13 -0
  140. data/lib/refract/nodes/self_node.rb +9 -0
  141. data/lib/refract/nodes/shareable_constant_node.rb +13 -0
  142. data/lib/refract/nodes/singleton_class_node.rb +14 -0
  143. data/lib/refract/nodes/source_encoding_node.rb +9 -0
  144. data/lib/refract/nodes/source_file_node.rb +9 -0
  145. data/lib/refract/nodes/source_line_node.rb +9 -0
  146. data/lib/refract/nodes/splat_node.rb +13 -0
  147. data/lib/refract/nodes/statements_node.rb +13 -0
  148. data/lib/refract/nodes/string_node.rb +13 -0
  149. data/lib/refract/nodes/super_node.rb +14 -0
  150. data/lib/refract/nodes/symbol_node.rb +13 -0
  151. data/lib/refract/nodes/true_node.rb +9 -0
  152. data/lib/refract/nodes/undef_node.rb +13 -0
  153. data/lib/refract/nodes/unless_node.rb +16 -0
  154. data/lib/refract/nodes/until_node.rb +15 -0
  155. data/lib/refract/nodes/when_node.rb +14 -0
  156. data/lib/refract/nodes/while_node.rb +15 -0
  157. data/lib/refract/nodes/x_string_node.rb +13 -0
  158. data/lib/refract/nodes/yield_node.rb +13 -0
  159. data/lib/refract/version.rb +5 -0
  160. data/lib/refract/visitor.rb +689 -0
  161. data/lib/refract.rb +50 -55
  162. data/lib/rubocop/cop/refract/ordered_visit_methods.rb +107 -0
  163. data/lib/rubocop/cop/refract_cops.rb +3 -0
  164. metadata +189 -26
@@ -0,0 +1,1304 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Refract
4
+ class Formatter < BasicVisitor
5
+ def initialize
6
+ super
7
+ @buffer = []
8
+ @source_map = []
9
+ @current_line = 1
10
+ @indent = 0
11
+ end
12
+
13
+ def around_visit(node)
14
+ if (start_line = node.start_line)
15
+ @source_map[@current_line] = start_line
16
+ end
17
+
18
+ super
19
+ end
20
+
21
+ def format_node(node)
22
+ visit(node)
23
+ @buffer.join
24
+ end
25
+
26
+ visit AliasGlobalVariableNode do |node|
27
+ push "alias"
28
+ space
29
+ visit node.new_name
30
+ space
31
+ visit node.old_name
32
+ end
33
+
34
+ visit AliasMethodNode do |node|
35
+ push "alias"
36
+ space
37
+ visit node.new_name
38
+ space
39
+ visit node.old_name
40
+ end
41
+
42
+ visit AlternationPatternNode do |node|
43
+ visit node.left
44
+ push " | "
45
+ visit node.right
46
+ end
47
+
48
+ visit AndNode do |node|
49
+ visit node.left
50
+ space
51
+ push node.operator
52
+ space
53
+ visit node.right
54
+ end
55
+
56
+ visit ArgumentsNode do |node|
57
+ visit_each(node.arguments) { push ", " }
58
+ end
59
+
60
+ visit ArrayNode do |node|
61
+ brackets do
62
+ indent do
63
+ visit_each(node.elements) { push ","; new_line }
64
+ end
65
+ new_line
66
+ end
67
+ end
68
+
69
+ visit ArrayPatternNode do |node|
70
+ visit node.constant
71
+ brackets do
72
+ visit_each(node.requireds) { push ", " }
73
+ visit(node.rest)
74
+ end
75
+ end
76
+
77
+ visit AssocNode do |node|
78
+ case node.key
79
+ when SymbolNode
80
+ push node.key.unescaped
81
+ push ":"
82
+ space unless ImplicitNode === node.value
83
+ visit node.value
84
+ else
85
+ visit node.key
86
+ push " => "
87
+ visit node.value
88
+ end
89
+ end
90
+
91
+ visit AssocSplatNode do |node|
92
+ push "**"
93
+ visit node.value
94
+ end
95
+
96
+ visit BackReferenceReadNode do |node|
97
+ push node.name
98
+ end
99
+
100
+ visit BeginNode do |node|
101
+ outdent do
102
+ push "begin"
103
+
104
+ indent do
105
+ visit node.statements
106
+ end
107
+
108
+ new_line
109
+
110
+ if node.rescue_clause
111
+ visit node.rescue_clause
112
+ new_line
113
+ end
114
+
115
+ if node.else_clause
116
+ visit node.else_clause
117
+ new_line
118
+ end
119
+
120
+ if node.ensure_clause
121
+ visit node.ensure_clause
122
+ new_line
123
+ end
124
+
125
+ push "end"
126
+ end
127
+ end
128
+
129
+ visit BlockArgumentNode do |node|
130
+ push "&"
131
+ visit node.expression
132
+ end
133
+
134
+ visit BlockLocalVariableNode do |node|
135
+ push node.name
136
+ end
137
+
138
+ visit BlockNode do |node|
139
+ braces do
140
+ case node.parameters
141
+ when nil
142
+ nil
143
+ when ItParametersNode, NumberedParametersNode
144
+ visit node.parameters
145
+ else
146
+ space
147
+ pipes do
148
+ visit node.parameters
149
+ end
150
+ end
151
+
152
+ indent do
153
+ visit node.body
154
+ end
155
+
156
+ new_line
157
+ end
158
+ end
159
+
160
+ visit BlockParameterNode do |node|
161
+ push "&"
162
+ push node.name
163
+ end
164
+
165
+ visit BlockParametersNode do |node|
166
+ visit node.parameters
167
+
168
+ if node.locals&.any?
169
+ push "; "
170
+ visit_each(node.locals) { push ", " }
171
+ end
172
+ end
173
+
174
+ visit BreakNode do |node|
175
+ push "break"
176
+ if node.arguments
177
+ space
178
+ visit node.arguments
179
+ end
180
+ end
181
+
182
+ visit CallAndWriteNode do |node|
183
+ if node.receiver
184
+ visit node.receiver
185
+ push "."
186
+ end
187
+
188
+ push node.read_name
189
+ space
190
+ push "&&="
191
+ space
192
+ visit node.value
193
+ end
194
+
195
+ visit CallNode do |node|
196
+ if node.receiver
197
+ visit node.receiver
198
+ push "."
199
+ end
200
+
201
+ push node.name
202
+
203
+ case node.block
204
+ when BlockNode
205
+ if node.arguments
206
+ parens { visit node.arguments }
207
+ end
208
+
209
+ space
210
+ visit node.block
211
+ when BlockArgumentNode
212
+ parens do
213
+ if node.arguments
214
+ visit node.arguments
215
+ push ", "
216
+ end
217
+
218
+ visit node.block
219
+ end
220
+ else
221
+ if node.arguments
222
+ parens { visit node.arguments }
223
+ end
224
+ end
225
+ end
226
+
227
+ visit CallOperatorWriteNode do |node|
228
+ if node.receiver
229
+ visit node.receiver
230
+ push "."
231
+ end
232
+
233
+ push node.read_name
234
+ space
235
+ push node.binary_operator
236
+ push "="
237
+ space
238
+ visit node.value
239
+ end
240
+
241
+ visit CallOrWriteNode do |node|
242
+ if node.receiver
243
+ visit node.receiver
244
+ push "."
245
+ end
246
+
247
+ push node.read_name
248
+ push " ||= "
249
+ visit node.value
250
+ end
251
+
252
+ visit CallTargetNode do |node|
253
+ if node.receiver
254
+ visit node.receiver
255
+ push "."
256
+ end
257
+
258
+ push node.name[0..-2]
259
+ end
260
+
261
+ visit CapturePatternNode do |node|
262
+ visit node.value
263
+ push " => "
264
+ visit node.target
265
+ end
266
+
267
+ visit CaseMatchNode do |node|
268
+ push "case "
269
+ visit node.predicate
270
+ new_line
271
+ visit_each(node.conditions) { new_line }
272
+ new_line
273
+ if node.else_clause
274
+ visit node.else_clause
275
+ new_line
276
+ end
277
+ push "end"
278
+ end
279
+
280
+ visit CaseNode do |node|
281
+ push "case "
282
+ visit node.predicate
283
+ new_line
284
+ visit_each(node.conditions) { new_line }
285
+ new_line
286
+ if node.else_clause
287
+ visit node.else_clause
288
+ new_line
289
+ end
290
+ push "end"
291
+ end
292
+
293
+ visit ClassNode do |node|
294
+ push "class"
295
+ space
296
+ visit node.constant_path
297
+ if node.superclass
298
+ push " < "
299
+ visit node.superclass
300
+ end
301
+ if node.body
302
+ indent do
303
+ visit node.body
304
+ end
305
+ end
306
+ new_line
307
+ push "end"
308
+ end
309
+
310
+ visit ClassVariableAndWriteNode do |node|
311
+ push node.name
312
+ push " &&= "
313
+ visit node.value
314
+ end
315
+
316
+ visit ClassVariableOperatorWriteNode do |node|
317
+ push node.name
318
+ push " #{node.binary_operator}= "
319
+ visit node.value
320
+ end
321
+
322
+ visit ClassVariableOrWriteNode do |node|
323
+ push node.name
324
+ push " ||= "
325
+ visit node.value
326
+ end
327
+
328
+ visit ClassVariableReadNode do |node|
329
+ push node.name
330
+ end
331
+
332
+ visit ClassVariableTargetNode do |node|
333
+ push node.name
334
+ end
335
+
336
+ visit ClassVariableWriteNode do |node|
337
+ push node.name
338
+ push " = "
339
+ visit node.value
340
+ end
341
+
342
+ visit ConstantAndWriteNode do |node|
343
+ push node.name
344
+ push " &&= "
345
+ visit node.value
346
+ end
347
+
348
+ visit ConstantOperatorWriteNode do |node|
349
+ push node.name
350
+ push " #{node.binary_operator}= "
351
+ visit node.value
352
+ end
353
+
354
+ visit ConstantOrWriteNode do |node|
355
+ push node.name
356
+ push " ||= "
357
+ visit node.value
358
+ end
359
+
360
+ visit ConstantPathAndWriteNode do |node|
361
+ visit node.target
362
+ push " &&= "
363
+ visit node.value
364
+ end
365
+
366
+ visit ConstantPathNode do |node|
367
+ visit node.parent
368
+ push "::"
369
+ push node.name
370
+ end
371
+
372
+ visit ConstantPathOperatorWriteNode do |node|
373
+ visit node.target
374
+ space
375
+ push node.binary_operator
376
+ push "= "
377
+ visit node.value
378
+ end
379
+
380
+ visit ConstantPathOrWriteNode do |node|
381
+ visit node.target
382
+ push " ||= "
383
+ visit node.value
384
+ end
385
+
386
+ visit ConstantPathTargetNode do |node|
387
+ visit node.parent if node.parent
388
+ push "::" if node.parent
389
+ push node.name
390
+ end
391
+
392
+ visit ConstantPathWriteNode do |node|
393
+ visit node.target
394
+ push " = "
395
+ visit node.value
396
+ end
397
+
398
+ visit ConstantReadNode do |node|
399
+ push node.name
400
+ end
401
+
402
+ visit ConstantTargetNode do |node|
403
+ push node.name
404
+ end
405
+
406
+ visit ConstantWriteNode do |node|
407
+ push node.name
408
+ push " = "
409
+ visit node.value
410
+ end
411
+
412
+ visit DefNode do |node|
413
+ push "def"
414
+ space
415
+
416
+ if node.receiver
417
+ visit node.receiver
418
+ push "."
419
+ end
420
+
421
+ push node.name
422
+
423
+ if node.parameters
424
+ parens do
425
+ visit node.parameters
426
+ end
427
+ end
428
+
429
+ if node.body
430
+ indent do
431
+ visit node.body
432
+ end
433
+ end
434
+
435
+ new_line
436
+
437
+ push "end"
438
+ end
439
+
440
+ visit DefinedNode do |node|
441
+ push "defined?"
442
+ parens do
443
+ visit node.value
444
+ end
445
+ end
446
+
447
+ visit ElseNode do |node|
448
+ push "else"
449
+
450
+ indent do
451
+ visit node.statements
452
+ end
453
+ end
454
+
455
+ visit EmbeddedStatementsNode do |node|
456
+ push "\#{"
457
+ visit node.statements
458
+ push "}"
459
+ end
460
+
461
+ visit EmbeddedVariableNode do |node|
462
+ push "#"
463
+ visit node.variable
464
+ end
465
+
466
+ visit EnsureNode do |node|
467
+ push "ensure"
468
+
469
+ indent do
470
+ visit node.statements
471
+ end
472
+ end
473
+
474
+ visit FalseNode do |node|
475
+ push "false"
476
+ end
477
+
478
+ visit FindPatternNode do |node|
479
+ visit node.constant
480
+ brackets do
481
+ visit_each([node.left, *node.requireds, node.right]) { push ", " }
482
+ end
483
+ end
484
+
485
+ visit FlipFlopNode do |node|
486
+ visit node.left
487
+ push node.exclude_end ? "..." : ".."
488
+ visit node.right
489
+ end
490
+
491
+ visit FloatNode do |node|
492
+ push node.value.to_s
493
+ end
494
+
495
+ visit ForNode do |node|
496
+ push "for"
497
+ space
498
+ visit node.index
499
+ push " in "
500
+ visit node.collection
501
+ indent do
502
+ visit node.statements
503
+ end
504
+ new_line
505
+ push "end"
506
+ end
507
+
508
+ visit ForwardingArgumentsNode do |node|
509
+ push "..."
510
+ end
511
+
512
+ visit ForwardingParameterNode do |node|
513
+ push "..."
514
+ end
515
+
516
+ visit ForwardingSuperNode do |node|
517
+ push "super"
518
+ visit node.block if node.block
519
+ end
520
+
521
+ visit GlobalVariableAndWriteNode do |node|
522
+ push node.name
523
+ push " &&= "
524
+ visit node.value
525
+ end
526
+
527
+ visit GlobalVariableOperatorWriteNode do |node|
528
+ push node.name
529
+ space
530
+ push node.binary_operator
531
+ push "= "
532
+ visit node.value
533
+ end
534
+
535
+ visit GlobalVariableOrWriteNode do |node|
536
+ push node.name
537
+ push " ||= "
538
+ visit node.value
539
+ end
540
+
541
+ visit GlobalVariableReadNode do |node|
542
+ push node.name
543
+ end
544
+
545
+ visit GlobalVariableTargetNode do |node|
546
+ push node.name
547
+ end
548
+
549
+ visit GlobalVariableWriteNode do |node|
550
+ push node.name
551
+ push " = "
552
+ visit node.value
553
+ end
554
+
555
+ visit HashNode do |node|
556
+ braces do
557
+ indent do
558
+ visit_each(node.elements) { push ","; new_line }
559
+ end
560
+
561
+ new_line
562
+ end
563
+ end
564
+
565
+ visit HashPatternNode do |node|
566
+ braces do
567
+ space
568
+ visit_each([*node.elements, node.rest]) { push ", " }
569
+ space
570
+ end
571
+ end
572
+
573
+ visit IfNode do |node|
574
+ if node.inline
575
+ visit node.statements
576
+ push " if "
577
+ visit node.predicate
578
+ else
579
+ # Check if this is an elsif by looking at the parent
580
+ if IfNode === @stack[-2]
581
+ push "elsif "
582
+ else
583
+ push "if "
584
+ end
585
+ visit node.predicate
586
+ if node.statements
587
+ indent do
588
+ visit node.statements
589
+ end
590
+ end
591
+ if node.subsequent
592
+ new_line
593
+ visit node.subsequent
594
+ end
595
+ unless IfNode === @stack[-2]
596
+ new_line
597
+ push "end"
598
+ end
599
+ end
600
+ end
601
+
602
+ visit ImaginaryNode do |node|
603
+ visit node.numeric
604
+ push "i"
605
+ end
606
+
607
+ visit ImplicitNode do |node|
608
+ nil
609
+ end
610
+
611
+ visit ImplicitRestNode do |node|
612
+ nil
613
+ end
614
+
615
+ visit InNode do |node|
616
+ push "in "
617
+ visit node.pattern
618
+ if node.statements
619
+ indent do
620
+ visit node.statements
621
+ end
622
+ end
623
+ end
624
+
625
+ visit IndexAndWriteNode do |node|
626
+ visit node.receiver
627
+ push "["
628
+ visit_each([node.arguments, node.block]) { push ", " }
629
+ push "] &&= "
630
+ visit node.value
631
+ end
632
+
633
+ visit IndexOperatorWriteNode do |node|
634
+ visit node.receiver
635
+ push "["
636
+ visit_each([node.arguments, node.block]) { push ", " }
637
+ push "] "
638
+ push node.binary_operator
639
+ push "= "
640
+ visit node.value
641
+ end
642
+
643
+ visit IndexOrWriteNode do |node|
644
+ visit node.receiver
645
+ push "["
646
+ visit_each([node.arguments, node.block]) { push ", " }
647
+ push "] ||= "
648
+ visit node.value
649
+ end
650
+
651
+ visit IndexTargetNode do |node|
652
+ visit node.receiver
653
+ push "["
654
+ visit_each([node.arguments, node.block]) { push ", " }
655
+ push "]"
656
+ end
657
+
658
+ visit InstanceVariableAndWriteNode do |node|
659
+ push node.name
660
+ push " &&= "
661
+ visit node.value
662
+ end
663
+
664
+ visit InstanceVariableOperatorWriteNode do |node|
665
+ push node.name
666
+ space
667
+ push node.binary_operator
668
+ push "= "
669
+ visit node.value
670
+ end
671
+
672
+ visit InstanceVariableOrWriteNode do |node|
673
+ push node.name
674
+ push " ||= "
675
+ visit node.value
676
+ end
677
+
678
+ visit InstanceVariableReadNode do |node|
679
+ push node.name
680
+ end
681
+
682
+ visit InstanceVariableTargetNode do |node|
683
+ push node.name
684
+ end
685
+
686
+ visit InstanceVariableWriteNode do |node|
687
+ push node.name
688
+ push " = "
689
+ visit node.value
690
+ end
691
+
692
+ visit IntegerNode do |node|
693
+ push node.value.to_s
694
+ end
695
+
696
+ visit InterpolatedMatchLastLineNode do |node|
697
+ push "/"
698
+ node.parts.each do |part|
699
+ case part
700
+ when StringNode
701
+ push part.unescaped.gsub("/", "\\/")
702
+ else
703
+ visit part
704
+ end
705
+ end
706
+ push "/"
707
+ end
708
+
709
+ visit InterpolatedRegularExpressionNode do |node|
710
+ push "/"
711
+ node.parts.each do |part|
712
+ case part
713
+ when StringNode
714
+ push part.unescaped.gsub("/", "\\/")
715
+ else
716
+ visit part
717
+ end
718
+ end
719
+ push "/"
720
+ push "i" if node.ignore_case
721
+ push "m" if node.multi_line
722
+ push "x" if node.extended
723
+ push "o" if node.once
724
+ end
725
+
726
+ visit InterpolatedStringNode do |node|
727
+ doubles do
728
+ node.parts.each do |part|
729
+ case part
730
+ when StringNode
731
+ push part.unescaped.gsub('"', '\"')
732
+ else
733
+ visit part
734
+ end
735
+ end
736
+ end
737
+ end
738
+
739
+ visit InterpolatedSymbolNode do |node|
740
+ push ':"'
741
+ node.parts.each do |part|
742
+ case part
743
+ when StringNode
744
+ push part.unescaped.gsub('"', '\"')
745
+ else
746
+ visit part
747
+ end
748
+ end
749
+ push '"'
750
+ end
751
+
752
+ visit InterpolatedXStringNode do |node|
753
+ push "`"
754
+ node.parts.each do |part|
755
+ case part
756
+ when StringNode
757
+ push part.unescaped.gsub("`", "\\`")
758
+ else
759
+ visit part
760
+ end
761
+ end
762
+ push "`"
763
+ end
764
+
765
+ visit ItLocalVariableReadNode do |node|
766
+ push "it"
767
+ end
768
+
769
+ visit ItParametersNode do |node|
770
+ nil
771
+ end
772
+
773
+ visit KeywordHashNode do |node|
774
+ visit_each(node.elements) { push ", " }
775
+ end
776
+
777
+ visit KeywordRestParameterNode do |node|
778
+ push "**"
779
+ push node.name
780
+ end
781
+
782
+ visit LambdaNode do |node|
783
+ push "->"
784
+
785
+ case node.parameters
786
+ when nil
787
+ nil
788
+ when ItParametersNode, NumberedParametersNode
789
+ visit node.parameters
790
+ else
791
+ space
792
+
793
+ parens do
794
+ visit node.parameters
795
+ end
796
+ end
797
+
798
+ space
799
+
800
+ braces do
801
+ indent do
802
+ visit node.body
803
+ end
804
+
805
+ new_line
806
+ end
807
+ end
808
+
809
+ visit LocalVariableAndWriteNode do |node|
810
+ push node.name
811
+ push " &&= "
812
+ visit node.value
813
+ end
814
+
815
+ visit LocalVariableOperatorWriteNode do |node|
816
+ push node.name
817
+ space
818
+ push node.binary_operator
819
+ push "= "
820
+ visit node.value
821
+ end
822
+
823
+ visit LocalVariableOrWriteNode do |node|
824
+ push node.name
825
+ push " ||= "
826
+ visit node.value
827
+ end
828
+
829
+ visit LocalVariableReadNode do |node|
830
+ push node.name
831
+ end
832
+
833
+ visit LocalVariableTargetNode do |node|
834
+ push node.name
835
+ end
836
+
837
+ visit LocalVariableWriteNode do |node|
838
+ push node.name
839
+ push " = "
840
+ visit node.value
841
+ end
842
+
843
+ visit MatchLastLineNode do |node|
844
+ push "/"
845
+ push node.unescaped.gsub("/", '\\/')
846
+ push "/"
847
+ push "i" if node.ignore_case
848
+ push "m" if node.multi_line
849
+ push "x" if node.extended
850
+ push "o" if node.once
851
+ end
852
+
853
+ visit MatchPredicateNode do |node|
854
+ visit node.value
855
+ push " in "
856
+ visit node.pattern
857
+ end
858
+
859
+ visit MatchRequiredNode do |node|
860
+ visit node.value
861
+ push " => "
862
+ visit node.pattern
863
+ end
864
+
865
+ visit MatchWriteNode do |node|
866
+ visit node.call
867
+ # Targets are written to by the match
868
+ end
869
+
870
+ visit MissingNode do |node|
871
+ # Missing nodes represent syntax errors - output nothing
872
+ end
873
+
874
+ visit ModuleNode do |node|
875
+ push "module"
876
+ space
877
+ visit node.constant_path
878
+ if node.body
879
+ indent do
880
+ visit node.body
881
+ end
882
+ end
883
+ new_line
884
+ push "end"
885
+ end
886
+
887
+ visit MultiTargetNode do |node|
888
+ visit_each([*node.lefts, node.rest, *node.rights]) { push ", " }
889
+ end
890
+
891
+ visit MultiWriteNode do |node|
892
+ visit_each([*node.lefts, node.rest, *node.rights]) { push ", " }
893
+ space unless ImplicitRestNode === node.rest
894
+ push "= "
895
+ visit node.value
896
+ end
897
+
898
+ visit NextNode do |node|
899
+ push "next"
900
+ if node.arguments
901
+ space
902
+ visit node.arguments
903
+ end
904
+ end
905
+
906
+ visit NilNode do |node|
907
+ push "nil"
908
+ end
909
+
910
+ visit NoKeywordsParameterNode do |node|
911
+ push "**nil"
912
+ end
913
+
914
+ visit NumberedParametersNode do |node|
915
+ nil
916
+ end
917
+
918
+ visit NumberedReferenceReadNode do |node|
919
+ push "$#{node.number}"
920
+ end
921
+
922
+ visit OptionalKeywordParameterNode do |node|
923
+ push node.name
924
+ push ": "
925
+ visit node.value
926
+ end
927
+
928
+ visit OptionalParameterNode do |node|
929
+ push node.name
930
+ push " = "
931
+ visit node.value
932
+ end
933
+
934
+ visit OrNode do |node|
935
+ visit node.left
936
+ space
937
+ push node.operator
938
+ space
939
+ visit node.right
940
+ end
941
+
942
+ visit ParametersNode do |node|
943
+ visit_each([
944
+ *node.requireds,
945
+ *node.optionals,
946
+ node.rest,
947
+ *node.posts,
948
+ *node.keywords,
949
+ node.keyword_rest,
950
+ node.block,
951
+ ]) { push ", " }
952
+ end
953
+
954
+ visit ParenthesesNode do |node|
955
+ parens do
956
+ visit node.body
957
+ end
958
+ end
959
+
960
+ visit PinnedExpressionNode do |node|
961
+ push "^("
962
+ visit node.expression
963
+ push ")"
964
+ end
965
+
966
+ visit PinnedVariableNode do |node|
967
+ push "^"
968
+ visit node.variable
969
+ end
970
+
971
+ visit PostExecutionNode do |node|
972
+ push "END {"
973
+ indent do
974
+ visit node.statements
975
+ end
976
+ new_line
977
+ push "}"
978
+ end
979
+
980
+ visit PreExecutionNode do |node|
981
+ push "BEGIN {"
982
+ indent do
983
+ visit node.statements
984
+ end
985
+ new_line
986
+ push "}"
987
+ end
988
+
989
+ visit ProgramNode do |node|
990
+ visit node.statements
991
+ end
992
+
993
+ visit RangeNode do |node|
994
+ visit node.left
995
+ push node.exclude_end ? "..." : ".."
996
+ visit node.right
997
+ end
998
+
999
+ visit RationalNode do |node|
1000
+ if node.denominator == 1
1001
+ push node.numerator.to_s
1002
+ push "r"
1003
+ else
1004
+ push "#{(node.numerator.to_f / node.denominator)}r"
1005
+ end
1006
+ end
1007
+
1008
+ visit RedoNode do |node|
1009
+ push "redo"
1010
+ end
1011
+
1012
+ visit RegularExpressionNode do |node|
1013
+ push "/"
1014
+ push node.unescaped.gsub("/", '\\/')
1015
+ push "/"
1016
+ push "i" if node.ignore_case
1017
+ push "m" if node.multi_line
1018
+ push "x" if node.extended
1019
+ push "o" if node.once
1020
+ end
1021
+
1022
+ visit RequiredKeywordParameterNode do |node|
1023
+ push node.name
1024
+ push ":"
1025
+ end
1026
+
1027
+ visit RequiredParameterNode do |node|
1028
+ push node.name
1029
+ end
1030
+
1031
+ visit RescueModifierNode do |node|
1032
+ visit node.expression
1033
+ push " rescue "
1034
+ visit node.rescue_expression
1035
+ end
1036
+
1037
+ visit RescueNode do |node|
1038
+ push "rescue"
1039
+ if node.exceptions&.any?
1040
+ space
1041
+ visit_each(node.exceptions) { push ", " }
1042
+ end
1043
+
1044
+ if node.reference
1045
+ push " => "
1046
+ visit node.reference
1047
+ end
1048
+
1049
+ if node.statements
1050
+ indent do
1051
+ visit node.statements
1052
+ end
1053
+ end
1054
+
1055
+ if node.subsequent
1056
+ new_line
1057
+ visit node.subsequent
1058
+ end
1059
+ end
1060
+
1061
+ visit RestParameterNode do |node|
1062
+ push "*"
1063
+ push node.name
1064
+ end
1065
+
1066
+ visit RetryNode do |node|
1067
+ push "retry"
1068
+ end
1069
+
1070
+ visit ReturnNode do |node|
1071
+ push "return"
1072
+ if node.arguments
1073
+ space
1074
+ visit node.arguments
1075
+ end
1076
+ end
1077
+
1078
+ visit SelfNode do |node|
1079
+ push "self"
1080
+ end
1081
+
1082
+ visit ShareableConstantNode do |node|
1083
+ visit node.write
1084
+ end
1085
+
1086
+ visit SingletonClassNode do |node|
1087
+ push "class << "
1088
+ visit node.expression
1089
+
1090
+ if node.body
1091
+ indent do
1092
+ visit node.body
1093
+ end
1094
+ end
1095
+
1096
+ new_line
1097
+ push "end"
1098
+ end
1099
+
1100
+ visit SourceEncodingNode do |node|
1101
+ push "__ENCODING__"
1102
+ end
1103
+
1104
+ visit SourceFileNode do |node|
1105
+ push "__FILE__"
1106
+ end
1107
+
1108
+ visit SourceLineNode do |node|
1109
+ push "__LINE__"
1110
+ end
1111
+
1112
+ visit SplatNode do |node|
1113
+ push "*"
1114
+ visit node.expression
1115
+ end
1116
+
1117
+ visit StatementsNode do |node|
1118
+ visit_each(node.body) { new_line }
1119
+ end
1120
+
1121
+ visit StringNode do |node|
1122
+ doubles do
1123
+ push node.unescaped.gsub('"', '\"')
1124
+ end
1125
+ end
1126
+
1127
+ visit SuperNode do |node|
1128
+ push "super"
1129
+ if node.arguments
1130
+ parens do
1131
+ visit node.arguments
1132
+ end
1133
+ end
1134
+ visit node.block if node.block
1135
+ end
1136
+
1137
+ visit SymbolNode do |node|
1138
+ push ":"
1139
+ push node.unescaped
1140
+ end
1141
+
1142
+ visit TrueNode do |node|
1143
+ push "true"
1144
+ end
1145
+
1146
+ visit UndefNode do |node|
1147
+ push "undef"
1148
+ space
1149
+ visit_each(node.names) { push ", " }
1150
+ end
1151
+
1152
+ visit UnlessNode do |node|
1153
+ if node.inline
1154
+ visit node.statements
1155
+ push " unless "
1156
+ visit node.predicate
1157
+ else
1158
+ push "unless "
1159
+ visit node.predicate
1160
+
1161
+ if node.statements
1162
+ indent do
1163
+ visit node.statements
1164
+ end
1165
+ end
1166
+
1167
+ if node.else_clause
1168
+ new_line
1169
+ visit node.else_clause
1170
+ end
1171
+
1172
+ new_line
1173
+ push "end"
1174
+ end
1175
+ end
1176
+
1177
+ visit UntilNode do |node|
1178
+ if node.inline
1179
+ visit node.statements
1180
+ push " until "
1181
+ visit node.predicate
1182
+ else
1183
+ push "until "
1184
+ visit node.predicate
1185
+ if node.statements
1186
+ indent do
1187
+ visit node.statements
1188
+ end
1189
+ end
1190
+ new_line
1191
+ push "end"
1192
+ end
1193
+ end
1194
+
1195
+ visit WhenNode do |node|
1196
+ push "when"
1197
+ space
1198
+ visit_each(node.conditions) { push ", " }
1199
+ indent do
1200
+ visit node.statements
1201
+ end
1202
+ end
1203
+
1204
+ visit WhileNode do |node|
1205
+ if node.inline
1206
+ visit node.statements
1207
+ push " while "
1208
+ visit node.predicate
1209
+ else
1210
+ push "while "
1211
+ visit node.predicate
1212
+ if node.statements
1213
+ indent do
1214
+ visit node.statements
1215
+ end
1216
+ end
1217
+ new_line
1218
+ push "end"
1219
+ end
1220
+ end
1221
+
1222
+ visit XStringNode do |node|
1223
+ push "`"
1224
+ push node.unescaped
1225
+ push "`"
1226
+ end
1227
+
1228
+ visit YieldNode do |node|
1229
+ push "yield"
1230
+ if node.arguments
1231
+ parens do
1232
+ visit node.arguments
1233
+ end
1234
+ end
1235
+ end
1236
+
1237
+ private def push(value)
1238
+ string = case value
1239
+ when String
1240
+ value
1241
+ when Symbol
1242
+ value.name
1243
+ end
1244
+
1245
+ @buffer << string
1246
+ end
1247
+
1248
+ private def space
1249
+ push " "
1250
+ end
1251
+
1252
+ private def new_line
1253
+ @buffer << "\n#{"\t" * @indent}"
1254
+ @current_line += 1
1255
+ end
1256
+
1257
+ private def indent
1258
+ @indent += 1
1259
+ new_line
1260
+ yield
1261
+ @indent -= 1
1262
+ nil
1263
+ end
1264
+
1265
+ private def outdent
1266
+ return yield if @indent == 0
1267
+ @indent -= 1
1268
+ new_line
1269
+ yield
1270
+ @indent += 1
1271
+ nil
1272
+ end
1273
+
1274
+ private def parens
1275
+ push "("
1276
+ yield
1277
+ push ")"
1278
+ end
1279
+
1280
+ private def braces
1281
+ push "{"
1282
+ yield
1283
+ push "}"
1284
+ end
1285
+
1286
+ private def brackets
1287
+ push "["
1288
+ yield
1289
+ push "]"
1290
+ end
1291
+
1292
+ private def pipes
1293
+ push "|"
1294
+ yield
1295
+ push "|"
1296
+ end
1297
+
1298
+ private def doubles
1299
+ push '"'
1300
+ yield
1301
+ push '"'
1302
+ end
1303
+ end
1304
+ end