synvert-core 0.63.1 → 0.64.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -1
  3. data/README.md +73 -33
  4. data/lib/synvert/core/configuration.rb +12 -0
  5. data/lib/synvert/core/exceptions.rb +0 -4
  6. data/lib/synvert/core/node_ext.rb +188 -87
  7. data/lib/synvert/core/rewriter/action/append_action.rb +4 -3
  8. data/lib/synvert/core/rewriter/action/delete_action.rb +13 -6
  9. data/lib/synvert/core/rewriter/action/insert_action.rb +16 -7
  10. data/lib/synvert/core/rewriter/action/insert_after_action.rb +3 -2
  11. data/lib/synvert/core/rewriter/action/prepend_action.rb +3 -2
  12. data/lib/synvert/core/rewriter/action/remove_action.rb +16 -10
  13. data/lib/synvert/core/rewriter/action/replace_action.rb +13 -5
  14. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +18 -11
  15. data/lib/synvert/core/rewriter/action/replace_with_action.rb +6 -5
  16. data/lib/synvert/core/rewriter/action/wrap_action.rb +13 -5
  17. data/lib/synvert/core/rewriter/action.rb +20 -9
  18. data/lib/synvert/core/rewriter/any_value.rb +1 -0
  19. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +4 -0
  20. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +4 -0
  21. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +4 -0
  22. data/lib/synvert/core/rewriter/condition.rb +11 -3
  23. data/lib/synvert/core/rewriter/gem_spec.rb +6 -3
  24. data/lib/synvert/core/rewriter/helper.rb +2 -2
  25. data/lib/synvert/core/rewriter/instance.rb +195 -94
  26. data/lib/synvert/core/rewriter/ruby_version.rb +4 -4
  27. data/lib/synvert/core/rewriter/scope/goto_scope.rb +5 -6
  28. data/lib/synvert/core/rewriter/scope/within_scope.rb +9 -4
  29. data/lib/synvert/core/rewriter/scope.rb +8 -0
  30. data/lib/synvert/core/rewriter/warning.rb +1 -1
  31. data/lib/synvert/core/rewriter.rb +90 -43
  32. data/lib/synvert/core/version.rb +1 -1
  33. data/lib/synvert/core.rb +0 -1
  34. data/spec/synvert/core/node_ext_spec.rb +0 -7
  35. data/spec/synvert/core/rewriter/action_spec.rb +0 -4
  36. data/spec/synvert/core/rewriter/gem_spec_spec.rb +1 -1
  37. data/spec/synvert/core/rewriter/instance_spec.rb +7 -17
  38. data/synvert-core-ruby.gemspec +2 -1
  39. metadata +20 -6
@@ -1,11 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parser::AST
4
- # Parser::AST::Node monkey patch.
4
+ # Extend Parser::AST::Node.
5
+ # {https://github.com/whitequark/parser/blob/master/lib/parser/ast/node.rb}
6
+ #
7
+ # Rules
8
+ #
9
+ # Synvert compares ast nodes with key / value pairs, each ast node has
10
+ # multiple attributes, e.g. +receiver+, +message+ and +arguments+, it
11
+ # matches only when all of key / value pairs match.
12
+ #
13
+ # +type: 'send', message: :include, arguments: ['FactoryGirl::Syntax::Methods']+
14
+ #
15
+ # Synvert does comparison based on the value type
16
+ #
17
+ # 1. if value is a symbol, then compares ast node value as symbol, e.g. +message: :include+
18
+ # 2. if value is a string, then compares ast node original source code, e.g. +name: 'Synvert::Application'+
19
+ # 3. if value is a regexp, then compares ast node original source code, e.g. +message: /find_all_by_/+
20
+ # 4. if value is an array, then compares each ast node, e.g. +arguments: ['FactoryGirl::Syntax::Methods']+
21
+ # 5. if value is nil, then check if ast node is nil, e.g. +arguments: [nil]+
22
+ # 6. if value is true or false, then check if ast node is :true or :false, e.g. +arguments: [false]+
23
+ # 7. if value is ast, then compare ast node directly, e.g. +to_ast: Parser::CurrentRuby.parse("self.class.serialized_attributes")+
24
+ #
25
+ # It can also compare nested key / value pairs, like
26
+ #
27
+ # +type: 'send', receiver: { type: 'send', receiver: { type: 'send', message: 'config' }, message: 'active_record' }, message: 'identity_map='+
28
+ #
29
+ # Source Code to Ast Node
30
+ # {https://synvert-playground.xinminlabs.com}
5
31
  class Node
