unparser 0.1.5 → 0.1.6

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +38 -2
  3. data/.travis.yml +3 -6
  4. data/Changelog.md +7 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.devtools +22 -17
  7. data/README.md +3 -4
  8. data/TODO +3 -2
  9. data/bin/unparser +10 -0
  10. data/circle.yml +2 -0
  11. data/config/flay.yml +1 -1
  12. data/config/flog.yml +1 -1
  13. data/config/reek.yml +10 -0
  14. data/config/rubocop.yml +9 -17
  15. data/lib/unparser.rb +8 -1
  16. data/lib/unparser/buffer.rb +2 -0
  17. data/lib/unparser/cli.rb +113 -0
  18. data/lib/unparser/cli/differ.rb +30 -0
  19. data/lib/unparser/cli/preprocessor.rb +196 -0
  20. data/lib/unparser/cli/source.rb +118 -0
  21. data/lib/unparser/comments.rb +64 -23
  22. data/lib/unparser/constants.rb +19 -7
  23. data/lib/unparser/emitter.rb +23 -25
  24. data/lib/unparser/emitter/alias.rb +2 -0
  25. data/lib/unparser/emitter/argument.rb +2 -0
  26. data/lib/unparser/emitter/assignment.rb +3 -1
  27. data/lib/unparser/emitter/begin.rb +3 -6
  28. data/lib/unparser/emitter/binary.rb +2 -0
  29. data/lib/unparser/emitter/block.rb +2 -0
  30. data/lib/unparser/emitter/break.rb +4 -5
  31. data/lib/unparser/emitter/case.rb +2 -0
  32. data/lib/unparser/emitter/cbase.rb +2 -0
  33. data/lib/unparser/emitter/class.rb +4 -3
  34. data/lib/unparser/emitter/def.rb +2 -0
  35. data/lib/unparser/emitter/defined.rb +2 -0
  36. data/lib/unparser/emitter/empty.rb +2 -0
  37. data/lib/unparser/emitter/ensure.rb +2 -0
  38. data/lib/unparser/emitter/flipflop.rb +2 -0
  39. data/lib/unparser/emitter/for.rb +2 -0
  40. data/lib/unparser/emitter/hookexe.rb +2 -0
  41. data/lib/unparser/emitter/if.rb +2 -0
  42. data/lib/unparser/emitter/literal.rb +2 -0
  43. data/lib/unparser/emitter/literal/array.rb +33 -0
  44. data/lib/unparser/emitter/literal/dynamic.rb +21 -1
  45. data/lib/unparser/emitter/literal/dynamic_body.rb +9 -5
  46. data/lib/unparser/emitter/literal/execute_string.rb +2 -0
  47. data/lib/unparser/emitter/literal/hash.rb +136 -0
  48. data/lib/unparser/emitter/literal/primitive.rb +4 -2
  49. data/lib/unparser/emitter/literal/range.rb +2 -0
  50. data/lib/unparser/emitter/literal/regexp.rb +4 -2
  51. data/lib/unparser/emitter/literal/singleton.rb +2 -0
  52. data/lib/unparser/emitter/match.rb +2 -0
  53. data/lib/unparser/emitter/module.rb +2 -3
  54. data/lib/unparser/emitter/next.rb +2 -0
  55. data/lib/unparser/emitter/op_assign.rb +3 -1
  56. data/lib/unparser/emitter/redo.rb +2 -0
  57. data/lib/unparser/emitter/repetition.rb +2 -0
  58. data/lib/unparser/emitter/resbody.rb +2 -0
  59. data/lib/unparser/emitter/rescue.rb +2 -0
  60. data/lib/unparser/emitter/retry.rb +2 -0
  61. data/lib/unparser/emitter/return.rb +19 -4
  62. data/lib/unparser/emitter/root.rb +13 -0
  63. data/lib/unparser/emitter/send.rb +26 -22
  64. data/lib/unparser/emitter/send/arguments.rb +46 -0
  65. data/lib/unparser/emitter/send/attribute_assignment.rb +35 -0
  66. data/lib/unparser/emitter/send/binary.rb +2 -0
  67. data/lib/unparser/emitter/send/index.rb +2 -0
  68. data/lib/unparser/emitter/send/regular.rb +4 -2
  69. data/lib/unparser/emitter/send/unary.rb +3 -1
  70. data/lib/unparser/emitter/splat.rb +2 -0
  71. data/lib/unparser/emitter/super.rb +2 -0
  72. data/lib/unparser/emitter/undef.rb +2 -0
  73. data/lib/unparser/emitter/variable.rb +2 -0
  74. data/lib/unparser/emitter/yield.rb +2 -0
  75. data/lib/unparser/finalize.rb +2 -0
  76. data/lib/unparser/node_helpers.rb +19 -0
  77. data/spec/spec_helper.rb +10 -0
  78. data/spec/unit/unparser/buffer/append_spec.rb +2 -0
  79. data/spec/unit/unparser/buffer/append_without_prefix_spec.rb +2 -0
  80. data/spec/unit/unparser/buffer/capture_content_spec.rb +2 -0
  81. data/spec/unit/unparser/buffer/content_spec.rb +3 -1
  82. data/spec/unit/unparser/buffer/fresh_line_spec.rb +2 -0
  83. data/spec/unit/unparser/buffer/indent_spec.rb +3 -1
  84. data/spec/unit/unparser/buffer/nl_spec.rb +2 -0
  85. data/spec/unit/unparser/buffer/unindent_spec.rb +2 -0
  86. data/spec/unit/unparser/comments/consume_spec.rb +2 -1
  87. data/spec/unit/unparser/comments/take_all_spec.rb +2 -1
  88. data/spec/unit/unparser/comments/take_before_spec.rb +6 -5
  89. data/spec/unit/unparser/comments/take_eol_comments_spec.rb +2 -1
  90. data/spec/unit/unparser/emitter/class_methods/handle_spec.rb +2 -0
  91. data/spec/unit/unparser_spec.rb +110 -57
  92. data/unparser.gemspec +5 -4
  93. metadata +32 -12
  94. data/bin/test-unparser +0 -26
  95. data/lib/unparser/emitter/literal/composed.rb +0 -64
  96. data/spec/unit/unparser/comments/skip_eol_comment_spec.rb +0 -29
