synvert-core 0.15.2 → 0.19.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -2
  3. data/Gemfile +2 -0
  4. data/Guardfile +2 -0
  5. data/Rakefile +2 -0
  6. data/lib/synvert/core.rb +2 -3
  7. data/lib/synvert/core/configuration.rb +10 -17
  8. data/lib/synvert/core/engine.rb +1 -1
  9. data/lib/synvert/core/engine/erb.rb +31 -23
  10. data/lib/synvert/core/exceptions.rb +5 -3
  11. data/lib/synvert/core/node_ext.rb +107 -101
  12. data/lib/synvert/core/rewriter.rb +22 -16
  13. data/lib/synvert/core/rewriter/action.rb +4 -6
  14. data/lib/synvert/core/rewriter/action/append_action.rb +3 -3
  15. data/lib/synvert/core/rewriter/action/insert_action.rb +9 -5
  16. data/lib/synvert/core/rewriter/action/insert_after_action.rb +2 -2
  17. data/lib/synvert/core/rewriter/action/remove_action.rb +2 -2
  18. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +5 -4
  19. data/lib/synvert/core/rewriter/action/replace_with_action.rb +7 -5
  20. data/lib/synvert/core/rewriter/condition.rb +1 -1
  21. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +2 -2
  22. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +2 -3
  23. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +2 -2
  24. data/lib/synvert/core/rewriter/gem_spec.rb +11 -11
  25. data/lib/synvert/core/rewriter/helper.rb +4 -6
  26. data/lib/synvert/core/rewriter/instance.rb +37 -23
  27. data/lib/synvert/core/rewriter/ruby_version.rb +1 -1
  28. data/lib/synvert/core/rewriter/scope.rb +1 -1
  29. data/lib/synvert/core/rewriter/scope/goto_scope.rb +2 -1
  30. data/lib/synvert/core/rewriter/scope/within_scope.rb +23 -7
  31. data/lib/synvert/core/rewriter/warning.rb +1 -1
  32. data/lib/synvert/core/version.rb +2 -2
  33. data/spec/spec_helper.rb +3 -6
  34. data/spec/support/parser_helper.rb +2 -0
  35. data/spec/synvert/core/engine/erb_spec.rb +32 -30
  36. data/spec/synvert/core/node_ext_spec.rb +57 -54
  37. data/spec/synvert/core/rewriter/action/append_action_spec.rb +2 -0
  38. data/spec/synvert/core/rewriter/action/insert_action_spec.rb +10 -8
  39. data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +5 -3
  40. data/spec/synvert/core/rewriter/action/remove_action_spec.rb +3 -1
  41. data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +2 -0
  42. data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +17 -11
  43. data/spec/synvert/core/rewriter/action_spec.rb +2 -0
  44. data/spec/synvert/core/rewriter/condition/if_exist_condition_spec.rb +19 -9
  45. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +23 -12
  46. data/spec/synvert/core/rewriter/condition/unless_exist_condition_spec.rb +19 -9
  47. data/spec/synvert/core/rewriter/condition_spec.rb +2 -0
  48. data/spec/synvert/core/rewriter/gem_spec_spec.rb +13 -10
  49. data/spec/synvert/core/rewriter/helper_spec.rb +36 -31
  50. data/spec/synvert/core/rewriter/instance_spec.rb +118 -66
  51. data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +10 -6
  52. data/spec/synvert/core/rewriter/scope/within_scope.rb +18 -9
  53. data/spec/synvert/core/rewriter/scope_spec.rb +2 -0
  54. data/spec/synvert/core/rewriter/warning_spec.rb +2 -0
  55. data/spec/synvert/core/rewriter_spec.rb +106 -73
  56. metadata +2 -4
  57. data/spec/synvert/core/configuration_spec.rb +0 -10
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # Rewriter is the top level namespace in a snippet.
@@ -42,7 +42,14 @@ module Synvert::Core
42
42
  autoload :RubyVersion, 'synvert/core/rewriter/ruby_version'