6
- # Get name node of :class, :module, :const, :mlhs, :def and :defs node.
7
- #
8
- # @return [Parser::AST::Node] name node.
32
+ # Get the name of node.
33
+ # It supports :arg, :blockarg, :class, :const, :cvar, :def, :defs, :ivar,
34
+ # :lvar, :mlhs, :module and :restarg nodes.
35
+ # @example
36
+ # node # => s(:class, s(:const, nil, :Synvert), nil, nil)
37
+ # node.name # => s(:const, nil, :Synvert)
38
+ # @return [Parser::AST::Node] name of node.
9
39
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
10
40
  def name
11
41
  case type
@@ -20,9 +50,12 @@ module Parser::AST
20
50
  end
21
51
  end
22
52
 
23
- # Get parent_class node of :class node.
24
- #
25
- # @return [Parser::AST::Node] parent_class node.
53
+ # Get parent_class of node.
54
+ # It supports :class node.
55
+ # @example
56
+ # node # s(:class, s(:const, nil, :Post), s(:const, s(:const, nil, :ActiveRecord), :Base), nil)
57
+ # node.parent_class # s(:const, s(:const, nil, :ActiveRecord), :Base)
58
+ # @return [Parser::AST::Node] parent_class of node.
26
59
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
27
60
  def parent_class
28
61
  if :class == type
@@ -32,9 +65,12 @@ module Parser::AST
32
65
  end
33
66
  end
34
67
 
35
- # Get parent constant node of :const node.
36
- #
37
- # @return [Parser::AST::Node] parent const node.
68
+ # Get parent constant of node.
69
+ # It supports :const node.
70
+ # @example
71
+ # node # s(:const, s(:const, nil, :Synvert), :Node)
72
+ # node.parent_const # s(:const, nil, :Synvert)
73
+ # @return [Parser::AST::Node] parent const of node.
38
74
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
39
75
  def parent_const
40
76
  if :const == type
@@ -44,9 +80,12 @@ module Parser::AST
44
80
  end
45
81
  end
46
82
 
47
- # Get receiver node of :send node.
48
- #
49
- # @return [Parser::AST::Node] receiver node.
83
+ # Get receiver of node.
84
+ # It support :csend and :send nodes.
85
+ # @example
86
+ # node # s(:send, s(:const, nil, :FactoryGirl), :create, s(:sym, :post))
87
+ # node.receiver # s(:const, nil, :FactoryGirl)
88
+ # @return [Parser::AST::Node] receiver of node.
50
89
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
51
90
  def receiver
52
91
  if %i[csend send].include?(type)
@@ -56,9 +95,12 @@ module Parser::AST
56
95
  end
57
96
  end
58
97
 
59
- # Get message node of :super or :send node.
60
- #
61
- # @return [Parser::AST::Node] mesage node.
98
+ # Get message of node.
99
+ # It support :csend, :send, :super and :zsuper nodes.
100
+ # @example
101
+ # node # s(:send, s(:const, nil, :FactoryGirl), :create, s(:sym, :post))
102
+ # node.message # :create
103
+ # @return [Symbol] mesage of node.
62
104
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
63
105
  def message
64
106
  case type
@@ -71,9 +113,12 @@ module Parser::AST
71
113
  end
72
114
  end
73
115
 
74
- # Get arguments node of :send, :block or :defined? node.
75
- #
76
- # @return [Array<Parser::AST::Node>] arguments node.
116
+ # Get arguments of node.
117
+ # It supports :block, :csend, :def, :defined?, :defs and :send nodes.
118
+ # @example
119
+ # node # s(:send, s(:const, nil, :FactoryGirl), :create, s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post"))))
120
+ # node.arguments # [s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post")))]
121
+ # @return [Array<Parser::AST::Node>] arguments of node.
77
122
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
78
123
  def arguments
79
124
  case type
@@ -90,9 +135,12 @@ module Parser::AST
90
135
  end