@@ -1,18 +1,22 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  # All unparser constants maybe included in other libraries.
3
5
  module Constants
4
6
 
7
+ # All unary operators of the ruby language
5
8
  UNARY_OPERATORS = %w(
6
9
  ! ~ -@ +@
7
10
  ).map(&:to_sym).to_set
8
11
 
12
+ # All binary operators of the ruby language
9
13
  BINARY_OPERATORS = %w(
10
14
  + - * / & | && || << >> ==
11
15
  === != <= < <=> > >= =~ !~ ^
12
16
  ** %
13
17
  ).map(&:to_sym).to_set
14
18
 
15
- COMMENT = '#'.freeze
19
+ COMMENT = '#'
16
20
 
17
21
  WS = ' '
18
22
  NL = "\n"
@@ -34,6 +38,10 @@ module Unparser
34
38
  M_PO = '('
35
39
  M_PC = ')'
36
40
 
41
+ SNGL_QUOTE = "'"
42
+ DBL_QUOTE = '"'
43
+
44
+ # Keywords
37
45
  K_DO = 'do'
38
46
  K_DEF = 'def'
39
47
  K_END = 'end'
@@ -77,12 +85,16 @@ module Unparser
77
85
  K_FILE = '__FILE__'
78
86
  K_THEN = 'then'
79
87
 
80
- TERMINATED = [
81
- :int, :float, :self, :kwbegin, :const, :regexp, :args, :lvar,
82
- :ivar, :gvar, :cvar, :if, :case, :module, :class, :sclass, :super,
83
- :yield, :zsuper, :break, :next, :defined?, :str, :block, :while, :loop, :until,
84
- :def, :defs, :true, :false, :nil, :array, :hash, :sym, :return
85
- ].to_set
88
+ # Nodes that can be emitted in tokens that terminate their expression.
89
+ #
90
+ # These nodes dont require parentheses to be exactly reproduced in context of a more complex expression.
91
+ #
92
+ TERMINATED = %w(
93
+ int float self kwbegin const regexp args lvar
94
+ ivar gvar cvar if case module class sclass super
95
+ yield zsuper break next defined? str block while loop until
96
+ def defs true false nil array hash sym return
97
+ ).map(&:to_sym).to_set
86
98
 
