unparser 0.4.9 → 0.5.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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/bin/unparser +1 -1
  3. data/lib/unparser.rb +98 -61
  4. data/lib/unparser/ast.rb +0 -1
  5. data/lib/unparser/ast/local_variable_scope.rb +6 -76
  6. data/lib/unparser/buffer.rb +19 -16
  7. data/lib/unparser/cli.rb +26 -39
  8. data/lib/unparser/color.rb +0 -3
  9. data/lib/unparser/comments.rb +0 -26
  10. data/lib/unparser/constants.rb +4 -53
  11. data/lib/unparser/diff.rb +0 -17
  12. data/lib/unparser/dsl.rb +0 -32
  13. data/lib/unparser/emitter.rb +23 -425
  14. data/lib/unparser/emitter/alias.rb +2 -8
  15. data/lib/unparser/emitter/args.rb +45 -0
  16. data/lib/unparser/emitter/argument.rb +8 -166
  17. data/lib/unparser/emitter/array.rb +27 -0
  18. data/lib/unparser/emitter/array_pattern.rb +29 -0
  19. data/lib/unparser/emitter/assignment.rb +36 -127
  20. data/lib/unparser/emitter/begin.rb +9 -84
  21. data/lib/unparser/emitter/binary.rb +7 -20
  22. data/lib/unparser/emitter/block.rb +57 -41
  23. data/lib/unparser/emitter/case.rb +6 -48
  24. data/lib/unparser/emitter/case_guard.rb +27 -0
  25. data/lib/unparser/emitter/case_match.rb +40 -0
  26. data/lib/unparser/emitter/cbase.rb +1 -3
  27. data/lib/unparser/emitter/class.rb +6 -26
  28. data/lib/unparser/emitter/const_pattern.rb +24 -0
  29. data/lib/unparser/emitter/def.rb +7 -51
  30. data/lib/unparser/emitter/defined.rb +2 -12
  31. data/lib/unparser/emitter/dstr.rb +22 -0
  32. data/lib/unparser/emitter/dsym.rb +41 -0
  33. data/lib/unparser/emitter/flipflop.rb +11 -10
  34. data/lib/unparser/emitter/float.rb +29 -0
  35. data/lib/unparser/emitter/flow_modifier.rb +8 -55
  36. data/lib/unparser/emitter/for.rb +5 -19
  37. data/lib/unparser/emitter/hash.rb +74 -0
  38. data/lib/unparser/emitter/hash_pattern.rb +67 -0
  39. data/lib/unparser/emitter/hookexe.rb +5 -11
  40. data/lib/unparser/emitter/if.rb +9 -73
  41. data/lib/unparser/emitter/in_match.rb +21 -0
  42. data/lib/unparser/emitter/in_pattern.rb +34 -0
  43. data/lib/unparser/emitter/index.rb +21 -88
  44. data/lib/unparser/emitter/kwbegin.rb +31 -0
  45. data/lib/unparser/emitter/lambda.rb +0 -8
  46. data/lib/unparser/emitter/masgn.rb +20 -0
  47. data/lib/unparser/emitter/match.rb +3 -17
  48. data/lib/unparser/emitter/match_alt.rb +23 -0
  49. data/lib/unparser/emitter/match_as.rb +21 -0
  50. data/lib/unparser/emitter/match_rest.rb +26 -0
  51. data/lib/unparser/emitter/match_var.rb +19 -0
  52. data/lib/unparser/emitter/mlhs.rb +40 -0
  53. data/lib/unparser/emitter/module.rb +3 -9
  54. data/lib/unparser/emitter/op_assign.rb +12 -27
  55. data/lib/unparser/emitter/pin.rb +19 -0
  56. data/lib/unparser/emitter/primitive.rb +93 -0
  57. data/lib/unparser/emitter/range.rb +35 -0
  58. data/lib/unparser/emitter/regexp.rb +35 -0
  59. data/lib/unparser/emitter/repetition.rb +17 -57
  60. data/lib/unparser/emitter/rescue.rb +1 -97
  61. data/lib/unparser/emitter/root.rb +17 -1
  62. data/lib/unparser/emitter/send.rb +10 -219
  63. data/lib/unparser/emitter/simple.rb +33 -0
  64. data/lib/unparser/emitter/splat.rb +2 -18
  65. data/lib/unparser/emitter/super.rb +1 -29
  66. data/lib/unparser/emitter/undef.rb +1 -9
  67. data/lib/unparser/emitter/variable.rb +1 -31
  68. data/lib/unparser/emitter/xstr.rb +72 -0
  69. data/lib/unparser/emitter/yield.rb +1 -9
  70. data/lib/unparser/generation.rb +250 -0
  71. data/lib/unparser/node_details.rb +21 -0
  72. data/lib/unparser/node_details/send.rb +62 -0
  73. data/lib/unparser/node_helpers.rb +45 -6
  74. data/lib/unparser/validation.rb +37 -35
  75. data/lib/unparser/writer.rb +15 -0
  76. data/lib/unparser/writer/binary.rb +99 -0
  77. data/lib/unparser/writer/dynamic_string.rb +229 -0
  78. data/lib/unparser/writer/resbody.rb +40 -0
  79. data/lib/unparser/writer/rescue.rb +39 -0
  80. data/lib/unparser/writer/send.rb +124 -0
  81. data/lib/unparser/{emitter → writer}/send/attribute_assignment.rb +11 -26
  82. data/lib/unparser/writer/send/binary.rb +27 -0
  83. data/lib/unparser/writer/send/conditional.rb +25 -0
  84. data/lib/unparser/writer/send/regular.rb +33 -0
  85. data/lib/unparser/{emitter → writer}/send/unary.rb +10 -17
  86. metadata +63 -31
  87. data/lib/unparser/emitter/empty.rb +0 -23
  88. data/lib/unparser/emitter/ensure.rb +0 -37
  89. data/lib/unparser/emitter/literal.rb +0 -10
  90. data/lib/unparser/emitter/literal/array.rb +0 -29
  91. data/lib/unparser/emitter/literal/dynamic.rb +0 -53
  92. data/lib/unparser/emitter/literal/dynamic_body.rb +0 -132
  93. data/lib/unparser/emitter/literal/execute_string.rb +0 -38
  94. data/lib/unparser/emitter/literal/hash.rb +0 -156
  95. data/lib/unparser/emitter/literal/primitive.rb +0 -145
  96. data/lib/unparser/emitter/literal/range.rb +0 -36
  97. data/lib/unparser/emitter/literal/regexp.rb +0 -114
  98. data/lib/unparser/emitter/literal/singleton.rb +0 -26
  99. data/lib/unparser/emitter/meta.rb +0 -16
  100. data/lib/unparser/emitter/redo.rb +0 -25
  101. data/lib/unparser/emitter/resbody.rb +0 -76
  102. data/lib/unparser/emitter/retry.rb +0 -25
  103. data/lib/unparser/emitter/send/binary.rb +0 -57
  104. data/lib/unparser/emitter/send/conditional.rb +0 -40
  105. data/lib/unparser/emitter/send/regular.rb +0 -40
  106. data/lib/unparser/preprocessor.rb +0 -159
