synvert-core 1.4.0 → 1.6.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +0 -1
  3. data/.gitignore +0 -5
  4. data/CHANGELOG.md +12 -0
  5. data/Gemfile +0 -3
  6. data/Gemfile.lock +101 -0
  7. data/Guardfile +0 -9
  8. data/README.md +31 -13
  9. data/Rakefile +1 -15
  10. data/lib/synvert/core/engine/erb.rb +1 -1
  11. data/lib/synvert/core/engine.rb +1 -1
  12. data/lib/synvert/core/node_ext.rb +0 -639
  13. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +20 -17
  14. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -5
  15. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +1 -1
  16. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -5
  17. data/lib/synvert/core/rewriter/condition.rb +5 -1
  18. data/lib/synvert/core/rewriter/instance.rb +91 -140
  19. data/lib/synvert/core/rewriter/scope/query_scope.rb +8 -6
  20. data/lib/synvert/core/rewriter/scope/within_scope.rb +4 -87
  21. data/lib/synvert/core/rewriter.rb +0 -10
  22. data/lib/synvert/core/version.rb +1 -1
  23. data/lib/synvert/core.rb +4 -6
  24. data/spec/synvert/core/engine/erb_spec.rb +3 -3
  25. data/spec/synvert/core/node_ext_spec.rb +0 -965
  26. data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +21 -1
  27. data/spec/synvert/core/rewriter/instance_spec.rb +64 -131
  28. data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -4
  29. data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +1 -16
  30. data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +22 -13
  31. data/synvert-core-ruby.gemspec +5 -3
  32. metadata +46 -62
  33. data/lib/synvert/core/array_ext.rb +0 -48
  34. data/lib/synvert/core/node_query/compiler/array.rb +0 -34
  35. data/lib/synvert/core/node_query/compiler/attribute.rb +0 -39
  36. data/lib/synvert/core/node_query/compiler/attribute_list.rb +0 -24
  37. data/lib/synvert/core/node_query/compiler/basic_selector.rb +0 -28
  38. data/lib/synvert/core/node_query/compiler/boolean.rb +0 -23
  39. data/lib/synvert/core/node_query/compiler/comparable.rb +0 -86
  40. data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +0 -51
  41. data/lib/synvert/core/node_query/compiler/expression.rb +0 -41
  42. data/lib/synvert/core/node_query/compiler/float.rb +0 -23
  43. data/lib/synvert/core/node_query/compiler/identifier.rb +0 -41
  44. data/lib/synvert/core/node_query/compiler/integer.rb +0 -23
  45. data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +0 -7
  46. data/lib/synvert/core/node_query/compiler/nil.rb +0 -23
  47. data/lib/synvert/core/node_query/compiler/parse_error.rb +0 -7
  48. data/lib/synvert/core/node_query/compiler/regexp.rb +0 -37
  49. data/lib/synvert/core/node_query/compiler/selector.rb +0 -113
  50. data/lib/synvert/core/node_query/compiler/string.rb +0 -23
  51. data/lib/synvert/core/node_query/compiler/symbol.rb +0 -23
  52. data/lib/synvert/core/node_query/compiler.rb +0 -25
  53. data/lib/synvert/core/node_query/lexer.rex +0 -99
  54. data/lib/synvert/core/node_query/lexer.rex.rb +0 -299
  55. data/lib/synvert/core/node_query/parser.racc.rb +0 -306
  56. data/lib/synvert/core/node_query/parser.y +0 -60
  57. data/lib/synvert/core/node_query.rb +0 -36
  58. data/lib/synvert/core/rewriter/action/append_action.rb +0 -28
  59. data/lib/synvert/core/rewriter/action/delete_action.rb +0 -34
  60. data/lib/synvert/core/rewriter/action/insert_action.rb +0 -34
  61. data/lib/synvert/core/rewriter/action/insert_after_action.rb +0 -22
  62. data/lib/synvert/core/rewriter/action/prepend_action.rb +0 -44
  63. data/lib/synvert/core/rewriter/action/remove_action.rb +0 -56
  64. data/lib/synvert/core/rewriter/action/replace_action.rb +0 -33
  65. data/lib/synvert/core/rewriter/action/replace_with_action.rb +0 -36
  66. data/lib/synvert/core/rewriter/action/wrap_action.rb +0 -37
  67. data/lib/synvert/core/rewriter/action.rb +0 -102
  68. data/spec/synvert/core/node_query/lexer_spec.rb +0 -580
  69. data/spec/synvert/core/node_query/parser_spec.rb +0 -337
  70. data/spec/synvert/core/rewriter/action/append_action_spec.rb +0 -70
  71. data/spec/synvert/core/rewriter/action/delete_action_spec.rb +0 -26
  72. data/spec/synvert/core/rewriter/action/insert_action_spec.rb +0 -70
  73. data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +0 -26
  74. data/spec/synvert/core/rewriter/action/prepend_action_spec.rb +0 -175
  75. data/spec/synvert/core/rewriter/action/remove_action_spec.rb +0 -26
  76. data/spec/synvert/core/rewriter/action/replace_action_spec.rb +0 -28
  77. data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +0 -59
  78. data/spec/synvert/core/rewriter/action/wrap_action_spec.rb +0 -31
  79. data/spec/synvert/core/rewriter/action_spec.rb +0 -14
