unparser 0.3.0 → 0.4.0

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.
@@ -97,7 +97,7 @@ module Unparser
97
97
  # @api private
98
98
  #
99
99
  def diff
100
- output = ''
100
+ output = +''
101
101
 
102
102
  collapsed_hunks.each do |hunk|
103
103
  output << hunk.diff(:unified) << "\n"
@@ -182,7 +182,7 @@ module Unparser
182
182
  # @api private
183
183
  #
184
184
  def generated_ast
185
- generated.success? && Preprocessor.run(parse(generated.source))
185
+ generated.success? && Preprocessor.run(Unparser.parse(generated.source))
186
186
  rescue Parser::SyntaxError
187
187
  nil
188
188
  end
@@ -195,25 +195,12 @@ module Unparser
195
195
  # @api private
196
196
  #
197
197
  def original_ast
198
- Preprocessor.run(parse(original_source))
198
+ Preprocessor.run(Unparser.parse(original_source))
199
199
  rescue Parser::SyntaxError
200
200
  nil
201
201
  end
202
202
  memoize :original_ast
203
203
 
204
- # Parse source with current ruby
205
- #
206
- # @param [String] source
207
- #
208
- # @return [Parser::AST::Node]
209
- #
210
- # @api private
211
- #
212
- # ignore :reek:UtilityFunction
213
- def parse(source)
214
- Parser::CurrentRuby.parse(source)
215
- end
216
-
217
204
  # CLI source from string
218
205
  class String < self
219
206
  include Concord.new(:original_source)
@@ -22,6 +22,10 @@ module Unparser
22
22
  end
23
23
  private_class_method :symbol_set
24
24
 
25
+ BRACKETS_CURLY = IceNine.deep_freeze(%w[{ }])
26
+ BRACKETS_ROUND = IceNine.deep_freeze(%w[( )])
27
+ BRACKETS_SQUARE = IceNine.deep_freeze(%w([ ]))
28
+
25
29
  # All unary operators of the ruby language