91
136
  end
92
137
 
93
- # Get caller node of :block node.
94
- #
95
- # @return [Parser::AST::Node] caller node.
138
+ # Get caller of node.
139
+ # It support :block node.
140
+ # @example
141
+ # node # s(:block, s(:send, s(:const, nil, :RSpec), :configure), s(:args, s(:arg, :config)), nil)
142
+ # node.caller # s(:send, s(:const, nil, :RSpec), :configure)
143
+ # @return [Parser::AST::Node] caller of node.
96
144
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
97
145
  def caller
98
146
  if :block == type
@@ -102,9 +150,12 @@ module Parser::AST
102
150
  end
103
151
  end
104
152
 
105
- # Get body node of :begin or :block node.
106
- #
107
- # @return [Array<Parser::AST::Node>] body node.
153
+ # Get body of node.
154
+ # It supports :begin, :block, :class, :def, :defs and :module node.
155
+ # @example
156
+ # node # s(:block, s(:send, s(:const, nil, :RSpec), :configure), s(:args, s(:arg, :config)), s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers)))
157
+ # node.body # [s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers))]
158
+ # @return [Array<Parser::AST::Node>] body of node.
108
159
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
109
160
  def body
110
161
  case type
@@ -123,9 +174,12 @@ module Parser::AST
123
174
  end
124
175
  end
125
176
 
126
- # Get condition node of :if node.
127
- #
128
- # @return [Parser::AST::Node] condition node.
177
+ # Get condition of node.
178
+ # It supports :if node.
179
+ # @example
180
+ # node # s(:if, s(:defined?, s(:const, nil, :Bundler)), nil, nil)
181
+ # node.condition # s(:defined?, s(:const, nil, :Bundler))
182
+ # @return [Parser::AST::Node] condition of node.
129
183
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
130
184
  def condition
131
185
  if :if == type
@@ -135,9 +189,11 @@ module Parser::AST
135
189
  end
136
190
  end
137
191
 
138
- # Get keys node of :hash node.
139
- #
140
- # @return [Array<Parser::AST::Node>] keys node.
192
+ # Get keys of :hash node.
193
+ # @example
194
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
195
+ # node.keys # [s(:sym, :foo), s(:str, "foo")]
196
+ # @return [Array<Parser::AST::Node>] keys of node.
141
197
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
142
198
  def keys
143
199
  if :hash == type
@@ -147,9 +203,11 @@ module Parser::AST
147
203
  end
148
204
  end
149
205
 
150
- # Get values node of :hash node.
151
- #
152
- # @return [Array<Parser::AST::Node>] values node.
206
+ # Get values of :hash node.
207
+ # @example
208
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
209
+ # node.values # [s(:sym, :bar), s(:str, "bar")]
210
+ # @return [Array<Parser::AST::Node>] values of node.
153
211
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
154
212
  def values
155
213
  if :hash == type
@@ -159,9 +217,11 @@ module Parser::AST
159
217
  end
160
218
  end
161
219
 
162
- # Test if hash node contains specified key.
163
- #
164
- # @param [Object] key value.
220
+ # Check if :hash node contains specified key.
221
+ # @example
222
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
223
+ # node.key?(:foo) # true
224
+ # @param [Symbol, String] key value.
165
225
  # @return [Boolean] true if specified key exists.
166
226
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
167
227
  def key?(key)
@@ -172,10 +232,12 @@ module Parser::AST
172
232
  end
173
233
  end
174
234
 
175
- # Get hash value node according to specified key.
176
- #
177
- # @param [Object] key value.
178
- # @return [Parser::AST::Node] value node.
235
+ # Get :hash value node according to specified key.
236
+ # @example
237
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
238
+ # node.hash_value(:foo) # s(:sym, :bar)
239
+ # @param [Symbol, String] key value.
240
+ # @return [Parser::AST::Node] hash value of node.
179
241
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
180
242
  def hash_value(key)
181
243
  if :hash == type
@@ -187,8 +249,10 @@ module Parser::AST
187
249
  end
188
250
 
189
251
  # Get key node of hash :pair node.
