synvert-core 0.17.0 → 0.18.0

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