synvert-core 0.15.2 → 0.19.0

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