43
43
  autoload :GemSpec, 'synvert/core/rewriter/gem_spec'
44
44
 
45
- class <<self
45
+ class << self
46
+ # Execute the temporary rewriter without group and name.
47
+ #
48
+ # @param block [Block] a block defines the behaviors of the rewriter.
49
+ def execute(&block)
50
+ Rewriter.new('', '', &block).process
51
+ end
52
+
46
53
  # Register a rewriter with its group and name.
47
54
  #
48
55
  # @param group [String] the rewriter group.
@@ -65,7 +72,7 @@ module Synvert::Core
65
72
  if exist? group, name
66
73
  rewriters[group][name]
67
74
  else
68
- raise RewriterNotFound.new "Rewriter #{group} #{name} not found"
75
+ raise RewriterNotFound, "Rewriter #{group} #{name} not found"
69
76
  end
70
77
  end
71
78
 
@@ -82,7 +89,7 @@ module Synvert::Core
82
89
  rewriter.process
83
90
  rewriter
84
91
  else
85
- raise RewriterNotFound.new "Rewriter #{group}/#{name} not found"
92
+ raise RewriterNotFound, "Rewriter #{group}/#{name} not found"
86
93
  end
87
94
  end
88
95
 
@@ -112,7 +119,7 @@ module Synvert::Core
112
119
  rewriters.clear
113
120
  end
114
121
 
115
- private
122
+ private
116
123
 
117
124
  def rewriters
118
125
  @rewriters ||= {}
@@ -151,14 +158,14 @@ module Synvert::Core
151
158
  # Process the rewriter.
152
159
  # It will call the block.
153
160
  def process
154
- self.instance_eval &@block
161
+ instance_eval &@block
155
162
  end
156
163
 
157
164
  # Process rewriter with sandbox mode.
158
165
  # It will call the block but doesn't change any file.
159
166
  def process_with_sandbox
160
167
  @sandbox = true
161
- self.process
168
+ process
162
169
  @sandbox = false
163
170
  end
164
171
 
@@ -178,7 +185,7 @@ module Synvert::Core
178
185
  #
179
186
  # @param description [String] rewriter description.
180
187
  # @return rewriter description.
181
- def description(description=nil)
188
+ def description(description = nil)
182
189
  if description
183
190
  @description = description
184
191
  else
@@ -208,17 +215,16 @@ module Synvert::Core
208
215
  # @param file_pattern [String] pattern to find files, e.g. spec/**/*_spec.rb
209
216
  # @param options [Hash] instance options.
210
217
  # @param block [Block] the block to rewrite code in the matching files.
211
- def within_files(file_pattern, options={}, &block)
218
+ def within_files(file_pattern, options = {}, &block)
212
219
  return if @sandbox
213
220
 
214
- if (!@ruby_version || @ruby_version.match?) &&
215
- (!@gem_spec || @gem_spec.match?)
221
+ if (!@ruby_version || @ruby_version.match?) && (!@gem_spec || @gem_spec.match?)
216
222
  Rewriter::Instance.new(self, file_pattern, options, &block).process
217
223
  end
218
224
  end
219
225
 
220
226
  # Parse within_file dsl, it finds a specifiled file.
221
- alias_method :within_file, :within_files
227
+ alias within_file within_files
222
228
 
223
229
  # Parses add_file dsl, it adds a new file.
224
230
  #
@@ -227,7 +233,7 @@ module Synvert::Core
227
233
  def add_file(filename, content)
228
234
  return if @sandbox
229
235
 
230
- filepath = File.join(Configuration.instance.get(:path), filename)
236
+ filepath = File.join(Configuration.path, filename)
231
237
  if File.exist?(filepath)
232
238
  puts "File #{filepath} already exists."
233
239
  return
@@ -245,7 +251,7 @@ module Synvert::Core
245
251
  def remove_file(filename)
246
252
  return if @sandbox
247
253
 
248
- file_path = File.join(Configuration.instance.get(:path), filename)
254
+ file_path = File.join(Configuration.path, filename)
249
255
  File.delete(file_path) if File.exist?(file_path)