@@ -28,9 +28,6 @@ module Unparser
28
28
 
29
29
  private
30
30
 
31
- # Initialize null color
32
- #
33
- # @return [undefined]
34
31
  def initialize; end
35
32
 
36
33
  end.new
@@ -3,8 +3,6 @@
3
3
  module Unparser
4
4
 
5
5
  # Holds the comments that remain to be emitted
6
- #
7
- # ignore :reek:RepeatedConditional
8
6
  class Comments
9
7
 
10
8
  # Proxy to singleton
@@ -113,39 +111,15 @@ module Unparser
113
111
 
114
112
  private
115
113
 
116
- # Take comments while the provided block returns true
117
- #
118
- # @yield [Parser::Source::Comment]
119
- #
120
- # @return [Array]
121
- #
122
- # @api private
123
- #
124
114
  def take_while
125
115
  number_to_take = @comments.index { |comment| !yield(comment) } || @comments.size
126
116
  @comments.shift(number_to_take)
127
117
  end
128
118
 
129
- # Take comments up to the line number
130
- #
131
- # @param [Fixnum] line
132
- #
133
- # @return [Array]
134
- #
135
- # @api private
136
- #
137
119
  def take_up_to_line(line)
138
120
  take_while { |comment| comment.location.expression.line <= line }