@@ -29,311 +29,6 @@ module Parser::AST
29
29
  # Source Code to Ast Node
30
30
  # {https://synvert-playground.xinminlabs.com/ruby}
31
31
  class Node
32
- TYPE_CHILDREN = {
33
- and: %i[left_value right_value],
34
- arg: %i[name],
35
- begin: %i[body],
36
- block: %i[caller arguments body],
37
- blockarg: %i[name],
38
- const: %i[parent_const name],
39
- class: %i[name parent_class body],
40
- csend: %i[receiver message arguments],
41
- cvasgn: %i[left_value right_value],
42
- cvar: %i[name],
43
- def: %i[name arguments body],
44
- definded?: %i[arguments],
45
- defs: %i[self name arguments body],
46
- hash: %i[pairs],
47
- ivasgn: %i[left_value right_value],
48
- ivar: %i[name],
49
- lvar: %i[name],
50
- lvasgn: %i[left_value right_value],
51
- masgn: %i[left_value right_value],
52
- module: %i[name body],
53
- or: %i[left_value right_value],
54
- or_asgn: %i[left_value right_value],
55
- pair: %i[key value],
56
- restarg: %i[name],
57
- send: %i[receiver message arguments],
58
- super: %i[arguments],
59
- zsuper: %i[]
60
- }
61
-
62
- # Initialize a Node.
63
- #
64
- # It extends {Parser::AST::Node} and set parent for its child nodes.
65
- def initialize(type, children = [], properties = {})
66
- @mutable_attributes = {}
67
- super
68
- # children could be nil for s(:array)
69
- Array(children).each do |child_node|
70
- if child_node.is_a?(Parser::AST::Node)
71
- child_node.parent = self
72
- end
73
- end
74
- end
75
-
76
- # Get the parent node.
77
- # @return [Parser::AST::Node] parent node.
78
- def parent
79
- @mutable_attributes[:parent]
80
- end
81
-
82
- # Set the parent node.
83
- # @param node [Parser::AST::Node] parent node.
84
- def parent=(node)
85
- @mutable_attributes[:parent] = node
86
- end
87
-
88
- # Get the sibling nodes.
89
- # @return [Array<Parser::AST::Node>] sibling nodes.
90
- def siblings
91
- index = parent.children.index(self)
92
- parent.children[index + 1..]
93
- end
94
-
95
- # Dyamically defined method
96
- # caller, key, left_value, message, name, pairs, parent_class, parent_const, receivr, rgith_value and value.
97
- # based on const TYPE_CHILDREN.
98
- %i[
99
- caller
100
- key
101
- left_value
102
- message
103
- name
104
- pairs
105
- parent_class
106
- parent_const
107
- receiver
108
- right_value
109
- value
110
- ].each do |method_name|
111
- define_method(method_name) do
112
- index = TYPE_CHILDREN[type]&.index(method_name)
113
- return children[index] if index
114
-
115
- raise Synvert::Core::MethodNotSupported, "#{method_name} is not handled for #{debug_info}"
116
- end
117
- end
118
-
119
- # Return the left value of node.
120
- # It supports :and, :cvagn, :lvasgn, :masgn, :or and :or_asgn nodes.
121
- # @example
122
- # node # s(:or_asgn, s(:lvasgn, :a), s(:int, 1))
123
- # node.left_value # :a
124
- # @return [Parser::AST::Node] left value of node.
125
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
126
- def left_value
127
- return children[0].children[0] if type == :or_asgn
128
-
129
- index = TYPE_CHILDREN[type]&.index(:left_value)
130
- return children[index] if index
131
-
132
- raise Synvert::Core::MethodNotSupported, "#{left_value} is not handled for #{debug_info}"
133
- end
134
-
135
- # Get arguments of node.
136
- # It supports :block, :csend, :def, :defined?, :defs and :send nodes.
137
- # @example
138
- # node # s(:send, s(:const, nil, :FactoryGirl), :create, s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post"))))
139
- # node.arguments # [s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post")))]
140
- # @return [Array<Parser::AST::Node>] arguments of node.
141
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
142
- def arguments
143
- case type
144
- when :def, :block
145
- children[1].children
146
- when :defs
147
- children[2].children
148
- when :send, :csend
149
- children[2..-1]
150
- when :defined?
151
- children
152
- else
153
- raise Synvert::Core::MethodNotSupported, "arguments is not handled for #{debug_info}"
154
- end
155
- end
156
-
157
- # Get body of node.
158
- # It supports :begin, :block, :class, :def, :defs and :module node.
159
- # @example
160
- # 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)))
161
- # node.body # [s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers))]
162
- # @return [Array<Parser::AST::Node>] body of node.
163
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
164
- def body
165
- case type
166
- when :begin
167
- children
168
- when :def, :block, :class, :module
169
- return [] if children[2].nil?
170
-
171
- :begin == children[2].type ? children[2].body : children[2..-1]
172
- when :defs
173
- return [] if children[3].nil?
174
-
175
- :begin == children[3].type ? children[3].body : children[3..-1]
176
- else
177
- raise Synvert::Core::MethodNotSupported, "body is not handled for #{debug_info}"
178
- end
179
- end
180
-
181
- # Get condition of node.
182
- # It supports :if node.
183
- # @example
184
- # node # s(:if, s(:defined?, s(:const, nil, :Bundler)), nil, nil)
185
- # node.condition # s(:defined?, s(:const, nil, :Bundler))
186
- # @return [Parser::AST::Node] condition of node.
187
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
188
- def condition
189
- if :if == type
190
- children[0]
191
- else
192
- raise Synvert::Core::MethodNotSupported, "condition is not handled for #{debug_info}"
193
- end
194
- end
195
-
196
- # Get keys of :hash node.
197
- # @example
198
- # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
199
- # node.keys # [s(:sym, :foo), s(:str, "foo")]
200
- # @return [Array<Parser::AST::Node>] keys of node.
201
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
202
- def keys
203
- if :hash == type
204
- children.map { |child| child.children[0] }
205
- else
206
- raise Synvert::Core::MethodNotSupported, "keys is not handled for #{debug_info}"
207
- end
208
- end
209
-
210
- # Get values of :hash node.
211
- # @example
212
- # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
213
- # node.values # [s(:sym, :bar), s(:str, "bar")]
214
- # @return [Array<Parser::AST::Node>] values of node.
215
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
216
- def values
217
- if :hash == type
218
- children.map { |child| child.children[1] }
219
- else
220
- raise Synvert::Core::MethodNotSupported, "keys is not handled for #{debug_info}"
221
- end
222
- end
223
-
224
- # Check if :hash node contains specified key.
225
- # @example
226
- # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
227
- # node.key?(:foo) # true
228
- # @param [Symbol, String] key value.
229
- # @return [Boolean] true if specified key exists.
230
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
231
- def key?(key)
232
- if :hash == type
233
- children.any? { |pair_node| pair_node.key.to_value == key }
234
- else
235
- raise Synvert::Core::MethodNotSupported, "key? is not handled for #{debug_info}"
236
- end
237
- end
238
-
239
- # Get :hash value node according to specified key.
240
- # @example
241
- # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
242
- # node.hash_value(:foo) # s(:sym, :bar)
243
- # @param [Symbol, String] key value.
244
- # @return [Parser::AST::Node] hash value of node.
245
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
246
- def hash_value(key)
247
- if :hash == type
248
- value_node = children.find { |pair_node| pair_node.key.to_value == key }
249
- value_node&.value
250
- else
251
- raise Synvert::Core::MethodNotSupported, "hash_value is not handled for #{debug_info}"
252
- end
253
- end
254
-
255
- # Return the exact value of node.
256
- # It supports :array, :begin, :erange, :false, :float, :irange, :int, :str, :sym and :true nodes.
257
- # @example
258
- # node # s(:array, s(:str, "str"), s(:sym, :str))
259
- # node.to_value # ['str', :str]
260
- # @return [Object] exact value.
261
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
262
- def to_value
263
- case type
264
- when :int, :float, :str, :sym
265
- children.last
266
- when :true
267
- true
268
- when :false
269
- false
270
- when :nil
271
- nil
272
- when :array
273
- children.map(&:to_value)
274
- when :irange
275
- (children.first.to_value..children.last.to_value)
276
- when :erange
277
- (children.first.to_value...children.last.to_value)
278
- when :begin
279
- children.first.to_value
280
- else
281
- self
282
- end
283
- end
284
-
285
- # Respond key value and source for hash node, e.g.
286
- # @example
287
- # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
288
- # node.foo_value # :bar
289
- # node.foo_source # ":bar"
290
- def method_missing(method_name, *args, &block)
291
- if :args == type && children.respond_to?(method_name)
292
- return children.send(method_name, *args, &block)
293
- elsif :hash == type && method_name.to_s.include?('_value')
294
- key = method_name.to_s.sub('_value', '')
295
- return hash_value(key.to_sym)&.to_value if key?(key.to_sym)
296
- return hash_value(key.to_s)&.to_value if key?(key.to_s)
297
-
298
- return nil
299
- elsif :hash == type && method_name.to_s.include?('_source')
300
- key = method_name.to_s.sub('_source', '')
301
- return hash_value(key.to_sym)&.to_source if key?(key.to_sym)
302
- return hash_value(key.to_s)&.to_source if key?(key.to_s)
303
-
304
- return nil
305
- end
306
-
307
- super
308
- end
309
-
310
- def respond_to_missing?(method_name, *args)
311
- if :args == type && children.respond_to?(method_name)
312
- return true
313
- elsif :hash == type && method_name.to_s.include?('_value')
314
- key = method_name.to_s.sub('_value', '')
315
- return true if key?(key.to_sym) || key?(key.to_s)
316
- elsif :hash == type && method_name.to_s.include?('_source')
317
- key = method_name.to_s.sub('_source', '')
318
- return true if key?(key.to_sym) || key?(key.to_s)
319
- end
320
-
321
- super
322
- end
323
-
324
- # Return the debug info.
325
- #
326
- # @return [String] file, line, source and node.
327
- def debug_info
328
- "\n" +
329
- [
330
- "file: #{loc.expression.source_buffer.name}",
331
- "line: #{loc.expression.line}",
332
- "source: #{to_source}",
333
- "node: #{inspect}"
334
- ].join("\n")
335
- end
336
-
337
32
  # Get the file name of node.