250
256
  end
251
257
 
@@ -262,7 +268,7 @@ module Synvert::Core
262
268
  # @param name [String] helper method name.
263
269
  # @param block [Block] helper method block.
264
270
  def helper_method(name, &block)
265
- @helpers << {name: name, block: block}
271
+ @helpers << { name: name, block: block }
266
272
  end
267
273
 
268
274
  # Parse todo dsl, it sets todo of the rewriter.
@@ -270,7 +276,7 @@ module Synvert::Core
270
276
  #
271
277
  # @param todo_list [String] rewriter todo.
272
278
  # @return [String] rewriter todo.
273
- def todo(todo=nil)
279
+ def todo(todo = nil)
274
280
  if todo
275
281
  @todo = todo
276
282
  else
@@ -1,9 +1,9 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # Action defines rewriter action, add, replace or remove code.
5
5
  class Rewriter::Action
6
- DEFAULT_OPTIONS = { autoindent: true }
6
+ DEFAULT_OPTIONS = { autoindent: true }.freeze
7
7
  DEFAULT_INDENT = 2
8
8
 
9
9
  # Initialize an action.
@@ -11,7 +11,7 @@ module Synvert::Core
11
11
  # @param instance [Synvert::Core::Rewriter::Instance]
12
12
  # @param code [String] new code to add, replace or remove.
13
13
  # @param options [Hash] action options, it includes :autoindent.
14
- def initialize(instance, code, options={})
14
+ def initialize(instance, code, options = {})
15
15
  @instance = instance
16
16
  @code = code
17
17
  @options = DEFAULT_OPTIONS.merge(options)
@@ -30,9 +30,7 @@ module Synvert::Core
30
30
  # @return [String] rewritten code.
31
31
  def rewritten_code
32
32
  if rewritten_source.split("\n").length > 1
33
- "\n\n" + rewritten_source.split("\n").map { |line|
34
- indent(@node) + line
35
- }.join("\n")
33
+ "\n\n" + rewritten_source.split("\n").map { |line| indent(@node) + line }.join("\n")
36
34
  else
37
35
  "\n" + indent(@node) + rewritten_source
38
36
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # AppendAction to append code to the bottom of node body.
@@ -23,14 +23,14 @@ module Synvert::Core
23
23
  begin_pos
24
24
  end
25
25
 
26
- private
26
+ private
27
27
 
28
28
  # Indent of the node.
29
29
  #
30
30
  # @param node [Parser::AST::Node]
31
31
  # @return [String] n times whitesphace
32
32
  def indent(node)
33
- if [:block, :class].include? node.type
33
+ if %i[block class].include? node.type
34
34
  ' ' * (node.indent + DEFAULT_INDENT)
35
35
  else
36
36
  ' ' * node.indent
@@ -1,9 +1,9 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # InsertAction to insert code to the top of node body.
5
5
  class Rewriter::InsertAction < Rewriter::Action
6
- DO_LENGTH = " do".length
6
+ DO_LENGTH = ' do'.length
7
7
 
8
8
  # Begin position to insert code.
9
9
  #
@@ -11,7 +11,11 @@ module Synvert::Core
11
11
  def begin_pos
12
12
  case @node.type
13
13
  when :block
14
- @node.children[1].children.empty? ? @node.children[0].loc.expression.end_pos + DO_LENGTH : @node.children[1].loc.expression.end_pos
14
+ if @node.children[1].children.empty?
15
+ @node.children[0].loc.expression.end_pos + DO_LENGTH
16
+ else
17
+ @node.children[1].loc.expression.end_pos
18
+ end
15
19
  when :class
16
20
  @node.children[1] ? @node.children[1].loc.expression.end_pos : @node.children[0].loc.expression.end_pos
17
21
  else
@@ -26,14 +30,14 @@ module Synvert::Core
26
30
  begin_pos
27
31
  end
28
32
 
29
- private
33
+ private
30
34
 