139
121
  end
140
122
 
141
- # Unshift document comments and return the rest
142
- #
143
- # @param [Array] comments
144
- #
145
- # @return [Array]
146
- #
147
- # @api private
148
- #
149
123
  def unshift_documents(comments)
150
124
  doc_comments, other_comments = comments.partition(&:document?)
151
125
  doc_comments.reverse_each { |comment| @comments.unshift(comment) }
@@ -2,66 +2,19 @@
2
2
 
3
3
  module Unparser
4
4
  # All unparser constants maybe included in other libraries.
5
- #
6
- # False positive since constants are frozen dynamically
7
- # to avoid duplication of `.freeze` calls
8
- #
9
- # :reek:TooManyConstants
10
5
  module Constants
11
6
 
12
- # Return frozen symbol set from enumerable
13
- #
14
- # @param [Enumerable] enumerable
15
- #
16
- # @return [Set<Symbol>]
17
- #
18
- # @api private
19
- #
20
- def self.symbol_set(enumerable)
21
- enumerable.map(&:to_sym).freeze
22
- end
23
- private_class_method :symbol_set
24
-
25
- BRACKETS_CURLY = IceNine.deep_freeze(%w[{ }])
26
- BRACKETS_ROUND = IceNine.deep_freeze(%w[( )])
27
- BRACKETS_SQUARE = IceNine.deep_freeze(%w([ ]))
28
-
29
7
  # All unary operators of the ruby language
30
- UNARY_OPERATORS = symbol_set %w[
8
+ UNARY_OPERATORS = %i[
31
9
  ! ~ -@ +@
32
- ]
10
+ ].to_set.freeze
33
11
 
34
12
  # All binary operators of the ruby language
35
- BINARY_OPERATORS = symbol_set %w[
13
+ BINARY_OPERATORS = %i[
36
14
  + - * / & | && || << >> ==
37
15
  === != <= < <=> > >= =~ !~ ^
38
16
  ** %
39
- ]
40
-
41
- COMMENT = '#'
42
-
43
- WS = ' '
44
- NL = "\n"
45
- T_DOT = '.'
46
- T_LT = '<'
47
- T_DLT = '<<'
48
- T_AMP = '&'
49
- T_ASN = '='
50
- T_SPLAT = '*'
51
- T_DSPLAT = '**'
52
- T_ASR = '=>'
53
- T_PIPE = '|'
54
- T_DCL = '::'
55
- T_NEG = '!'
56
- T_OR = '||'
57
- T_AND = '&&'
58
- T_COLON = ':'
59
-
60
- M_PO = '('
61
- M_PC = ')'
62
-
63
- SNGL_QUOTE = "'"
64
- DBL_QUOTE = '"'
17
+ ].to_set.freeze
65
18
 
66
19
  # Keywords
67
20
  K_DO = 'do'
@@ -107,8 +60,6 @@ module Unparser
107
60
  K_FILE = '__FILE__'
108
61
  K_THEN = 'then'
109
62
 
110
- DEFAULT_DELIMITER = ', '.freeze
111
-
112
63
  KEYWORDS = constants.each_with_object([]) do |name, keywords|
113
64
  value = const_get(name).freeze