190
- #
191
- # @return [Parser::AST::Node] key node.
252
+ # @example
253
+ # node # s(:pair, s(:sym, :foo), s(:str, "bar"))
254
+ # node.key # s(:sym, :foo)
255
+ # @return [Parser::AST::Node] key of node.
192
256
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
193
257
  def key
194
258
  if :pair == type
@@ -199,8 +263,10 @@ module Parser::AST
199
263
  end
200
264
 
201
265
  # Get value node of hash :pair node.
202
- #
203
- # @return [Parser::AST::Node] value node.
266
+ # @example
267
+ # node # s(:pair, s(:sym, :foo), s(:str, "bar"))
268
+ # node.value # s(:str, "bar")
269
+ # @return [Parser::AST::Node] value of node.
204
270
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
205
271
  def value
206
272
  if :pair == type
@@ -210,9 +276,12 @@ module Parser::AST
210
276
  end
211
277
  end
212
278
 
213
- # Return the left value.
214
- #
215
- # @return [Parser::AST::Node] variable nodes.
279
+ # Return the left value of node.
280
+ # It supports :and, :cvagn, :lvasgn, :masgn, :or and :or_asgn nodes.
281
+ # @example
282
+ # node # s(:masgn, s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b)), s(:array, s(:int, 1), s(:int, 2)))
283
+ # node.left_value # s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))
284
+ # @return [Parser::AST::Node] left value of node.
216
285
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
217
286
  def left_value
218
287
  if %i[masgn lvasgn ivasgn cvasgn and or].include? type
@@ -224,9 +293,12 @@ module Parser::AST
224
293
  end
225
294
  end
226
295
 
227
- # Return the right value.
228
- #
229
- # @return [Array<Parser::AST::Node>] variable nodes.
296
+ # Return the right value of node.
297
+ # It supports :cvasgn, :ivasgn, :lvasgn, :masgn, :or and :or_asgn nodes.
298
+ # @example
299
+ # node # s(:masgn, s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b)), s(:array, s(:int, 1), s(:int, 2)))
300
+ # node.right_value # s(:array, s(:int, 1), s(:int, 2))
301
+ # @return [Array<Parser::AST::Node>] right value of node.
230
302
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
231
303
  def right_value
232
304
  if %i[masgn lvasgn ivasgn cvasgn or_asgn and or].include? type
@@ -236,8 +308,11 @@ module Parser::AST
236
308
  end
237
309
  end
238
310
 
239
- # Return the exact value.
240
- #
311
+ # Return the exact value of node.
312
+ # It supports :array, :begin, :erange, :false, :float, :irange, :int, :str, :sym and :true nodes.
313
+ # @example
314
+ # node # s(:array, s(:str, "str"), s(:sym, :str)) ["str", :str]
315
+ # node.to_value # ['str', :str]
241
316
  # @return [Object] exact value.
242
317
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
243
318
  def to_value
@@ -261,10 +336,11 @@ module Parser::AST
261
336
  end
262
337
  end
263
338
 
264
- # Respond key value for hash node, e.g.
265
- #
266
- # Current node is s(:hash, s(:pair, s(:sym, :number), s(:int, 10)))
267
- # node.number_value is 10
339
+ # Respond key value and source for hash node, e.g.
340
+ # @example
341
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
342
+ # node.foo_value # :bar
343
+ # node.foo_source # ":bar"
268
344
  def method_missing(method_name, *args, &block)
269
345
  if :args == type && children.respond_to?(method_name)
270
346
  return children.send(method_name, *args, &block)
@@ -299,12 +375,9 @@ module Parser::AST
299
375
  super
300
376
  end
301
377
 
302
- def to_s
303
- if :mlhs == type
304
- "(#{children.map(&:name).join(', ')})"
305
- end
306
- end
307
-
378
+ # Return the debug info.
379
+ #
380
+ # @return [String] file, line, source and node.
308
381
  def debug_info
309
382
  "\n" +
310
383
  [
@@ -315,37 +388,37 @@ module Parser::AST
315
388
  ].join("\n")
316
389
  end
317
390
 
318
- # Get the file name of the current node.
391
+ # Get the file name of node.
319
392
  #
320
393
  # @return [String] file name.
321
394
  def filename
322
395
  loc.expression&.source_buffer.name
323
396
  end
324
397
 
325
- # Get the source code of current node.
398
+ # Get the source code of node.
326
399
  #
