unparser 0.4.7 → 0.5.2

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