114
65
  next unless name.to_s.start_with?('K_')
@@ -59,25 +59,16 @@ module Unparser
59
59
 
60
60
  private
61
61
 
62
- # Diffs between old and new
63
- #
64
- # @return [Array<Array>]
65
62
  def diffs
66
63
  ::Diff::LCS.diff(old, new)
67
64
  end
68
65
 
69
- # Raw diff-lcs hunks
70
- #
71
- # @return [Array<Diff::LCS::Hunk>]
72
66
  def hunks
73
67
  diffs.map do |diff|
74
68
  ::Diff::LCS::Hunk.new(old.map(&:dup), new, diff, max_length, 0)
75
69
  end
76
70
  end
77
71
 
78
- # Minimized hunk
79
- #
80
- # @return Diff::LCS::Hunk
81
72
  def minimized_hunk
82
73
  head, *tail = hunks
83
74
 
@@ -87,18 +78,10 @@ module Unparser
87
78
  end
88
79
  end
89
80
 
90
- # Max length of source line in new and old
91
- #
92
- # @return [Integer]
93
81
  def max_length
94
82
  [old, new].map(&:length).max
95
83
  end
96
84
 
97
- # Colorized a unified diff line
98
- #
99
- # @param [String] line
100
- #
101
- # @return [String]
102
85
  def self.colorize_line(line)
103
86
  case line[0]
104
87
  when ADDITION
@@ -6,14 +6,6 @@ module Unparser
6
6
 
7
7
  private
8
8
 
9
- # Define remaining children
10
- #
11
- # @param [Enumerable<Symbol>] names
12
- #
13
- # @return [undefined]
14
- #
15
- # @api private
16
- #
17
9
  def define_remaining_children(names)
18
10
  range = names.length..-1
19
11
  define_method(:remaining_children) do
@@ -22,15 +14,6 @@ module Unparser
22
14
  private :remaining_children
23
15
  end
24
16
 
25
- # Define named child
26
- #
27
- # @param [Symbol] name
28
- # @param [Fixnum] index
29
- #
30
- # @return [undefined]
31
- #
32
- # @api private
33
- #
34
17
  def define_child(name, index)
35
18
  define_method(name) do
36
19
  children.at(index)
@@ -38,15 +21,6 @@ module Unparser
38
21
  private name
39
22
  end
40
23
 
41
- # Define a group of children
42
- #
43
- # @param [Symbol] name
44
- # @param [Range] range
45
- #
46
- # @return [undefined]
47
- #
48
- # @api private
49
- #
50
24
  def define_group(name, range)
51
25
  define_method(name) do
52
26
  children[range]
@@ -55,12 +29,6 @@ module Unparser
55
29
  memoize(name)
56
30
  end
57
31
 
58
- # Create name helpers
59
- #
60
- # @return [undefined]
61
- #
62
- # @api private
63
- #
64
32
  def children(*names)
65
33
  define_remaining_children(names)
66
34
 
@@ -4,34 +4,20 @@ module Unparser
4
4
  UnknownNodeError = Class.new(ArgumentError)
5
5
 
6
6
  # Emitter base class
7
- #
8
- # buggy, argument values are sends to self
9
- #
10
- # ignore :reek:TooManyMethods
11
7
  class Emitter
12
- include Adamantium::Flat, AbstractType, Constants, NodeHelpers
13
- include Concord.new(:node, :parent)
14
- extend DSL
8
+ include Adamantium::Flat, AbstractType, Constants, Generation, NodeHelpers
9
+ include Anima.new(:buffer, :comments, :node, :local_variable_scope)
15
10
 
16
- # Registry for node emitters
17
- REGISTRY = {} # rubocop:disable MutableConstant
11
+ public :node
18
12
 
19
- NOINDENT = %i[rescue ensure].to_set.freeze
13
+ extend DSL
20
14
 