31
35
  # Indent of the node.
32
36
  #
33
37
  # @param node [Parser::AST::Node]
34
38
  # @return [String] n times whitesphace
35
39
  def indent(node)
36
- if [:block, :class].include? node.type
40
+ if %i[block class].include? node.type
37
41
  ' ' * (node.indent + DEFAULT_INDENT)
38
42
  else
39
43
  ' ' * node.indent
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # InsertAfterAction to insert code next to the node.
@@ -17,7 +17,7 @@ module Synvert::Core
17
17
  begin_pos
18
18
  end
19
19
 
20
- private
20
+ private
21
21
 
22
22
  # Indent of the node.
23
23
  #
@@ -1,9 +1,9 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # RemoveAction to remove code.
5
5
  class Rewriter::RemoveAction < Rewriter::Action
6
- def initialize(instance, code=nil)
6
+ def initialize(instance, code = nil)
7
7
  super
8
8
  end
9
9
 
@@ -1,10 +1,10 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # ReplaceErbStmtWithExprAction to replace erb stmt code to expr,
5
5
  # e.g. <% form_for ... %> => <%= form_for ... %>.
6
6
  class Rewriter::ReplaceErbStmtWithExprAction < Rewriter::Action
7
- def initialize(instance, code=nil)
7
+ def initialize(instance, code = nil)
8
8
  super
9
9
  end
10
10
 
@@ -23,7 +23,7 @@ module Synvert::Core
23
23
  # @return [Integer] end position.
24
24
  def end_pos
25
25
  node_begin_pos = @node.loc.expression.begin_pos
26
- node_begin_pos += @node.loc.expression.source.index "do"
26
+ node_begin_pos += @node.loc.expression.source.index 'do'
27
27
  while @node.loc.expression.source_buffer.source[node_begin_pos += 1] != '@'
28
28
  end
29
29
  node_begin_pos
@@ -33,7 +33,8 @@ module Synvert::Core
33
33
  #
34
34
  # @return [String] rewritten code.
35
35
  def rewritten_code
36
- @node.loc.expression.source_buffer.source[begin_pos...end_pos].sub(Engine::ERUBY_STMT_SPLITTER, "@output_buffer.append= ")
36
+ @node.loc.expression.source_buffer.source[begin_pos...end_pos]
37
+ .sub(Engine::ERUBY_STMT_SPLITTER, '@output_buffer.append= ')
37
38
  .sub(Engine::ERUBY_STMT_SPLITTER, Engine::ERUBY_EXPR_SPLITTER)
38
39
  end
39
40
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # ReplaceWithAction to replace code.
@@ -23,16 +23,18 @@ module Synvert::Core
23
23
  def rewritten_code
24
24
  if rewritten_source.split("\n").length > 1
25
25
  new_code = []
26
- rewritten_source.split("\n").each_with_index { |line, index|
27
- new_code << (index == 0 || !@options[:autoindent] ? line : indent(@node) + line)
28
- }
26
+ rewritten_source
27
+ .split("\n")
28
+ .each_with_index { |line, index|
29
+ new_code << (index == 0 || !@options[:autoindent] ? line : indent(@node) + line)
30
+ }
29
31
  new_code.join("\n")
30
32
  else
31
33
  rewritten_source
32
34
  end
33
35
  end
34
36
 
35
- private
37
+ private
36
38
 
37
39
  # Indent of the node
38
40
  #
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # Condition checks if rules matches.
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # IfExistCondition checks if matching node exists in the node children.
@@ -7,7 +7,7 @@ module Synvert::Core
7
7
  def match?
8
8
  match = false
9
9
  @instance.current_node.recursive_children do |child_node|
10
- match = match || (child_node && child_node.match?(@rules))
10
+ match ||= (child_node&.match?(@rules))
11
11
  end
12
12
  match
13
13
  end
@@ -1,12 +1,11 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # IfExistCondition checks if node has only one child node and the child node matches rules.
5
5
  class Rewriter::IfOnlyExistCondition < Rewriter::Condition