338
33
  #
339
34
  # @return [String] file name.
@@ -341,13 +36,6 @@ module Parser::AST
341
36
  loc.expression&.source_buffer.name
342
37
  end
343
38
 
344
- # Get the source code of node.
345
- #
346
- # @return [String] source code.
347
- def to_source
348
- loc.expression&.source
349
- end
350
-
351
39
  # Get the column of node.
352
40
  #
353
41
  # @return [Integer] column.
@@ -362,197 +50,6 @@ module Parser::AST
362
50
  loc.expression.line
363
51
  end
364
52
 
365
- # Get child node by the name.
366
- #
367
- # @param child_name [String] name of child node.
368
- # @return [Parser::AST::Node] the child node.
369
- def child_node_by_name(child_name)
370
- direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
371
- if respond_to?(direct_child_name)
372
- child_node = send(direct_child_name)
373
-
374
- return child_node.child_node_by_name(nested_child_name) if nested_child_name
375
-
376
- return nil if child_node.nil?
377
-
378
- return child_node if child_node.is_a?(Parser::AST::Node)
379
-
380
- return child_node
381
- end
382
-
383
- raise Synvert::Core::MethodNotSupported,
384
- "child_node_by_name is not handled for #{debug_info}, child_name: #{child_name}"
385
- end
386
-
387
- # Get the source range of child node.
388
- #
389
- # @param child_name [String] name of child node.
390
- # @return [Parser::Source::Range] source range of child node.
391
- def child_node_range(child_name)
392
- case [type, child_name.to_sym]
393
- when %i[block pipes], %i[def parentheses], %i[defs parentheses]
394
- Parser::Source::Range.new(
395
- '(string)',
396
- arguments.first.loc.expression.begin_pos - 1,
397
- arguments.last.loc.expression.end_pos + 1
398
- )
399
- when %i[block arguments], %i[def arguments], %i[defs arguments]
400
- Parser::Source::Range.new(
401
- '(string)',
402
- arguments.first.loc.expression.begin_pos,
403
- arguments.last.loc.expression.end_pos
404
- )
405
- when %i[class name], %i[def name], %i[defs name]
406
- loc.name
407
- when %i[defs dot]
408
- loc.operator
409
- when %i[defs self]
410
- Parser::Source::Range.new('(string)', loc.operator.begin_pos - 'self'.length, loc.operator.begin_pos)
411
- when %i[send dot], %i[csend dot]
412
- loc.dot
413
- when %i[send message], %i[csend message]
414
- if loc.operator
415
- Parser::Source::Range.new('(string)', loc.selector.begin_pos, loc.operator.end_pos)
416
- else
417
- loc.selector
418
- end
419
- when %i[send parentheses], %i[csend parentheses]
420
- if loc.begin && loc.end
421
- Parser::Source::Range.new('(string)', loc.begin.begin_pos, loc.end.end_pos)
422
- end
423
- else
424
- direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
425
- if respond_to?(direct_child_name)
426
- child_node = send(direct_child_name)
427
-
428
- return child_node.child_node_range(nested_child_name) if nested_child_name
429
-
430
- return nil if child_node.nil?
431
-
432
- if child_node.is_a?(Parser::AST::Node)
433
- return(
434
- Parser::Source::Range.new(
435
- '(string)',
436
- child_node.loc.expression.begin_pos,
437
- child_node.loc.expression.end_pos
438
- )
439
- )
440
- end
441
-
442
- # arguments
443
- return nil if child_node.empty?
444
-
445
- return(
446
- Parser::Source::Range.new(
447
- '(string)',
448
- child_node.first.loc.expression.begin_pos,
449
- child_node.last.loc.expression.end_pos
450
- )
451
- )
452
- end
453
-
454
- raise Synvert::Core::MethodNotSupported,
455
- "child_node_range is not handled for #{debug_info}, child_name: #{child_name}"
456
- end
457
- end
458
-
459
- # Recursively iterate all child nodes of node.
460
- #
461
- # @yield [child] Gives a child node.
462
- # @yieldparam child [Parser::AST::Node] child node
463
- def recursive_children(&block)
464
- children.each do |child|
465
- if child.is_a?(Parser::AST::Node)
466
- stop = yield child
467
- child.recursive_children(&block) unless stop == :stop
468
- end
469
- end
470
- end
471
-
472
- # Match node with rules.
473
- # It provides some additional keywords to match rules, +any+, +contain+, +not+, +in+, +not_in+, +gt+, +gte+, +lt+, +lte+.
474
- # @example
475
- # type: 'send', arguments: { any: 'Lifo::ShowExceptions' }
476
- # type: { in: ['send', 'csend'] }
477
- # type: :send, arguments: { length: { gt: 2 } }
478
- # @param rules [Hash] rules to match.
479
- # @return true if matches.
480
- def match?(rules)
481
- keywords = %i[any contain not in not_in gt gte lt lte]
482
- flat_hash(rules).keys.all? do |multi_keys|
483
- last_key = multi_keys.last
484
- actual = keywords.include?(last_key) ? actual_value(multi_keys[0...-1]) : actual_value(multi_keys)
485
- expected = expected_value(rules, multi_keys)
486
- case last_key
487
- when :any, :contain
488
- actual.any? { |actual_value| match_value?(actual_value, expected) }
489
- when :not
490
- !match_value?(actual, expected)
491
- when :in
492
- expected.any? { |expected_value| match_value?(actual, expected_value) }
493
- when :not_in
494
- expected.all? { |expected_value| !match_value?(actual, expected_value) }
495
- when :gt
496
- actual > expected
497
- when :gte
498
- actual >= expected
499
- when :lt
500
- actual < expected
501
- when :lte
502
- actual <= expected
503
- else
504
- match_value?(actual, expected)
505
- end
506
- end
507
- end
508
-
509
- # Get rewritten source code.
510
- # @example
511
- # node.rewritten_source("create({{arguments}})") # "create(:post)"
512
- # @param code [String] raw code.
513
- # @return [String] rewritten code, replace string in block !{{ }} in raw code.
514
- # @raise [Synvert::Core::MethodNotSupported] if string in block !{{ }} does not support.
515
- def rewritten_source(code)
516
- code.gsub(/{{(.*?)}}/m) do
517
- old_code = Regexp.last_match(1)
518
- if respond_to?(old_code.split('.').first)
519
- evaluated = child_node_by_name(old_code)
520
- case evaluated
521
- when Parser::AST::Node
522
- if evaluated.type == :args
523
- evaluated.loc.expression.source[1...-1]
524
- else
525
- evaluated.loc.expression.source
526
- end
527
- when Array
528
- if evaluated.size > 0
529
- file_source = evaluated.first.loc.expression.source_buffer.source
530
- source = file_source[evaluated.first.loc.expression.begin_pos...evaluated.last.loc.expression.end_pos]
531
- lines = source.split "\n"
532
- lines_count = lines.length
533
- if lines_count > 1 && lines_count == evaluated.size
534
- new_code = []
535
- lines.each_with_index { |line, index|
536
- new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
537
- }
538
- new_code.join("\n")
539
- else
540
- source
541
- end
542
- end
543
- when String, Symbol, Integer, Float
544
- evaluated
545
- when NilClass
546
- 'nil'
547
- else
548
- raise Synvert::Core::MethodNotSupported, "rewritten_source is not handled for #{evaluated.inspect}"
549
- end
550
- else
551
- "{{#{old_code}}}"
552
- end
553
- end
554
- end
555
-
556
53
  # Strip curly braces for hash.