87
99
  KEYWORDS = constants.each_with_object([]) do |name, keywords|
88
100
  value = const_get(name).freeze
@@ -1,8 +1,10 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
 
3
5
  # Emitter base class
4
6
  class Emitter
5
- include Adamantium::Flat, AbstractType, Constants
7
+ include Adamantium::Flat, AbstractType, Constants, NodeHelpers
6
8
  include Concord.new(:node, :parent)
7
9
 
8
10
  # Registry for node emitters
@@ -14,6 +16,16 @@ module Unparser
14
16
 
15
17
  CURLY_BRACKETS = IceNine.deep_freeze(%w({ }))
16
18
 
19
+ # Return node type
20
+ #
21
+ # @return [Symbol]
22
+ #
23
+ # @api private
24
+ #
25
+ def node_type
26
+ node.type
27
+ end
28
+
17
29
  # Define remaining children
18
30
  #
19
31
  # @param [Enumerable<Symbol>] names
@@ -201,7 +213,6 @@ module Unparser
201
213
  conditional_parentheses(!emitter.terminated?) do
202
214
  emitter.write_to_buffer
203
215
  end
204
- emitter.write_to_buffer
205
216
  end
206
217
 
207
218
  # Visit within parentheses
@@ -256,10 +267,12 @@ module Unparser
256
267
  # @api private
257
268
  #
258
269
  def delimited(nodes, delimiter = DEFAULT_DELIMITER)
259
- max = nodes.length - 1
260
- nodes.each_with_index do |node, index|
270
+ return if nodes.empty?
271
+ head, *tail = nodes
272
+ visit(head)
273
+ tail.each do |node|
274
+ write(delimiter)
261
275
  visit(node)
262
- write(delimiter) if index < max
263
276
  end
264
277
  end
265
278
 
@@ -456,34 +469,19 @@ module Unparser
456
469
  # @api private
457
470
  #
458
471
  def parent_type
459
- parent && parent.node && parent.node.type
472
+ parent.node_type
460
473
  end
461
474
 
462
- # Helper for building nodes
475
+ # Delegate to emitter
463
476
  #
464
- # @param [Symbol]
465
- #
466
- # @return [Parser::AST::Node]
467
- #
468
- # @api private
469
- #
470
- def s(type, *children)
471
- Parser::AST::Node.new(type, *children)
472
- end
473
-
474
- # Helper to introduce an end-of-line comment
477
+ # @param [Class:Emitter] emitter
475
478
  #
476
479
  # @return [undefined]
477
480
  #
478
481
  # @api private
479
482
  #
480
- def eol_comment
481
- write(WS)
482
- comment = buffer.capture_content do
483
- write(COMMENT, WS)
484
- yield
485
- end
486
- comments.skip_eol_comment(comment)
483
+ def run(emitter, node = node)
484
+ emitter.new(node, self).write_to_buffer
487
485
  end
488
486
 
489
487
  end # Emitter
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for alias nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -75,7 +77,7 @@ module Unparser
75
77
  def emit_left
76
78
  if base
77
79
  visit(base)
78
- write(T_DCL)
80
+ write(T_DCL) if base.type != :cbase
79
81
  end
80
82
  write(name.to_s)
81
83
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -15,12 +17,7 @@ module Unparser
15
17
  # @api private
16
18
  #
17
19
  def emit_inner
18
- childs = children
19
- max = childs.length - 1
20
- childs.each_with_index do |child, index|
21
- visit(child)
22
- nl if index < max
23
- end
20
+ delimited(children, NL)
24
21
  end
25
22
 
26
23
  # Emitter for implicit begins
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Base class for binary emitters
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1,12 +1,12 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for break nodes
4
- class Break < self
6
+ class Break < Return
5
7
 