6
6
  # check if only have one child node and the child node matches rules.
7
7
  def match?
8
- @instance.current_node.body.size == 1 &&
9
- @instance.current_node.body.first.match?(@rules)
8
+ @instance.current_node.body.size == 1 && @instance.current_node.body.first.match?(@rules)
10
9
  end
11
10
  end
12
11
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # UnlessExistCondition checks if matching node doesn't exist in the node children.
@@ -7,7 +7,7 @@ module Synvert::Core
7
7
  def match?
8
8
  match = false
9
9
  @instance.current_node.recursive_children do |child_node|
10
- match = match || (child_node && child_node.match?(@rules))
10
+ match ||= (child_node&.match?(@rules))
11
11
  end
12
12
  !match
13
13
  end
@@ -1,9 +1,9 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # GemSpec checks and compares gem version.
5
5
  class Rewriter::GemSpec
6
- OPERATORS = {eq: '==', lt: '<', gt: '>', lte: '<=', gte: '>=', ne: '!='}
6
+ OPERATORS = { eq: '==', lt: '<', gt: '>', lte: '<=', gte: '>=', ne: '!=' }.freeze
7
7
 
8
8
  # Initialize a gem_spec.
9
9
  #
@@ -26,16 +26,16 @@ module Synvert::Core
26
26
  # @return [Boolean] true if matches, otherwise false.
27
27
  # @raise [Synvert::Core::GemfileLockNotFound] raise if Gemfile.lock does not exist.
28
28
  def match?
29
- gemfile_lock_path = File.join(Configuration.instance.get(:path), 'Gemfile.lock')
30
- if File.exists? gemfile_lock_path
31
- parser = Bundler::LockfileParser.new(File.read(gemfile_lock_path))
32
- if spec = parser.specs.find { |spec| spec.name == @name }
33
- Gem::Version.new(spec.version).send(OPERATORS[@operator], @version)
34
- else
35
- false
36
- end
29
+ gemfile_lock_path = File.join(Configuration.path, 'Gemfile.lock')
30
+
31
+ # if Gemfile.lock does not exist, just ignore this check
32
+ return true unless File.exist?(gemfile_lock_path)
33
+
34
+ parser = Bundler::LockfileParser.new(File.read(gemfile_lock_path))
35
+ if spec = parser.specs.find { |spec| spec.name == @name }
36
+ Gem::Version.new(spec.version).send(OPERATORS[@operator], @version)
37
37
  else
38
- raise GemfileLockNotFound.new 'Gemfile.lock does not exist'
38
+ false
39
39
  end
40
40
  end
41
41
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # Rewriter::Helper provides some helper methods to make it easier to write a snippet.
@@ -34,9 +34,9 @@ module Synvert::Core
34
34
  # if current_node has argument, it returns "({{arguments}})"
35
35
  def add_arguments_with_parenthesis_if_necessary
36
36
  if node.arguments.size > 0
37
- "({{arguments}})"
37
+ '({{arguments}})'
38
38
  else
39
- ""
39
+ ''
40
40
  end
41
41
  end
42
42
 
@@ -65,9 +65,7 @@ module Synvert::Core
65
65
  #
66
66
  # strip_brackets("(1..100)") #=> "1..100"
67
67
  def strip_brackets(code)
68
- code.sub(/^\((.*)\)$/) { $1 }
69
- .sub(/^\[(.*)\]$/) { $1 }
70
- .sub(/^{(.*)}$/) { $1 }
68
+ code.sub(/^\((.*)\)$/) { $1 }.sub(/^\[(.*)\]$/) { $1 }.sub(/^{(.*)}$/) { $1 }
71
69
  end
72
70
  end
73
71
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
4
  # Instance is an execution unit, it finds specified ast nodes,
@@ -8,7 +8,7 @@ module Synvert::Core
8
8
  class Rewriter::Instance
9
9
  include Rewriter::Helper
10
10
 
11
- class <<self
11
+ class << self
12
12
  # Cached file source.
