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,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