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,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -0,0 +1,136 @@
1
+ # encoding: utf-8
2
+
3
+ module Unparser
4
+ class Emitter
5
+ class Literal
6
+
7
+ # Abstract namespace class for hash pair emitters
8
+ class HashPair < self
9
+
10
+ # Pair emitter that emits hash-rocket separated key values
11
+ class Rocket < self
12
+ HASHROCKET = ' => '.freeze
13
+
14
+ handle :pair_rocket, :pair
15
+
16
+ private
17
+
18
+ # Perform dispatch
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ #
24
+ def dispatch
25
+ delimited(children, HASHROCKET)
26
+ end
27
+
28
+ end # Rocket
29
+
30
+ # Pair emitter that emits colon separated key values
31
+ class Colon < self
32
+ COLON = ': '.freeze
33
+
34
+ handle :pair_colon
35
+
36
+ children :key, :value
37
+
38
+ private
39
+
40
+ # Perform dispatch
41
+ #
42
+ # @return [undefined]
43
+ #
44
+ # @api private
45
+ #
46
+ def dispatch
47
+ write(key.children.first.to_s, COLON)
48
+ visit(value)
49
+ end
50
+
51
+ end # Colon
52
+
53
+ end # HashPair
54
+
55
+ # Emitter for hash bodies
56
+ class HashBody < self
57
+
58
+ DELIMITER = ', '.freeze
59
+ BAREWORD = /\A[A-Za-z_][A-Za-z_0-9]*[?!]?\z/.freeze
60
+
61
+ handle :hash_body
62
+
63
+ private
64
+
65
+ # Perform dispatch
66
+ #
67
+ # @return [undefined]
68
+ #
69
+ # @api private
70
+ #
71
+ def dispatch
72
+ delimited(effective_body, DELIMITER)
73
+ end
74
+
75
+ # Return effective body
76
+ #
77
+ # @return [Enumerable<Parser::AST::Node>]
78
+ #
79
+ # @api private
80
+ #
81
+ def effective_body
82
+ children.map do |pair|
83
+ key, _value = *pair
84
+ if key.type == :sym && key.children.first.to_s =~ BAREWORD
85
+ s(:pair_colon, pair.children)
86
+ else
87
+ s(:pair_rocket, pair.children)
88
+ end
89
+ end
90
+ end
91
+
92
+ end # HashBody
93
+
94
+ # Emitter for Hash literals
95
+ class Hash < self
96
+
97
+ DELIMITER = ', '.freeze
98
+ OPEN = '{'.freeze
99
+ CLOSE = '}'.freeze
100
+
101
+ handle :hash
102
+
103
+ private
104
+
105
+ # Perform dispatch
106
+ #
107
+ # @return [undefined]
108
+ #
109
+ # @api private
110
+ #
111
+ def dispatch
112
+ if children.empty?
113
+ write(OPEN, CLOSE)
114
+ else
115
+ emit_hash_body
116
+ end
117
+ end
118
+
119
+ # Emit hash body
120
+ #
121
+ # @return [undefined]
122
+ #
123
+ # @api private
124
+ #
125
+ def emit_hash_body
126
+ parentheses(OPEN, CLOSE) do
127
+ write(WS)
128
+ run(HashBody)
129
+ write(WS)
130
+ end
131
+ end
132
+
133
+ end # Hash
134
+ end # Literal
135
+ end # Emitter
136
+ end # Unparser
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -12,7 +14,7 @@ module Unparser
12
14
  # Emitter for primitives based on Object#inspect
13
15
  class Inspect < self
14
16
 
15
- handle :float, :sym, :int
17
+ handle :float, :int, :sym
16
18
 
17
19
  private
18
20
 
@@ -23,7 +25,7 @@ module Unparser
23
25
  # @api private
24
26
  #
25
27
  def dispatch
26
- buffer.append(value.inspect)
28
+ write(value.inspect)
27
29
  end
28
30
 
29
31
  end # Inspect
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -46,7 +48,7 @@ module Unparser
46
48
  def write_body(node)
47
49
  case node.type
48
50
  when :str
49
- write(escape(node).children.first)
51
+ buffer.append_without_prefix(escape(node).children.first)
50
52
  else
51
53
  visit(s(:interpolated, [node]))
52
54
  end
@@ -95,7 +97,7 @@ module Unparser
95
97
  def delimiter
96
98
  location = node.location
97
99
  return DELIMITER unless location
98
- location.expression.source[-1]
100
+ location.end.source[-1]
99
101
  end
100
102
  memoize :delimiter
101
103
 
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  class Literal
@@ -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 module nodes
@@ -20,9 +22,6 @@ module Unparser
20
22
  visit(name)
21
23
  emit_body
22
24
  k_end
23
- if parent_type != :send
24
- eol_comment { visit(name) }
25
- end
26
25
  end
27
26
 
28
27
  end # Module
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for next nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
 