13
13
  #
14
14
  # @param file_path [String] file path
@@ -64,7 +64,7 @@ module Synvert::Core
64
64
  # @return current filename
65
65
  attr_accessor :current_node, :current_file
66
66
 
67
- DEFAULT_OPTIONS = { sort_by: 'begin_pos' }
67
+ DEFAULT_OPTIONS = { sort_by: 'begin_pos' }.freeze
68
68
 
69
69
  # Initialize an instance.
70
70
  #
@@ -73,30 +73,33 @@ module Synvert::Core
73
73
  # @param options [Hash] instance options, it includes :sort_by.
74
74
  # @param block [Block] block code to find nodes, match conditions and rewrite code.
75
75
  # @return [Synvert::Core::Rewriter::Instance]
76
- def initialize(rewriter, file_pattern, options={}, &block)
76
+ def initialize(rewriter, file_pattern, options = {}, &block)
77
77
  @rewriter = rewriter
78
78
  @actions = []
79
79
  @file_pattern = file_pattern
80
80
  @options = DEFAULT_OPTIONS.merge(options)
81
81
  @block = block
82
- rewriter.helpers.each { |helper| self.singleton_class.send(:define_method, helper[:name], &helper[:block]) }
82
+ rewriter.helpers.each { |helper| singleton_class.send(:define_method, helper[:name], &helper[:block]) }
83
83
  end
84
84
 
85
85
  # Process the instance.
86
86
  # It finds all files, for each file, it executes the block code, gets all rewrite actions,
87
87
  # and rewrite source code back to original file.
88
88
  def process
89
- file_pattern = File.join(Configuration.instance.get(:path), @file_pattern)
90
- Dir.glob(file_pattern).each do |file_path|
91
- unless Configuration.instance.get(:skip_files).include? file_path
89
+ file_pattern = File.join(Configuration.path, @file_pattern)
90
+ Dir
91
+ .glob(file_pattern)
92
+ .each do |file_path|
93
+ next if Configuration.skip_files.include? file_path
94
+
92
95
  begin
93
96
  conflict_actions = []
94
- source = self.class.file_source(file_path)
97
+ source = +self.class.file_source(file_path)
95
98
  ast = self.class.file_ast(file_path)
96
99
 
97
100
  @current_file = file_path
98
101
 
99
- self.process_with_node ast do
102
+ process_with_node ast do
100
103
  begin
101
104
  instance_eval &@block
102
105
  rescue NoMethodError
@@ -108,7 +111,7 @@ module Synvert::Core
108
111
  if @actions.length > 0
109
112
  @actions.sort_by! { |action| action.send(@options[:sort_by]) }
110
113
  conflict_actions = get_conflict_actions
111
- @actions.reverse.each do |action|
114
+ @actions.reverse_each do |action|
112
115
  source[action.begin_pos...action.end_pos] = action.rewritten_code
113
116
  source = remove_code_or_whole_line(source, action.line)
114
117
  end
@@ -121,7 +124,6 @@ module Synvert::Core
121
124
  # do nothing, iterate next file
122
125
  end while !conflict_actions.empty?
123
126
  end
124
- end
125
127
  end
126
128
 
127
129
  # Gets current node, it allows to get current node in block code.
@@ -146,7 +148,7 @@ module Synvert::Core
146
148
  # @param node [Parser::AST::Node] node set to current_node
147
149
  # @yield process
148
150
  def process_with_other_node(node)
149
- original_node = self.current_node
151
+ original_node = current_node
150
152
  self.current_node = node
151
153
  yield
152
154
  self.current_node = original_node
@@ -156,15 +158,28 @@ module Synvert::Core
156
158
  # DSL #
157
159
  #######
158
160
 
159
- # Parse within_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find matching ast nodes,
161
+ # Parse within_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find recursive matching ast nodes,
160
162
  # then continue operating on each matching ast node.
161
163
  #
162
164
  # @param rules [Hash] rules to find mathing ast nodes.
