synvert-core 0.15.1 → 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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -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 +2 -1
  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 +20 -14
  13. data/lib/synvert/core/rewriter/action.rb +5 -7
  14. data/lib/synvert/core/rewriter/action/append_action.rb +8 -6
  15. data/lib/synvert/core/rewriter/action/insert_action.rb +18 -19
  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 +10 -10
  25. data/lib/synvert/core/rewriter/helper.rb +4 -6
  26. data/lib/synvert/core/rewriter/instance.rb +36 -22
  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 -1
  34. data/spec/support/parser_helper.rb +2 -0
  35. data/spec/synvert/core/configuration_spec.rb +3 -1
  36. data/spec/synvert/core/engine/erb_spec.rb +32 -30
  37. data/spec/synvert/core/node_ext_spec.rb +57 -54
  38. data/spec/synvert/core/rewriter/action/append_action_spec.rb +2 -0
  39. data/spec/synvert/core/rewriter/action/insert_action_spec.rb +10 -8
  40. data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +5 -3
  41. data/spec/synvert/core/rewriter/action/remove_action_spec.rb +3 -1
  42. data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +2 -0
  43. data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +17 -11
  44. data/spec/synvert/core/rewriter/action_spec.rb +2 -0
  45. data/spec/synvert/core/rewriter/condition/if_exist_condition_spec.rb +19 -9
  46. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +23 -12
  47. data/spec/synvert/core/rewriter/condition/unless_exist_condition_spec.rb +19 -9
  48. data/spec/synvert/core/rewriter/condition_spec.rb +2 -0
  49. data/spec/synvert/core/rewriter/gem_spec_spec.rb +13 -10
  50. data/spec/synvert/core/rewriter/helper_spec.rb +36 -31
  51. data/spec/synvert/core/rewriter/instance_spec.rb +118 -66
  52. data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +10 -6
  53. data/spec/synvert/core/rewriter/scope/within_scope.rb +18 -9
  54. data/spec/synvert/core/rewriter/scope_spec.rb +2 -0
  55. data/spec/synvert/core/rewriter/warning_spec.rb +2 -0
  56. data/spec/synvert/core/rewriter_spec.rb +106 -73
  57. data/synvert-core.gemspec +2 -2
  58. metadata +12 -12
@@ -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
  #
@@ -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,16 +1,17 @@
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
+ DEFAULT_INDENT = 2
7
8
 
8
9
  # Initialize an action.
9
10
  #
10
11
  # @param instance [Synvert::Core::Rewriter::Instance]
11
12
  # @param code [String] new code to add, replace or remove.
12
13
  # @param options [Hash] action options, it includes :autoindent.
13
- def initialize(instance, code, options={})
14
+ def initialize(instance, code, options = {})
14
15
  @instance = instance
15
16
  @code = code
16
17
  @options = DEFAULT_OPTIONS.merge(options)
@@ -29,9 +30,7 @@ module Synvert::Core
29
30
  # @return [String] rewritten code.
30
31
  def rewritten_code
31
32
  if rewritten_source.split("\n").length > 1
32
- "\n\n" + rewritten_source.split("\n").map { |line|
33
- indent(@node) + line
34
- }.join("\n")
33
+ "\n\n" + rewritten_source.split("\n").map { |line| indent(@node) + line }.join("\n")
35
34
  else
36
35
  "\n" + indent(@node) + rewritten_source
37
36
  end
@@ -45,4 +44,3 @@ module Synvert::Core
45
44
  end
46
45
  end
47
46
  end
48
-
@@ -1,8 +1,10 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # AppendWithAction to append code to the bottom of node body.
4
+ # AppendAction to append code to the bottom of node body.
5
5
  class Rewriter::AppendAction < Rewriter::Action
6
+ END_LENGTH = "\nend".length
7
+
6
8
  # Begin position to append code.
7
9
  #
8
10
  # @return [Integer] begin position.
@@ -10,7 +12,7 @@ module Synvert::Core
10
12
  if :begin == @node.type
11
13
  @node.loc.expression.end_pos
12
14
  else
13
- @node.loc.expression.end_pos - @node.indent - 4
15
+ @node.loc.expression.end_pos - @node.indent - END_LENGTH
14
16
  end
15
17
  end
16
18
 
@@ -21,15 +23,15 @@ module Synvert::Core
21
23
  begin_pos
22
24
  end
23
25
 
24
- private
26
+ private
25
27
 
26
28
  # Indent of the node.
27
29
  #
28
30
  # @param node [Parser::AST::Node]
29
31
  # @return [String] n times whitesphace
30
32
  def indent(node)
31
- if [:block, :class].include? node.type
32
- ' ' * (node.indent + 2)
33
+ if %i[block class].include? node.type
34
+ ' ' * (node.indent + DEFAULT_INDENT)
33
35
  else
34
36
  ' ' * node.indent
35
37
  end
@@ -1,13 +1,26 @@
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
7
+
6
8
  # Begin position to insert code.
7
9
  #
8
10
  # @return [Integer] begin position.
9
11
  def begin_pos
10
- insert_position(@node)
12
+ case @node.type
13
+ when :block
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
19
+ when :class
20
+ @node.children[1] ? @node.children[1].loc.expression.end_pos : @node.children[0].loc.expression.end_pos
21
+ else
22
+ @node.children.last.loc.expression.end_pos
23
+ end
11
24
  end
12
25
 
13
26
  # End position, always same to begin position.
@@ -17,29 +30,15 @@ module Synvert::Core
17
30
  begin_pos
18
31
  end
19
32
 
20
- private
21
-
22
- # Insert position.
23
- #
24
- # @return [Integer] insert position.
25
- def insert_position(node)
26
- case node.type
27
- when :block
28
- node.children[1].children.empty? ? node.children[0].loc.expression.end_pos + 3 : node.children[1].loc.expression.end_pos
29
- when :class
30
- node.children[1] ? node.children[1].loc.expression.end_pos : node.children[0].loc.expression.end_pos
31
- else
32
- node.children.last.loc.expression.end_pos
33
- end
34
- end
33
+ private
35
34
 
36
35
  # Indent of the node.
37
36
  #
38
37
  # @param node [Parser::AST::Node]
39
38
  # @return [String] n times whitesphace
40
39
  def indent(node)
41
- if [:block, :class].include? node.type
42
- ' ' * (node.indent + 2)
40
+ if %i[block class].include? node.type
41
+ ' ' * (node.indent + DEFAULT_INDENT)
43
42
  else
44
43
  ' ' * node.indent
45
44
  end
@@ -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
  #
@@ -27,15 +27,15 @@ 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
- 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
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