synvert-core 1.4.0 → 1.6.0

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