163
165
  # @param block [Block] block code to continue operating on the matching nodes.
164
166
  def within_node(rules, &block)
165
- Rewriter::WithinScope.new(self, rules, &block).process
167
+ Rewriter::WithinScope.new(self, rules, { recursive: true }, &block).process
166
168
  end
167
169
 
170
+ alias with_node within_node
171
+
172
+ # Parse within_direct_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find direct matching ast nodes,
173
+ # then continue operating on each matching ast node.
174
+ #
175
+ # @param rules [Hash] rules to find mathing ast nodes.
176
+ # @param block [Block] block code to continue operating on the matching nodes.
177
+ def within_direct_node(rules, &block)
178
+ Rewriter::WithinScope.new(self, rules, { recursive: false }, &block).process
179
+ end
180
+
181
+ alias with_direct_node within_direct_node
182
+
168
183
  # Parse goto_node dsl, it creates a [Synvert::Core::Rewriter::GotoScope] to go to a child node,
169
184
  # then continue operating on the child node.
170
185
  #
@@ -174,8 +189,6 @@ module Synvert::Core
174
189
  Rewriter::GotoScope.new(self, child_node_name, &block).process
175
190
  end
176
191
 
177
- alias_method :with_node, :within_node
178
-
179
192
  # Parse if_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfExistCondition] to check
180
193
  # if matching nodes exist in the child nodes, if so, then continue operating on each matching ast node.
181
194
  #
@@ -209,7 +222,7 @@ module Synvert::Core
209
222
  #
210
223
  # @param code [String] code need to be appended.
211
224
  # @param options [Hash] action options.
212
- def append(code, options={})
225
+ def append(code, options = {})
213
226
  @actions << Rewriter::AppendAction.new(self, code, options)
214
227
  end
215
228
 
@@ -218,7 +231,7 @@ module Synvert::Core
218
231
  #
219
232
  # @param code [String] code need to be inserted.
220
233
  # @param options [Hash] action options.
221
- def insert(code, options={})
234
+ def insert(code, options = {})
222
235
  @actions << Rewriter::InsertAction.new(self, code, options)
223
236
  end
224
237
 
@@ -227,7 +240,7 @@ module Synvert::Core
227
240
  #
228
241
  # @param code [String] code need to be inserted.
229
242
  # @param options [Hash] action options.
230
- def insert_after(node, options={})
243
+ def insert_after(node, options = {})
231
244
  @actions << Rewriter::InsertAfterAction.new(self, node, options)
232
245
  end
233
246
 
@@ -236,7 +249,7 @@ module Synvert::Core
236
249
  #
237
250
  # @param code [String] code need to be replaced with.
238
251
  # @param options [Hash] action options.
239
- def replace_with(code, options={})
252
+ def replace_with(code, options = {})
240
253
  @actions << Rewriter::ReplaceWithAction.new(self, code, options)
241
254
  end
242
255
 
@@ -258,7 +271,7 @@ module Synvert::Core
258
271
  @rewriter.add_warning Rewriter::Warning.new(self, message)
259
272
  end
260
273
 
261
- private
274
+ private
262
275
 
263
276
  # It changes source code from bottom to top, and it can change source code twice at the same time,
264
277
  # So if there is an overlap between two actions, it removes the conflict actions and operate them in the next loop.
@@ -290,7 +303,8 @@ module Synvert::Core
290
303
  source_arr = source.split("\n")
291
304
  if source_arr[line - 1] && source_arr[line - 1].strip.empty?
292
305
  source_arr.delete_at(line - 1)
293
- if source_arr[line - 2] && source_arr[line - 2].strip.empty? && source_arr[line - 1] && source_arr[line - 1].strip.empty?
306
+ if source_arr[line - 2] && source_arr[line - 2].strip.empty? && source_arr[line - 1] &&
307
+ source_arr[line - 1].strip.empty?
294
308
  source_arr.delete_at(line - 1)
295
309
  end
296
310
  source_arr.join("\n") + (newline_at_end_of_line ? "\n" : '')