21
- module Unterminated
22
- def terminated?
23
- false
24
- end
25
- end
15
+ # Registry for node emitters
16
+ REGISTRY = {} # rubocop:disable Style/MutableConstant
26
17
 
27
- module Terminated
28
- def terminated?
29
- true
30
- end
31
- end
18
+ NO_INDENT = %i[ensure rescue].freeze
32
19
 
33
20
  module LocalVariableRoot
34
-
35
21
  # Return local variable root
36
22
  #
37
23
  # @return [Parser::AST::Node]
@@ -47,33 +33,8 @@ module Unparser
47
33
  memoize :local_variable_scope
48
34
  end
49
35
  end
50
-
51
36
  end # LocalVariableRoot
52
37
 
53
- # Return local variable root
54
- #
55
- # @return [Parser::AST::Node]
56
- #
57
- # @api private
58
- #
59
- def local_variable_scope
60
- parent.local_variable_scope
61
- end
62
-
63
- # Return assigned lvars
64
- #
65
- # @return [Array<Symbol>]
66
- #
67
- # @api private
68
- #
69
- abstract_method :local_variables
70
-
71
- # Return node type
72
- #
73
- # @return [Symbol]
74
- #
75
- # @api private
76
- #
77
38
  def node_type
78
39
  node.type
79
40
  end
@@ -88,25 +49,16 @@ module Unparser
88
49
  #
89
50
  def self.handle(*types)
90
51
  types.each do |type|
52
+ fail "Handler for type: #{type} already registered" if REGISTRY.key?(type)
53
+
91
54
  REGISTRY[type] = self
92
55
  end
93
56
  end
94
57
  private_class_method :handle
95
58
 
96
- # Trigger write to buffer
97
- #
98
- # @return [self]
99
- #
100
- # @api private
101
- #
102
- def write_to_buffer
103
- emit_comments_before if buffer.fresh_line?
59
+ def emit_mlhs
104
60
  dispatch
105
- comments.consume(node)
106
- emit_eof_comments if parent.is_a?(Root)
107
- self
108
61
  end
109
- memoize :write_to_buffer
110
62
 
111
63
  # Return emitter
112
64
  #
@@ -114,384 +66,30 @@ module Unparser
114
66
  #
115
67
  # @api private
116
68
  #
117
- def self.emitter(node, parent)
69
+ # rubocop:disable Metrics/ParameterLists
70
+ def self.emitter(buffer:, comments:, node:, local_variable_scope:)
118
71
  type = node.type
119
- klass = REGISTRY.fetch(type) do
120
- raise UnknownNodeError, "Unknown node type: #{type.inspect}"
121
- end
122
- klass.new(node, parent)
123
- end
124
-
125
- # Dispatch node
126
- #
127
- # @return [undefined]
128
- #
129
- # @api private
130
- #
131
- abstract_method :dispatch
132
-
133
- # Test if node is emitted as terminated expression
134
- #
135
- # @return [Boolean]
136
- #
137
- # @api private
138
- #
139
- abstract_method :terminated?
140
72
 