6
8
  handle :break
7
9
 
8
- children :arguments
9
-
10
10
  private
11
11
 
12
12
  # Perform dispatch
@@ -18,8 +18,7 @@ module Unparser
18
18
  def dispatch
19
19
  conditional_parentheses(parent_type == :or || parent_type == :and) do
20
20
  write(K_BREAK)
21
- return unless arguments
22
- visit_parentheses(arguments)
21
+ emit_break_return_arguments
23
22
  end
24
23
  end
25
24
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for case nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for toplevel constant reference nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for class nodes
@@ -21,9 +23,6 @@ module Unparser
21
23
  emit_superclass
22
24
  emit_body
23
25
  k_end
24
- unless parent_type == :send
25
- eol_comment { visit(name) }
26
- end
27
26
  end
28
27
 
29
28
  # Emit superclass
@@ -47,6 +46,8 @@ module Unparser
47
46
 
48
47
  children :object, :body
49
48
 
49
+ private
50
+
50
51
  # Perform dispatch
51
52
  #
52
53
  # @return [undefined]
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for def node
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for defined? nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for flip flops
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for for nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Base class for pre and postexe emitters
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter if nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Namespace class for literal emiters
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ module Unparser
4
+ class Emitter
5
+ class Literal
6
+
7
+ # Array literal emitter
8
+ class Array < self
9
+ OPEN = '['.freeze
10
+ CLOSE = ']'.freeze
11
+ DELIMITER = ', '.freeze
12
+
13
+ handle :array
14
+
15
+ private
16
+
17
+ # Perform dispatch
18
+ #
19
+ # @return [undefined]
20
+ #
21
+ # @api private
22
+ #
23
+ def dispatch
24
+ parentheses(OPEN, CLOSE) do
25
+ delimited(children, DELIMITER)
26
+ end
27
+ end
28
+
29
+ end # Array
30
+
31
+ end # Literal
32
+ end # Emitter
33
+ end # Unparser
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -15,7 +17,25 @@ module Unparser
15
17
  #
16
18
  def dispatch
17
19
  util = self.class
18
- visit_parentheses(dynamic_body, util::OPEN, util::CLOSE)
20
+ if interpolation?
21
+ visit_parentheses(dynamic_body, util::OPEN, util::CLOSE)
22
+ else
23
+ delimited(children, WS)
24
+ end
25
+ end
26
+
27
+ # Test for interpolation
28
+ #
29
+ # @return [true]
30
+ # if dynamic component was interpolated
31
+ #
32
+ # @return [false]
33
+ # otherwise
34
+ #
35
+ # @api private
36
+ #
37
+ def interpolation?
38
+ children.any? { |child| child.type != :str }
19
39
  end
20
40
 
21
41
  # Return dynamic body
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -61,9 +63,11 @@ module Unparser
61
63
  emit_interpolated_segment(node)
62
64
  end
63
65
 
64
- ESCAPES = IceNine.deep_freeze(
65
- "\n" => '\n'
66
- )
66
+ pairs = Parser::Lexer::ESCAPES.invert.map do |key, value|
67
+ [key, "\\#{value}"] unless key == WS
68
+ end.compact
69
+
70
+ ESCAPES = ::Hash[pairs]
67
71
 
68
72
  REPLACEMENTS = ::Regexp.union(ESCAPES.keys)
69
73
 
@@ -79,8 +83,8 @@ module Unparser
79
83
  util = self.class
80
84
  string = node.children.first
81
85
  segment = string
82
- .gsub(util::DELIMITER, util::REPLACEMENT)
83
86
  .gsub(REPLACEMENTS, ESCAPES)
87
+ .gsub(util::DELIMITER, util::REPLACEMENT)
84
88
  write(segment)
85
89
  end
86
90
 
@@ -112,7 +116,7 @@ module Unparser
112
116
  handle :dyn_regexp_body
113
117
 
114
118
  DELIMITER = '/'.freeze
115
- REPLACEMENT = '/'.freeze
119
+ REPLACEMENT = '\/'.freeze
116
120
 
117
121
  end # Regexp
118
122