unparser 0.3.0 → 0.4.0

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