327
400
  # @return [String] source code.
328
401
  def to_source
329
402
  loc.expression&.source
330
403
  end
331
404
 
332
- # Get the column of current node.
405
+ # Get the column of node.
333
406
  #
334
407
  # @return [Integer] column.
335
408
  def column
336
409
  loc.expression.column
337
410
  end
338
411
 
339
- # Get the line of current node.
412
+ # Get the line of node.
340
413
  #
341
414
  # @return [Integer] line.
342
415
  def line
343
416
  loc.expression.line
344
417
  end
345
418
 
346
- # Get child node by child name.
419
+ # Get child node by the name.
347
420
  #
348
- # @param [String] name of child node.
421
+ # @param child_name [String] name of child node.
349
422
  # @return [Parser::AST::Node] the child node.
350
423
  def child_node_by_name(child_name)
351
424
  direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
@@ -382,7 +455,7 @@ module Parser::AST
382
455
 
383
456
  # Get the source range of child node.
384
457
  #
385
- # @param [String] name of child node.
458
+ # @param child_name [String] name of child node.
386
459
  # @return [Parser::Source::Range] source range of child node.
387
460
  def child_node_range(child_name)
388
461
  case [type, child_name.to_sym]
@@ -469,7 +542,7 @@ module Parser::AST
469
542
  end
470
543
  end
471
544
 
472
- # Recursively iterate all child nodes of current node.
545
+ # Recursively iterate all child nodes of node.
473
546
  #
474
547
  # @yield [child] Gives a child node.
475
548
  # @yieldparam child [Parser::AST::Node] child node
@@ -482,8 +555,12 @@ module Parser::AST
482
555
  end
483
556
  end
484
557
 
485
- # Match current node with rules.
486
- #
558
+ # Match node with rules.
559
+ # It provides some additional keywords to match rules, +any+, +contain+, +not+, +in+, +not_in+, +gt+, +gte+, +lt+, +lte+.
560
+ # @example
561
+ # type: 'send', arguments: { any: 'Lifo::ShowExceptions' }
562
+ # type: { in: ['send', 'csend'] }
563
+ # type: :send, arguments: { length: { gt: 2 } }
487
564
  # @param rules [Hash] rules to match.
488
565
  # @return true if matches.
489
566
  def match?(rules)
@@ -517,11 +594,10 @@ module Parser::AST
517
594
 
518
595
  # Get rewritten source code.
519
596
  # @example
520
- # node.rewritten_source("create({{arguments}})") #=> "create(:post)"
521
- #
597
+ # node.rewritten_source("create({{arguments}})") # "create(:post)"
522
598
  # @param code [String] raw code.
523
- # @return [String] rewritten code, replace string in block {{ }} in raw code.
524
- # @raise [Synvert::Core::MethodNotSupported] if string in block {{ }} does not support.
599
+ # @return [String] rewritten code, replace string in block !{{ }} in raw code.
600
+ # @raise [Synvert::Core::MethodNotSupported] if string in block !{{ }} does not support.
525
601
  def rewritten_source(code)
526
602
  code.gsub(/{{(.*?)}}/m) do
527
603
  old_code = Regexp.last_match(1)
@@ -563,42 +639,66 @@ module Parser::AST
563
639
  end
564
640
  end
565
641
 
566
- # strip curly braces for hash
642
+ # Strip curly braces for hash.
643
+ # @example
644
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:str, "bar")))
645
+ # node.strip_curly_braces # "foo: 'bar'"
646
+ # @return [String]
567
647
  def strip_curly_braces
568
648
  return to_source unless type == :hash
569
649
 
570
650
  to_source.sub(/^{(.*)}$/) { Regexp.last_match(1).strip }
571
651
  end
572
652
 
573
- # wrap curly braces for hash
653
+ # Wrap curly braces for hash.
654
+ # @example
655
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:str, "bar")))
656
+ # node.wrap_curly_braces # "{ foo: 'bar' }"
657
+ # @return [String]
574
658
  def wrap_curly_braces
575
659
  return to_source unless type == :hash
576
660
 
577
661
  "{ #{to_source} }"
578
662
  end
579
663
 
