unparser 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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