26
30
  UNARY_OPERATORS = symbol_set %w[
27
31
  ! ~ -@ +@
@@ -105,8 +109,6 @@ module Unparser
105
109
 
106
110
  DEFAULT_DELIMITER = ', '.freeze
107
111
 
108
- CURLY_BRACKETS = IceNine.deep_freeze(%w[{ }])
109
-
110
112
  KEYWORDS = constants.each_with_object([]) do |name, keywords|
111
113
  value = const_get(name).freeze
112
114
  next unless name.to_s.start_with?('K_')
@@ -17,10 +17,6 @@ module Unparser
17
17
 
18
18
  NOINDENT = %i[rescue ensure].to_set.freeze
19
19
 
20
- DEFAULT_DELIMITER = ', '.freeze
21
-
22
- CURLY_BRACKETS = IceNine.deep_freeze(%w[{ }])
23
-
24
20
  module Unterminated
25
21
  def terminated?
26
22
  false
@@ -111,16 +107,6 @@ module Unparser
111
107
  end
112
108
  memoize :write_to_buffer
113
109
 
114
- # Emit node
115
- #
116
- # @return [self]
117
- #
118
- # @api private
119
- #
120
- def self.emit(*arguments)
121
- new(*arguments).write_to_buffer
122
- end
123
-
124
110
  # Return emitter
125
111
  #
126
112
  # @return [Emitter]
@@ -30,6 +30,7 @@ module Unparser
30
30
  handle :args
31
31
 
32
32
  SHADOWARGS = ->(node) { node.type.equal?(:shadowarg) }.freeze
33
+ ARG = ->(node) { node.type.equal?(:arg) }.freeze
33
34
 
34
35
  private
35
36
 
@@ -41,12 +42,35 @@ module Unparser
41
42
  #
42
43
  def dispatch
43
44
  delimited(normal_arguments)
45
+
46
+ write(', ') if procarg_disambiguator?
47
+
44
48
  return if shadowargs.empty?
45
49
 
46
50
  write('; ')
47
51
  delimited(shadowargs)
48
52
  end
49
53
 
54
+ # Test for procarg_disambiguator
55
+ #
56
+ # @return [Boolean]
57
+ #
58
+ # @api private
59
+ #
60
+ def procarg_disambiguator?
61
+ regular_block? && normal_arguments.all?(&ARG) && normal_arguments.one?
62
+ end
63
+
64
+ # Test for regular block
65
+ #
66
+ # @return [Boolean]
67
+ #
68
+ # @api private
69
+ #
70
+ def regular_block?
71
+ parent_type.equal?(:block) && !parent.node.children.first.type.equal?(:lambda)
72
+ end
73
+
50
74
  # Return normal arguments
51
75
  #
52
76
  # @return [Enumerable<Parser::AST::Node>]
@@ -56,6 +80,7 @@ module Unparser
56
80
  def normal_arguments
57
81
  children.reject(&SHADOWARGS)
58
82
  end
83
+ memoize :normal_arguments
59
84
 
60
85
  # Return shadow args
61
86
  #
@@ -209,6 +234,43 @@ module Unparser
209
234
 
210
235
  end # Argument
211
236
 
237
+ # Progarg emitter
238
+ class Procarg < self
239
+ include Terminated
240
+
241
+ handle :procarg0
242
+
243
+ children :first_argument
244
+
245
+ private
246
+
247
+ # Perform dispatch
248
+ #
249
+ # @return [undefined]
250
+ #
251
+ # @api private
252
+ #
253
+ def dispatch
254
+ if first_argument.instance_of?(Symbol)
255
+ write(first_argument.to_s)
256
+ else
257
+ emit_multiple_children
258
+ end
259
+ end
260
+
261
+ # Emit multiple children
262
+ #
263
+ # @return [undefined]
264
+ #
265
+ # @api private
266
+ #
267
+ def emit_multiple_children
268
+ parentheses do
269
+ delimited(children)
270
+ end
271
+ end
272
+ end
273
+
212
274
  # Block pass node emitter
213
275
  class BlockPass < self
214
276
  include Terminated
@@ -29,7 +29,7 @@ module Unparser
29
29
  # @api private
30
30
  #
31
31
  def terminated?
32
- right_node.nil?
32
+ right.nil?
33
33
  end
34
34
 
35
35
  private
@@ -41,7 +41,6 @@ module Unparser
41
41
  # @api private
42
42
  #
43
43
  def emit_right
44
- right = right_node
45
44
  return unless right
46
45
 
47
46
  write(WS, T_ASN, WS)
@@ -55,7 +54,7 @@ module Unparser
55
54
 
56
55
  handle :lvasgn, :ivasgn, :cvasgn, :gvasgn
57
56
 
58
- children :name, :right_node
57
+ children :name, :right
59
58
 
60
59
  private
61
60
 
@@ -76,7 +75,7 @@ module Unparser
76
75
 
77
76
  handle :casgn
78
77
 
79
- children :base, :name, :right_node
78
+ children :base, :name, :right
80
79
 
81
80
  private
82
81
 
@@ -103,8 +102,6 @@ module Unparser
103
102
 
104
103
  handle :masgn
105
104
 
106
- PARENS = IceNine.deep_freeze(%w([ ]))
107
-
108
105
  private
109
106
 
110
107
  # Emit left
@@ -125,16 +122,7 @@ module Unparser
125
122
  #
126
123
  def emit_right
127
124
  write(WS, T_ASN, WS)
128
- right = children.last
129
- case right.type
130
- when :array
131
- children = right.children
132
- parentheses(*PARENS) do
133
- delimited(children)
134
- end
135
- else
136
- visit(right)
137
- end
125
+ visit(children.last)
138
126
  end
139
127
 
140
128
  end # Multiple
@@ -4,12 +4,14 @@ module Unparser
4
4
  class Emitter
5
5
 
6
6
  # Block emitter
7
+ #
8
+ # ignore :reek:RepeatedConditional
7
9
  class Block < self
8
10
  include Terminated
9
11
 
10
12
  handle :block
11
13
 
12
- children :send, :arguments, :body
14
+ children :target, :arguments, :body
13
15
 
14
16
  private
15
17
 
@@ -20,14 +22,37 @@ module Unparser
20
22
  # @api private
21
23
  #
22
24
  def dispatch
23
- visit(send)
25
+ emit_target
24
26
  write(WS, K_DO)
25
- comments.consume(node, :begin)
26
- emit_block_arguments
27
+ emit_block_arguments unless stabby_lambda?
27
28
  emit_body
28
29
  k_end
29
30
  end
30
31
 
32
+ # Emit target
33
+ #
34
+ # @return [undefined]
35
+ #
36
+ # @api private
37
+ #
38
+ def emit_target
39
+ visit(target)
40
+
41
+ if stabby_lambda?
42
+ parentheses { visit(arguments) }
43
+ end
44
+ end
45
+
46
+ # Test if we are emitting a stabby lambda
47
+ #
48
+ # @return [Boolean]
49
+ #
50
+ # @api private
51
+ #
52
+ def stabby_lambda?
53
+ target.type.equal?(:lambda)
54
+ end
55
+
31
56
  # Emit arguments
32
57
  #
33
58
  # @return [undefined]
@@ -24,7 +24,7 @@ module Unparser
24
24
  #
25
25
  def dispatch
26
26
  write(MAP.fetch(node.type), WS)
27
- parentheses(*CURLY_BRACKETS) do
27
+ parentheses(*BRACKETS_CURLY) do
28
28
  emit_body
29
29
  end
30
30
  end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unparser
4
+ class Emitter
5
+ # Emitter for send to index references
6
+ #
7
+ # ignore :reek:RepeatedConditional
8
+ class Index < self
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ emit_receiver
18
+ emit_operation
19
+ end
20
+
21
+ private
22
+
23
+ # Emit receiver
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ #
29
+ def emit_receiver
30
+ visit(first_child)
31
+ end
32
+
33
+ # Test for mlhs
34
+ #
35
+ # @return [Boolean]
36
+ #
37
+ # @api private
38
+ #
39
+ def mlhs?
40
+ parent_type.equal?(:mlhs)
41
+ end
42
+
43
+ class Reference < self
44
+ include Terminated
45
+
46
+ define_group(:indices, 1..-1)
47
+
48
+ handle :index
49
+
50
+ private
51
+
52
+ # Emit arguments
53
+ #
54
+ # @return [undefined]
55
+ #
56
+ # @api private
57
+ #
58
+ def emit_operation
59
+ parentheses(*BRACKETS_SQUARE) do
60
+ delimited_plain(indices)
61
+ end
62
+ end
63
+ end # Reference
64
+
65
+ # Emitter for assign to index nodes
66
+ class Assign < self
67
+
68
+ handle :indexasgn
69
+
70
+ VALUE_RANGE = (1..-2).freeze
71
+ NO_VALUE_PARENT = IceNine.deep_freeze(%i[and_asgn op_asgn or_asgn].to_set)
72
+
73
+ # Test if assign will be emitted terminated
74
+ #
75
+ # @return [Boolean]
76
+ #
77
+ # @api private
78
+ #
79
+ def terminated?
80
+ !emit_value?
81
+ end
82
+
83
+ private
84
+
85
+ # Emit arguments
86
+ #
87
+ # @return [undefined]
88
+ #
89
+ # @api private
90
+ #
91
+ def emit_operation
92
+ parentheses(*BRACKETS_SQUARE) do
93
+ delimited_plain(indices)
94
+ end
95
+
96
+ if emit_value?
97
+ write(WS, T_ASN, WS)
98
+ visit(children.last)
99
+ end
100
+ end
101
+
102
+ # The indices
103
+ #
104
+ # @return [Array<Parser::AST::Node>]
105
+ #
106
+ def indices
107
+ if emit_value?
108
+ children[VALUE_RANGE]
109
+ else
110
+ children.drop(1)
111
+ end
112
+ end
113
+
114
+ # Test if value should be emitted
115
+ #
116
+ # @return [Boolean]
117
+ #
118
+ # @api private
119
+ #
120
+ def emit_value?
121
+ !mlhs? && !no_value_parent?
122
+ end
123
+
124
+ # Test for no value parent
125
+ #
126
+ # @return [Boolean]
127
+ #
128
+ # @api private
129
+ #
130
+ def no_value_parent?
131
+ NO_VALUE_PARENT.include?(parent_type)
132
+ end
133
+ end # Assign
134
+ end # Index
135
+ end # Emitter
136
+ end # Unparser