synvert-core 0.17.0 → 0.18.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/synvert/core.rb +1 -1
  4. data/lib/synvert/core/engine/erb.rb +29 -22
  5. data/lib/synvert/core/node_ext.rb +102 -101
  6. data/lib/synvert/core/rewriter.rb +19 -13
  7. data/lib/synvert/core/rewriter/action.rb +3 -5
  8. data/lib/synvert/core/rewriter/action/append_action.rb +1 -1
  9. data/lib/synvert/core/rewriter/action/insert_action.rb +7 -3
  10. data/lib/synvert/core/rewriter/action/insert_after_action.rb +1 -1
  11. data/lib/synvert/core/rewriter/action/remove_action.rb +1 -1
  12. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +4 -3
  13. data/lib/synvert/core/rewriter/action/replace_with_action.rb +6 -4
  14. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -1
  15. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +1 -2
  16. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -1
  17. data/lib/synvert/core/rewriter/gem_spec.rb +2 -1
  18. data/lib/synvert/core/rewriter/helper.rb +3 -5
  19. data/lib/synvert/core/rewriter/instance.rb +20 -17
  20. data/lib/synvert/core/version.rb +1 -1
  21. data/spec/spec_helper.rb +1 -1
  22. data/spec/synvert/core/engine/erb_spec.rb +30 -30
  23. data/spec/synvert/core/node_ext_spec.rb +53 -52
  24. data/spec/synvert/core/rewriter/action/insert_action_spec.rb +8 -8
  25. data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +3 -3
  26. data/spec/synvert/core/rewriter/action/remove_action_spec.rb +1 -1
  27. data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +13 -9
  28. data/spec/synvert/core/rewriter/condition/if_exist_condition_spec.rb +17 -9
  29. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +21 -12
  30. data/spec/synvert/core/rewriter/condition/unless_exist_condition_spec.rb +17 -9
  31. data/spec/synvert/core/rewriter/gem_spec_spec.rb +6 -4
  32. data/spec/synvert/core/rewriter/helper_spec.rb +34 -31
  33. data/spec/synvert/core/rewriter/instance_spec.rb +100 -66
  34. data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +8 -6
  35. data/spec/synvert/core/rewriter/scope/within_scope.rb +15 -8
  36. data/spec/synvert/core/rewriter_spec.rb +99 -68
  37. metadata +2 -2
@@ -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
  #
@@ -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
@@ -3,7 +3,7 @@
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
@@ -23,7 +23,7 @@ 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
  #
@@ -3,7 +3,7 @@
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,7 +30,7 @@ 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
  #
@@ -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
  #
@@ -3,7 +3,7 @@
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
 
@@ -4,7 +4,7 @@ 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
@@ -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
  #
@@ -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
@@ -5,8 +5,7 @@ module Synvert::Core
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
@@ -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
@@ -3,7 +3,7 @@
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
  #
@@ -27,6 +27,7 @@ module Synvert::Core
27
27
  # @raise [Synvert::Core::GemfileLockNotFound] raise if Gemfile.lock does not exist.
28
28
  def match?
29
29
  gemfile_lock_path = File.join(Configuration.instance.get(:path), 'Gemfile.lock')
30
+
30
31
  # if Gemfile.lock does not exist, just ignore this check
31
32
  return true unless File.exist?(gemfile_lock_path)
32
33
 
@@ -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
@@ -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,13 +73,13 @@ 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.
@@ -87,8 +87,11 @@ module Synvert::Core
87
87
  # and rewrite source code back to original file.
88
88
  def process
89
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
90
+ Dir
91
+ .glob(file_pattern)
92
+ .each do |file_path|
93
+ next if Configuration.instance.get(:skip_files).include? file_path
94
+
92
95
  begin
93
96
  conflict_actions = []
94
97
  source = +self.class.file_source(file_path)
@@ -96,7 +99,7 @@ module Synvert::Core
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
@@ -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
@@ -165,7 +167,7 @@ module Synvert::Core
165
167
  Rewriter::WithinScope.new(self, rules, { recursive: true }, &block).process
166
168
  end
167
169
 
168
- alias_method :with_node, :within_node
170
+ alias with_node within_node
169
171
 
170
172
  # Parse within_direct_node dsl, it creates a [Synvert::Core::Rewriter::WithinScope] to find direct matching ast nodes,
171
173
  # then continue operating on each matching ast node.
@@ -176,7 +178,7 @@ module Synvert::Core
176
178
  Rewriter::WithinScope.new(self, rules, { recursive: false }, &block).process
177
179
  end
178
180
 
179
- alias_method :with_direct_node, :within_direct_node
181
+ alias with_direct_node within_direct_node
180
182
 
181
183
  # Parse goto_node dsl, it creates a [Synvert::Core::Rewriter::GotoScope] to go to a child node,
182
184
  # then continue operating on the child node.
@@ -220,7 +222,7 @@ module Synvert::Core
220
222
  #
221
223
  # @param code [String] code need to be appended.
222
224
  # @param options [Hash] action options.
223
- def append(code, options={})
225
+ def append(code, options = {})
224
226
  @actions << Rewriter::AppendAction.new(self, code, options)
225
227
  end
226
228
 
@@ -229,7 +231,7 @@ module Synvert::Core
229
231
  #
230
232
  # @param code [String] code need to be inserted.
231
233
  # @param options [Hash] action options.
232
- def insert(code, options={})
234
+ def insert(code, options = {})
233
235
  @actions << Rewriter::InsertAction.new(self, code, options)
234
236
  end
235
237
 
@@ -238,7 +240,7 @@ module Synvert::Core
238
240
  #
239
241
  # @param code [String] code need to be inserted.
240
242
  # @param options [Hash] action options.
241
- def insert_after(node, options={})
243
+ def insert_after(node, options = {})
242
244
  @actions << Rewriter::InsertAfterAction.new(self, node, options)
243
245
  end
244
246
 
@@ -247,7 +249,7 @@ module Synvert::Core
247
249
  #
248
250
  # @param code [String] code need to be replaced with.
249
251
  # @param options [Hash] action options.
250
- def replace_with(code, options={})
252
+ def replace_with(code, options = {})
251
253
  @actions << Rewriter::ReplaceWithAction.new(self, code, options)
252
254
  end
253
255
 
@@ -269,7 +271,7 @@ module Synvert::Core
269
271
  @rewriter.add_warning Rewriter::Warning.new(self, message)
270
272
  end
271
273
 
272
- private
274
+ private
273
275
 
274
276
  # It changes source code from bottom to top, and it can change source code twice at the same time,
275
277
  # So if there is an overlap between two actions, it removes the conflict actions and operate them in the next loop.
@@ -301,7 +303,8 @@ module Synvert::Core
301
303
  source_arr = source.split("\n")
302
304
  if source_arr[line - 1] && source_arr[line - 1].strip.empty?
303
305
  source_arr.delete_at(line - 1)
304
- 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?
305
308
  source_arr.delete_at(line - 1)
306
309
  end
307
310
  source_arr.join("\n") + (newline_at_end_of_line ? "\n" : '')