557
54
  # @example
558
55
  # node # s(:hash, s(:pair, s(:sym, :foo), s(:str, "bar")))
@@ -627,141 +124,5 @@ module Parser::AST
627
124
  to_source
628
125
  end
629
126
  end
630
-
631
- # Convert node to a hash, so that it can be converted to a json.
632
- def to_hash
633
- result = { type: type }
634
- if TYPE_CHILDREN[type]
635
- TYPE_CHILDREN[type].each do |key|
636
- value = send(key)
637
- result[key] =
638
- case value
639
- when Array
640
- value.map { |v| v.respond_to?(:to_hash) ? v.to_hash : v }
641
- when Parser::AST::Node
642
- value.to_hash
643
- else
644
- value
645
- end
646
- end
647
- else
648
- result[:children] = children.map { |c| c.respond_to?(:to_hash) ? c.to_hash : c }
649
- end
650
- result
651
- end
652
-
653
- private
654
-
655
- # Compare actual value with expected value.
656
- #
657
- # @param actual [Object] actual value.
658
- # @param expected [Object] expected value.
659
- # @return [Boolean]
660
- # @raise [Synvert::Core::MethodNotSupported] if expected class is not supported.
661
- def match_value?(actual, expected)
662
- return true if actual == expected
663
-
664
- case expected
665
- when Symbol
666
- if actual.is_a?(Parser::AST::Node)
667
- actual.to_source == ":#{expected}" || actual.to_source == expected.to_s
668
- else
669
- actual.to_sym == expected
670
- end
671
- when String
672
- if actual.is_a?(Parser::AST::Node)
673
- actual.to_source == expected || actual.to_source == unwrap_quote(expected) ||
674
- unwrap_quote(actual.to_source) == expected || unwrap_quote(actual.to_source) == unwrap_quote(expected)
675
- else
676
- actual.to_s == expected || wrap_quote(actual.to_s) == expected
677
- end
678
- when Regexp
679
- if actual.is_a?(Parser::AST::Node)
680
- actual.to_source =~ Regexp.new(expected.to_s, Regexp::MULTILINE)
681
- else
682
- actual.to_s =~ Regexp.new(expected.to_s, Regexp::MULTILINE)
683
- end
684
- when Array
685
- return false unless expected.length == actual.length
686
-
687
- actual.zip(expected).all? { |a, e| match_value?(a, e) }
688
- when NilClass
689
- if actual.is_a?(Parser::AST::Node)
690
- :nil == actual.type
691
- else
692
- actual.nil?
693
- end
694
- when Numeric
695
- if actual.is_a?(Parser::AST::Node)
696
- actual.children[0] == expected
697
- else
698
- actual == expected
699
- end
700
- when TrueClass
701
- :true == actual.type
702
- when FalseClass
703
- :false == actual.type
704
- when Parser::AST::Node
705
- actual == expected
706
- when Synvert::Core::Rewriter::AnyValue
707
- !actual.nil?
708
- else
709
- raise Synvert::Core::MethodNotSupported, "#{expected.class} is not handled for match_value?"
710
- end
711
- end
712
-
713
- # Convert a hash to flat one.
714
- #
715
- # @example
716
- # flat_hash(type: 'block', caller: {type: 'send', receiver: 'RSpec'})
717
- # # {[:type] => 'block', [:caller, :type] => 'send', [:caller, :receiver] => 'RSpec'}
718
- # @param h [Hash] original hash.
719
- # @return flatten hash.
720
- def flat_hash(h, k = [])
721
- new_hash = {}
722
- h.each_pair do |key, val|
723
- if val.is_a?(Hash)
724
- new_hash.merge!(flat_hash(val, k + [key]))
725
- else
726
- new_hash[k + [key]] = val
727
- end
728
- end
729
- new_hash
730
- end
731
-
732
- # Get actual value from the node.
733
- #
734
- # @param multi_keys [Array<Symbol, String>]
735
- # @return [Object] actual value.
736
- def actual_value(multi_keys)
737
- multi_keys.inject(self) { |n, key| n.send(key) if n }
738
- end
739
-
740
- # Get expected value from rules.
741
- #
742
- # @param rules [Hash]
743
- # @param multi_keys [Array<Symbol>]
744
- # @return [Object] expected value.
745
- def expected_value(rules, multi_keys)
746
- multi_keys.inject(rules) { |o, key| o[key] }
747
- end
748
-
749
- # Wrap the string with single or double quote.
750
- def wrap_quote(string)
751
- if string.include?("'")
752
- "\"#{string}\""
753
- else
754
- "'#{string}'"
755
- end
756
- end
757
-
758
- # Unwrap the quote from the string.
759
- def unwrap_quote(string)
760
- if (string[0] == '"' && string[-1] == '"') || (string[0] == "'" && string[-1] == "'")
761
- string[1...-1]
762
- else
763
- string
764
- end
765
- end
766
127
  end
767
128
  end