141
- protected
142
-
143
- # Return buffer
144
- #
145
- # @return [Buffer] buffer
146
- #
147
- # @api private
148
- #
149
- def buffer
150
- parent.buffer
151
- end
152
- memoize :buffer, freezer: :noop
153
-
154
- # Return comments
155
- #
156
- # @return [Comments] comments
157
- #
158
- # @api private
159
- #
160
- def comments
161
- parent.comments
162
- end
163
- memoize :comments, freezer: :noop
164
-
165
- private
166
-
167
- # Emit contents of block within parentheses
168
- #
169
- # @return [undefined]
170
- #
171
- # @api private
172
- #
173
- def parentheses(open = M_PO, close = M_PC)
174
- write(open)
175
- yield
176
- write(close)
177
- end
178
-
179
- # Visit node
180
- #
181
- # @param [Parser::AST::Node] node
182
- #
183
- # @return [undefined]
184
- #
185
- # @api private
186
- #
187
- def visit_plain(node)
188
- emitter = emitter(node)
189
- emitter.write_to_buffer
190
- end
191
-
192
- # Visit ambiguous node
193
- #
194
- # @param [Parser::AST::Node] node
195
- #
196
- # @return [undefined]
197
- #
198
- # @api private
199
- #
200
- def visit(node)
201
- emitter = emitter(node)
202
- conditional_parentheses(!emitter.terminated?) do
203
- emitter.write_to_buffer
204
- end
205
- end
206
-
207
- # Visit within parentheses
208
- #
209
- # @param [Parser::AST::Node] node
210
- #
211
- # @return [undefined]
212
- #
213
- # @api private
214
- #
215
- def visit_parentheses(node, *arguments)
216
- parentheses(*arguments) do
217
- visit_plain(node)
218
- end
219
- end
220
-
221
- # Call block in optional parentheses
222
- #
223
- # @param [true, false] flag
224
- #
225
- # @return [undefined]
226
- #
227
- # @api private
228
- #
229
- # ignore :reek:ControlParameter
230
- def conditional_parentheses(flag)
231
- if flag
232
- parentheses { yield }
233
- else
234
- yield
235
- end
236
- end
237
-
238
- # Return emitter for node
239
- #
240
- # @param [Parser::AST::Node] node
241
- #
242
- # @return [Emitter]
243
- #
244
- # @api private
245
- #
246
- def emitter(node)
247
- self.class.emitter(node, self)
248
- end
249
-
250
- # Emit delimited body
251
- #
252
- # @param [Enumerable<Parser::AST::Node>] nodes
253
- #
254
- # @return [undefined]
255
- #
256
- # @api private
257
- #
258
- def delimited_plain(nodes)
259
- delimited(nodes, &method(:visit_plain))
260
- end
261
-
262
- # Emit delimited body
263
- #
264
- # @param [Enumerable<Parser::AST::Node>] nodes
265
- #
266
- # @return [undefined]
267
- #
268
- # @api private
269
- #
270
- def delimited(nodes, &block)
271
- return if nodes.empty?
272
-
273
- block ||= method(:visit)
274
- head, *tail = nodes
275
- block.call(head)
276
- tail.each do |node|
277
- write(DEFAULT_DELIMITER)
278
- block.call(node)
279
- end
280
- end
281
-
282
- # Return children of node
283
- #
284
- # @return [Array<Parser::AST::Node>]
285
- #
286
- # @api private
287
- #
288
- def children
289
- node.children
290
- end
291
-
292
- # Write newline
293
- #
294
- # @return [undefined]
295
- #
296
- # @api private
297
- #
298
- def nl
299
- emit_eol_comments
300
- buffer.nl
301
- end
302
-
303
- # Write comments that appeared before source_part in the source
304
- #
305
- # @param [Symbol] source_part
306
- #
307
- # @return [undefined]
308
- #
309
- # @api private
310
- #
311
- def emit_comments_before(source_part = :expression)
312
- comments_before = comments.take_before(node, source_part)
313
- return if comments_before.empty?
314
-
315
- emit_comments(comments_before)
316
- buffer.nl
317
- end
318
-
319
- # Write end-of-line comments
320
- #
321
- # @return [undefined]
322
- #
323
- # @api private
324
- #
325
- def emit_eol_comments
326
- comments.take_eol_comments.each do |comment|
327
- write(WS, comment.text)
328
- end
329
- end
330
-
331
- # Write end-of-file comments
332
- #
333
- # @return [undefined]
334
- #
335
- # @api private
336
- #
337
- def emit_eof_comments
338
- emit_eol_comments
339
- comments_left = comments.take_all
340
- return if comments_left.empty?
341
-
342
- buffer.nl
343
- emit_comments(comments_left)
344
- end
345
-
346
- # Write each comment to a separate line
347
- #
348
- # @param [Array] comments
349
- #
350
- # @return [undefined]
351
- #
352
- # @api private
353
- #
354
- def emit_comments(comments)
355
- max = comments.size - 1
356
- comments.each_with_index do |comment, index|
357
- if comment.type.equal?(:document)
358
- buffer.append_without_prefix(comment.text.chomp)
359
- else
360
- write(comment.text)
361
- end
362
- buffer.nl if index < max
363
- end
364
- end
365
-
366
- # Write strings into buffer
367
- #
368
- # @return [undefined]
369
- #
370
- # @api private
371
- #
372
- def write(*strings)
373
- strings.each do |string|
374
- buffer.append(string)
375
- end
376
- end
377
-
378
- # Write end keyword
379
- #
380
- # @return [undefined]
381
- #
382
- # @api private
383
- #
384
- def k_end
385
- buffer.indent
386
- emit_comments_before(:end)
387
- buffer.unindent
388
- write(K_END)
389
- end
390
-
391
- # Return first child
392
- #
393
- # @return [Parser::AST::Node]
394
- # if present
395
- #
396
- # @return [nil]
397
- # otherwise
398
- #
399
- # @api private
400
- #
401
- def first_child
402
- children.first
403
- end
404
-
405
- # Write whitespace
406
- #
407
- # @return [undefined]
408
- #
409
- # @api private
410
- #
411
- def ws
412
- write(WS)
413
- end
414
-
415
- # Call emit contents of block indented
416
- #
417
- # @return [undefined]
418
- #
419
- # @api private
420
- #
421
- # False positive:
422
- #
423
- def indented
424
- buffer = buffer()
425
- buffer.indent
426
- nl
427
- yield
428
- nl
429
- buffer.unindent
430
- end
431
-
432
- # Emit non nil body
433
- #
434
- # @param [Parser::AST::Node] body
435
- #
436
- # @return [undefined]
437
- #
438
- # @api private
439
- #
440
- # rubocop:disable MethodCallWithoutArgsParentheses
441
- def emit_body(body = body())
442
- unless body
443
- buffer.indent
444
- nl
445
- buffer.unindent
446
- return
447
- end
448
- visit_indented(body)
449
- end
450
- # rubocop:enable MethodCallWithoutArgsParentheses
451
-
452
- # Visit indented node
453
- #
454
- # @param [Parser::AST::Node] node
455
- #
456
- # @return [undefined]
457
- #
458
- # @api private
459
- #
460
- def visit_indented(node)
461
- if NOINDENT.include?(node.type)
462
- visit_plain(node)
463
- else
464
- indented { visit_plain(node) }
73
+ klass = REGISTRY.fetch(type) do
74
+ fail UnknownNodeError, "Unknown node type: #{type.inspect}"
465
75
  end
466
- end
467
76
 
468
- # Return parent type
469
- #
470
- # @return [Symbol]
471
- # if parent is present
472
- #
473
- # @return [nil]
474
- # otherwise
475
- #
476
- # @api private
477
- #
478
- def parent_type
479
- parent.node_type
77
+ klass.new(
78
+ buffer: buffer,
79
+ comments: comments,
80
+ local_variable_scope: local_variable_scope,
81
+ node: node
82
+ )
480
83
  end
84
+ # rubocop:enable Metrics/ParameterLists
481
85
 
482
- # Delegate to emitter
483
- #
484
- # @param [Class:Emitter] emitter
86
+ # Dispatch node write as statement
485
87
  #
486
88
  # @return [undefined]
487
89
  #
488
90
  # @api private
489
91
  #
490
- # rubocop:disable MethodCallWithoutArgsParentheses
491
- def run(emitter, node = node())
492
- emitter.new(node, self).write_to_buffer
493
- end
494
- # rubocop:enable MethodCallWithoutArgsParentheses
92
+ abstract_method :dispatch
495
93
 
496
94
  end # Emitter
497
95
  end # Unparser