@@ -24,7 +26,7 @@ module Unparser
24
26
  def dispatch
25
27
  visit(target)
26
28
  write(WS, MAP.fetch(node.type), WS)
27
- visit(expression)
29
+ visit_terminated(expression)
28
30
  end
29
31
 
30
32
  end # BinaryAssign
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for redo 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
  # Emitter for rescue body nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for rescue nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for retry nodes
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for return nodes
@@ -5,8 +7,6 @@ module Unparser
5
7
 
6
8
  handle :return
7
9
 
8
- children :argument
9
-
10
10
  private
11
11
 
12
12
  # Perform dispatch
@@ -17,8 +17,23 @@ module Unparser
17
17
  #
18
18
  def dispatch
19
19
  write(K_RETURN)
20
- return unless argument
21
- visit_parentheses(argument)
20
+ emit_break_return_arguments
21
+ end
22
+
23
+ # Emit break or return arguments
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ #
29
+ def emit_break_return_arguments
30
+ return if children.empty?
31
+ head, *tail = children
32
+ parentheses { visit(head) }
33
+ tail.each do |node|
34
+ write(DEFAULT_DELIMITER)
35
+ parentheses { visit(node) }
36
+ end
22
37
  end
23
38
 
24
39
  end # Return
@@ -1,8 +1,21 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Root emitter a special case
4
6
  class Root < self
5
7
  include Concord::Public.new(:buffer, :comments)
8
+
9
+ # Return root node type
10
+ #
11
+ # @return [nil]
12
+ #
13
+ # @api private
14
+ #
15
+ def node_type
16
+ nil
17
+ end
18
+
6
19
  end # Root
7
20
  end # Emitter
8
21
  end # Unparser
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  module Unparser
2
4
  class Emitter
3
5
  # Emitter for send
@@ -71,10 +73,12 @@ module Unparser
71
73
  # @api private
72
74
  #
73
75
  def non_index_emitter
74
- if binary?
76
+ if binary_operator?
75
77
  Binary
76
- elsif unary?
78
+ elsif unary_operator?
77
79
  Unary
80
+ elsif attribute_assignment?
81
+ AttributeAssignment
78
82
  else
79
83
  Regular
80
84
  end
@@ -91,18 +95,6 @@ module Unparser
91
95
  end
92
96
  memoize :string_selector
93
97
 
94
- # Delegate to emitter
95
- #
96
- # @param [Class:Emitter] emitter
97
- #
98
- # @return [undefined]
99
- #
100
- # @api private
101
- #
102
- def run(emitter)
103
- emitter.new(node, self).write_to_buffer
104
- end
105
-
106
98
  # Test for unary operator implemented as method
107
99
  #
108
100
  # @return [true]
@@ -113,7 +105,7 @@ module Unparser
113
105
  #
114
106
  # @api private
115
107
  #
116
- def unary?
108
+ def unary_operator?
117
109
  UNARY_OPERATORS.include?(selector)
118
110
  end
119
111
 
@@ -127,8 +119,8 @@ module Unparser
127
119
  #
128
120
  # @api private
129
121
  #
130
- def binary?
131
- BINARY_OPERATORS.include?(selector) && arguments.length == 1 && arguments.first.type != :splat
122
+ def binary_operator?
123
+ BINARY_OPERATORS.include?(selector) && arguments.one? && arguments.first.type != :splat
132
124
  end
133
125
 
134
126
  # Emit selector
@@ -161,6 +153,8 @@ module Unparser
161
153
 
162
154
  # Test for assignment
163
155
  #
156
+ # FIXME: This also returns true for <= operator!
157
+ #
164
158
  # @return [true]
165
159
  # if node represents attribute / element assignment
166
160
  #
@@ -173,6 +167,19 @@ module Unparser
173
167
  string_selector[-1] == ASSIGN_SUFFIX
174
168
  end
175
169
 
170
+ # Test for attribute assignment
171
+ #
172
+ # @return [true]
173
+ # if node represetns and attribute assignment
174
+ #
175
+ # @return [false]
176
+ #
177
+ # @api private
178
+ #
179
+ def attribute_assignment?
180
+ !BINARY_OPERATORS.include?(selector) && !UNARY_OPERATORS.include?(selector) && assignment? && !mlhs?
181
+ end
182
+
176
183
  # Test for empty arguments
177
184
  #
178
185
  # @return [true]
@@ -196,6 +203,7 @@ module Unparser
196
203
  def arguments
197
204
  children[2..-1]
198
205
  end
206
+ memoize :arguments
199
207
 
200
208
  # Emit arguments
201
209
  #
@@ -204,11 +212,7 @@ module Unparser
204
212
  # @api private
205
213
  #
206
214
  def emit_arguments
207
- args = arguments
208
- return if args.empty?
209
- parentheses do
210
- delimited(args)
211
- end
215
+ run(Arguments, s(:arguments, arguments))
212
216
  end
213
217
 
214
218
  end # Send