580
- # get single quote string
664
+ # Get single quote string.
665
+ # @example
666
+ # node # s(:str, "foobar")
667
+ # node.to_single_quote # "'foobar'"
668
+ # @return [String]
581
669
  def to_single_quote
582
670
  return to_source unless type == :str
583
671
 
584
672
  "'#{to_value}'"
585
673
  end
586
674
 
587
- # convert string to symbol
675
+ # Convert string to symbol.
676
+ # @example
677
+ # node # s(:str, "foobar")
678
+ # node.to_symbol # ":foobar"
679
+ # @return [String]
588
680
  def to_symbol
589
681
  return to_source unless type == :str
590
682
 
591
683
  ":#{to_value}"
592
684
  end
593
685
 
594
- # convert symbol to string
686
+ # Convert symbol to string.
687
+ # @example
688
+ # node # s(:sym, :foobar)
689
+ # node.to_string # "foobar"
690
+ # @return [String]
595
691
  def to_string
596
692
  return to_source unless type == :sym
597
693
 
598
694
  to_value.to_s
599
695
  end
600
696
 
601
- # convert lambda {} to -> {}
697
+ # Convert lambda {} to -> {}
698
+ # @example
699
+ # node # s(:block, s(:send, nil, :lambda), s(:args), s(:send, nil, :foobar))
700
+ # node.to_lambda_literal # "-> { foobar }"
701
+ # @return [String]
602
702
  def to_lambda_literal
603
703
  if type == :block && caller.type == :send && caller.receiver.nil? && caller.message == :lambda
604
704
  new_source = to_source
@@ -620,7 +720,7 @@ module Parser::AST
620
720
  #
621
721
  # @param actual [Object] actual value.
622
722
  # @param expected [Object] expected value.
623
- # @return [Integer] -1, 0 or 1.
723
+ # @return [Boolean]
624
724
  # @raise [Synvert::Core::MethodNotSupported] if expected class is not supported.
625
725
  def match_value?(actual, expected)
626
726
  return true if actual == expected
@@ -678,7 +778,7 @@ module Parser::AST
678
778
  #
679
779
  # @example
680
780
  # flat_hash(type: 'block', caller: {type: 'send', receiver: 'RSpec'})
681
- # #=> {[:type] => 'block', [:caller, :type] => 'send', [:caller, :receiver] => 'RSpec'}
781
+ # # {[:type] => 'block', [:caller, :type] => 'send', [:caller, :receiver] => 'RSpec'}
682
782
  # @param h [Hash] original hash.
683
783
  # @return flatten hash.
684
784
  def flat_hash(h, k = [])
@@ -695,8 +795,7 @@ module Parser::AST
695
795
 
696
796
  # Get actual value from the node.
697
797
  #
698
- # @param node [Parser::AST::Node]
699
- # @param multi_keys [Array<Symbol>]
798
+ # @param multi_keys [Array<Symbol, String>]
700
799
  # @return [Object] actual value.
701
800
  def actual_value(multi_keys)
702
801
  multi_keys.inject(self) { |n, key| n.send(key) if n }
@@ -711,6 +810,7 @@ module Parser::AST
711
810
  multi_keys.inject(rules) { |o, key| o[key] }
712
811
  end
713
812
 
813
+ # Wrap the string with single or double quote.
714
814
  def wrap_quote(string)
715
815
  if string.include?("'")
716
816
  "\"#{string}\""
@@ -719,6 +819,7 @@ module Parser::AST
719
819
  end
720
820
  end
721
821
 
822
+ # Unwrap the quote from the string.
722
823
  def unwrap_quote(string)
723
824
  if (string[0] == '"' && string[-1] == '"') || (string[0] == "'" && string[-1] == "'")
724
825
  string[1...-1]
@@ -1,17 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # AppendAction to append code to the bottom of node body.
4
+ # AppendAction appends code to the bottom of node body.
5
5
  class Rewriter::AppendAction < Rewriter::Action
6
+ private
7
+
6
8
  END_LENGTH = "\nend".length
7
9
 
10
+ # Calculate the begin the end positions.
8
11
  def calculate_position
9
12
  @begin_pos = :begin == @node.type ? @node.loc.expression.end_pos : @node.loc.expression.end_pos - @node.column - END_LENGTH
10
13
  @end_pos = @begin_pos
11
14
  end
12
15
 
13
- private
14
-
15
16
  # Indent of the node.
16
17
  #
17
18
  # @param node [Parser::AST::Node]
@@ -1,23 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # DeleteAction to delete child nodes.
4
+ # DeleteAction deletes child nodes.
5
5
  class Rewriter::DeleteAction < Rewriter::Action
6
+ # Initialize a DeleteAction.
7
+ #
8
+ # @param instance [Synvert::Core::Rewriter::Instance]
9
+ # @param selectors [Array<Symbol, String>] used to select child nodes
6
10
  def initialize(instance, *selectors)
7
11
  super(instance, nil)
8
12
  @selectors = selectors
9
13
  end
10
14
 
15
+ # The rewritten code, always empty string.
16
+ def rewritten_code
17
+ ''
18
+ end
19
+
20
+ private
21
+
22
+ # Calculate the begin and end positions.
11
23
  def calculate_position
12
24
  @begin_pos = @selectors.map { |selector| @node.child_node_range(selector) }.compact.map(&:begin_pos).min
13
25
  @end_pos = @selectors.map { |selector| @node.child_node_range(selector) }.compact.map(&:end_pos).max
14
26
  squeeze_spaces
15
27
  remove_comma
16
28
  end
17
-
18
- # The rewritten code, always empty string.
19
- def rewritten_code
20
- ''
21
- end
22
29
  end
23
30
  end
@@ -3,23 +3,32 @@
3
3
  module Synvert::Core
4
4
  # InsertAction to add code to the node.
5
5
  class Rewriter::InsertAction < Rewriter::Action
6
- def initialize(instance, code, at:, to: nil)
6
+ # Initialize an InsertAction.
7
+ #
8
+ # @param instance [Synvert::Core::Rewriter::Instance]
9
+ # @param code [String] to be inserted
10
+ # @param at [String] position to insert, beginning or end
11
+ # @param to [<Symbol|String>] name of child node
12
+ def initialize(instance, code, at: 'end', to: nil)
7
13
  super(instance, code)
8
14
  @at = at
9
15
  @to = to
10
16
  end
11
17
 
12
- def calculate_position
13
- node_range = @to ? @node.child_node_range(@to) : @node.loc.expression
14
- @begin_pos = @at == 'end' ? node_range.end_pos : node_range.begin_pos
15
- @end_pos = @begin_pos
16
- end
17
-
18
18
  # The rewritten source code.
19
19
  #
20
20
  # @return [String] rewritten code.
21
21
  def rewritten_code
22
22
  rewritten_source
23
23
  end
24
+
25
+ private
26
+
27
+ # Calculate the begin and end positions.
28
+ def calculate_position
29
+ node_range = @to ? @node.child_node_range(@to) : @node.loc.expression
30
+ @begin_pos = @at == 'end' ? node_range.end_pos : node_range.begin_pos
31
+ @end_pos = @begin_pos
32
+ end
24
33
  end
25
34
  end
@@ -3,13 +3,14 @@
3
3
  module Synvert::Core
4
4
  # InsertAfterAction to insert code next to the node.
5
5
  class Rewriter::InsertAfterAction < Rewriter::Action
6
+ private
7
+
8
+ # Calculate the begin and end positions.
6
9
  def calculate_position
7
10
  @begin_pos = @node.loc.expression.end_pos
8
11
  @end_pos = @begin_pos
9
12
  end
10
13
 
11
- private
12
-
13
14
  # Indent of the node.
14
15
  #
15
16
  # @param node [Parser::AST::Node]
@@ -3,8 +3,11 @@
3
3
  module Synvert::Core
4
4
  # PrependAction to prepend code to the top of node body.
5
5
  class Rewriter::PrependAction < Rewriter::Action
6
+ private
7
+
6
8
  DO_LENGTH = ' do'.length
7
9
 
10
+ # Calculate the begin and end positions.
8
11
  def calculate_position
9
12
  @begin_pos =
10
13
  case @node.type
@@ -26,8 +29,6 @@ module Synvert::Core
26
29
  @end_pos = @begin_pos
27
30
  end
28
31
 
29
- private
30
-
31
32
  # Indent of the node.
32
33
  #
33
34
  # @param node [Parser::AST::Node]