synvert-core 0.24.0 → 0.27.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b07d8def5ce35c251b7d1f7b04388654aadce0b6498c969b81457c9867d37dfb
4
- data.tar.gz: d43a62b62ba6a4fa6bd51a97f7dfd6a4a805651d8ae6a595eac4724bba67f792
3
+ metadata.gz: 49f00515f034212fb244c270b4d9815e51e5a4d2eb1e91c1cd8c3ddc402fca28
4
+ data.tar.gz: 8de939c1e2834259e1aa8af2b17e540221a5e7d0d3f936ad526081db408e994f
5
5
  SHA512:
6
- metadata.gz: 98a9a81c409ca86ad13a58d00ef380ced1bc0a0fd3288c970e13f9a04ed4f13180b2b3e20ed87fc3521ee61531709507e7ce412ab7802c5d1091ef39fc63dca3
7
- data.tar.gz: 05ecb25382bca6d4cc0e677b1ea3ccf19a0113bf2376fc1888135c1f069c4a4d7b2196f648b0433133761646d6dae8de4a43f43e28b506062ad97c236c9c38f3
6
+ metadata.gz: 12236d2c862b82798e3865755394362e50773ff27505b1ddf08e7308dd51ca0a791b604e8e3cafd768e8d3b957c76bb18ff5d5bd8daded14eef0e2a788c51c36
7
+ data.tar.gz: 42b67fd980a096a5d8bffe78ba023c47b18bca34ac3957a631da16bd722b979e8cb9523eaf97e8ca42b870091e4ec81922b866ff8359325f0144766cb9ceb3db
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.27.0 (2021-03-31)
4
+
5
+ * Support `:class` in `child_node_range`
6
+ * Add `delete` action
7
+
8
+ ## 0.26.0 (2021-03-30)
9
+
10
+ * attr_reader ruby_version and gem_spec
11
+ * Add `replace` action
12
+
13
+ ## 0.25.0 (2021-03-23)
14
+
15
+ * Use `Gem::Dependency#match?` to check gem version
16
+
3
17
  ## 0.24.0 (2021-03-17)
4
18
 
5
19
  * Rename helper method `has_key?` to `key?`
@@ -205,7 +205,7 @@ module Parser::AST
205
205
  value_node = children.find { |pair_node| pair_node.key.to_value == key }
206
206
  value_node ? value_node.value : nil
207
207
  else
208
- raise Synvert::Core::MethodNotSupported, "has_value is not handled for #{debug_info}"
208
+ raise Synvert::Core::MethodNotSupported, "hash_value is not handled for #{debug_info}"
209
209
  end
210
210
  end
211
211
 
@@ -317,6 +317,35 @@ module Parser::AST
317
317
  loc.expression.line
318
318
  end
319
319
 
320
+ # Get the source range of child node.
321
+ #
322
+ # @param [String] name of child node.
323
+ # @return [Parser::Source::Range] source range of child node.
324
+ def child_node_range(child_name)
325
+ case type
326
+ when :class
327
+ case child_name
328
+ when :name
329
+ loc.name
330
+ when :parent_class
331
+ parent_class&.loc&.expression
332
+ end
333
+ when :send
334
+ case child_name
335
+ when :receiver
336
+ receiver&.loc&.expression
337
+ when :dot
338
+ loc.dot
339
+ when :message
340
+ loc.selector
341
+ when :arguments
342
+ Parser::Source::Range.new('(string)', arguments.first.loc.expression.begin_pos, arguments.last.loc.expression.end_pos) unless arguments.empty?
343
+ end
344
+ else
345
+ raise Synvert::Core::MethodNotSupported, "child_node_range is not handled for #{evaluated.inspect}, child_name: #{child_name}"
346
+ end
347
+ end
348
+
320
349
  # Recursively iterate all child nodes of current node.
321
350
  #
322
351
  # @yield [child] Gives a child node.
@@ -7,7 +7,7 @@ module Synvert::Core
7
7
  # which define the behavior what files and what codes to detect and rewrite to what code.
8
8
  #
9
9
  # Synvert::Rewriter.new 'factory_girl_short_syntax', 'use FactoryGirl short syntax' do
10
- # if_gem 'factory_girl', {gte: '2.0.0'}
10
+ # if_gem 'factory_girl', '>= 2.0.0'
11
11
  #
12
12
  # within_files 'spec/**/*.rb' do
13
13
  # with_node type: 'send', receiver: 'FactoryGirl', message: 'create' do
@@ -21,8 +21,10 @@ module Synvert::Core
21
21
  autoload :InsertAction, 'synvert/core/rewriter/action/insert_action'
22
22
  autoload :InsertAfterAction, 'synvert/core/rewriter/action/insert_after_action'
23
23
  autoload :ReplaceWithAction, 'synvert/core/rewriter/action/replace_with_action'
24
+ autoload :ReplaceAction, 'synvert/core/rewriter/action/replace_action'
24
25
  autoload :ReplaceErbStmtWithExprAction, 'synvert/core/rewriter/action/replace_erb_stmt_with_expr_action'
25
26
  autoload :RemoveAction, 'synvert/core/rewriter/action/remove_action'
27
+ autoload :DeleteAction, 'synvert/core/rewriter/action/delete_action'
26
28
 
27
29
  autoload :Warning, 'synvert/core/rewriter/warning'
28
30
 
@@ -147,7 +149,11 @@ module Synvert::Core
147
149
  # @return [Array<Synvert::Core::Rewriter::Warning>] warning messages.
148
150
  # @!attribute [r] affected_files
149
151
  # @return [Set] affected fileds
150
- attr_reader :group, :name, :sub_snippets, :helpers, :warnings, :affected_files
152
+ # @!attribute [r] ruby_version
153
+ # @return [Rewriter::RubyVersion] the ruby version
154
+ # @!attribute [r] gem_spec
155
+ # @return [Rewriter::GemSpec] the gem spec
156
+ attr_reader :group, :name, :sub_snippets, :helpers, :warnings, :affected_files, :ruby_version, :gem_spec
151
157
 
152
158
  # Initialize a rewriter.
153
159
  # When a rewriter is initialized, it is also registered.
@@ -225,10 +231,9 @@ module Synvert::Core
225
231
  # Parse if_gem dsl, it compares version of the specified gem.
226
232
  #
227
233
  # @param name [String] gem name.
228
- # @param comparator [Hash] equal, less than or greater than specified version, e.g. {gte: '2.0.0'},
229
- # key can be eq, lt, gt, lte, gte or ne.
230
- def if_gem(name, comparator)
231
- @gem_spec = Rewriter::GemSpec.new(name, comparator)
234
+ # @param version [String] equal, less than or greater than specified version, e.g. '>= 2.0.0',
235
+ def if_gem(name, version)
236
+ @gem_spec = Rewriter::GemSpec.new(name, version)
232
237
  end
233
238
 
234
239
  # Parse within_files dsl, it finds specified files.
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core
4
+ # RemoveAction to delete code.
5
+ class Rewriter::DeleteAction < Rewriter::Action
6
+ def initialize(instance, *selectors)
7
+ super(instance, nil)
8
+ @selectors = selectors
9
+ end
10
+
11
+ # Begin position of code to replace.
12
+ #
13
+ # @return [Integer] begin position.
14
+ def begin_pos
15
+ @selectors.map { |selector| @node.child_node_range(selector).begin_pos }.min
16
+ end
17
+
18
+ # End position of code to replace.
19
+ #
20
+ # @return [Integer] end position.
21
+ def end_pos
22
+ @selectors.map { |selector| @node.child_node_range(selector).end_pos }.max
23
+ end
24
+
25
+ # The rewritten code, always empty string.
26
+ def rewritten_code
27
+ ''
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core
4
+ # ReplaceAction to replace child node with code.
5
+ class Rewriter::ReplaceAction < Rewriter::Action
6
+ def initialize(instance, selector, with:)
7
+ @instance = instance
8
+ @selector = selector
9
+ @code = with
10
+ @node = @instance.current_node
11
+ end
12
+
13
+ # Begin position of code to replace.
14
+ #
15
+ # @return [Integer] begin position.
16
+ def begin_pos
17
+ @node.child_node_range(@selector).begin_pos
18
+ end
19
+
20
+ # End position of code to replace.
21
+ #
22
+ # @return [Integer] end position.
23
+ def end_pos
24
+ @node.child_node_range(@selector).end_pos
25
+ end
26
+
27
+ # The rewritten source code.
28
+ #
29
+ # @return [String] rewritten code.
30
+ def rewritten_code
31
+ rewritten_source
32
+ end
33
+ end
34
+ end
@@ -3,22 +3,15 @@
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: '!=' }.freeze
6
+ attr_reader :name, :version
7
7
 
8
8
  # Initialize a gem_spec.
9
9
  #
10
10
  # @param name [String] gem name
11
- # @param comparator [Hash] comparator to gem version, e.g. {eq: '2.0.0'},
12
- # comparator key can be eq, lt, gt, lte, gte or ne.
13
- def initialize(name, comparator)
11
+ # @param version [String] gem version, e.g. '~> 2.0.0',
12
+ def initialize(name, version)
14
13
  @name = name
15
- if comparator.is_a?(Hash)
16
- @operator = comparator.keys.first
17
- @version = Gem::Version.new comparator.values.first
18
- else
19
- @operator = :eq
20
- @version = Gem::Version.new comparator
21
- end
14
+ @version = version
22
15
  end
23
16
 
24
17
  # Check if the specified gem version in Gemfile.lock matches gem_spec comparator.
@@ -33,11 +26,7 @@ module Synvert::Core
33
26
 
34
27
  ENV['BUNDLE_GEMFILE'] = Configuration.path # make sure bundler reads Gemfile.lock in the correct path
35
28
  parser = Bundler::LockfileParser.new(File.read(gemfile_lock_path))
36
- if spec = parser.specs.find { |spec| spec.name == @name }
37
- Gem::Version.new(spec.version).send(OPERATORS[@operator], @version)
38
- else
39
- false
40
- end
29
+ parser.specs.any? { |spec| Gem::Dependency.new(@name, @version).match?(spec) }
41
30
  end
42
31
  end
43
32
  end
@@ -251,17 +251,31 @@ module Synvert::Core
251
251
  @actions << Rewriter::ReplaceWithAction.new(self, code, options)
252
252
  end
253
253
 
254
+ # Parse replace with dsl, it creates a [Synvert::Core::Rewriter::ReplaceAction] to
255
+ # replace child node with code.
256
+ #
257
+ # @param selector [Symbol] selector name of child name.
258
+ # @param with [String] code need to be replaced with.
259
+ def replace(selector, with:)
260
+ @actions << Rewriter::ReplaceAction.new(self, selector, with: with)
261
+ end
262
+
254
263
  # Parse replace_erb_stmt_with_expr dsl, it creates a [Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction] to
255
264
  # replace erb stmt code to expr code.
256
265
  def replace_erb_stmt_with_expr
257
266
  @actions << Rewriter::ReplaceErbStmtWithExprAction.new(self)
258
267
  end
259
268
 
260
- # Parse remove dsl, it creates a [Synvert::Core::Rewriter::RemoveAction] to current node.
269
+ # Parse remove dsl, it creates a [Synvert::Core::Rewriter::RemoveAction] to remove current node.
261
270
  def remove
262
271
  @actions << Rewriter::RemoveAction.new(self)
263
272
  end
264
273
 
274
+ # Parse delete dsl, it creates a [Synvert::Core::Rewriter::DeleteAction] to delete child nodes.
275
+ def delete
276
+ @actions << Rewriter::DeleteAction.new(self, *selectors)
277
+ end
278
+
265
279
  # Parse warn dsl, it creates a [Synvert::Core::Rewriter::Warning] to save warning message.
266
280
  #
267
281
  # @param message [String] warning message.
@@ -3,6 +3,8 @@
3
3
  module Synvert::Core
4
4
  # GemSpec checks and compares gem version.
5
5
  class Rewriter::RubyVersion
6
+ attr_reader :version
7
+
6
8
  # Initialize a ruby_version.
7
9
  #
8
10
  # @param version [String] ruby version
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.24.0'
5
+ VERSION = '0.27.0'
6
6
  end
7
7
  end
@@ -394,6 +394,72 @@ describe Parser::AST::Node do
394
394
  end
395
395
  end
396
396
 
397
+ describe '#child_node_range' do
398
+ context 'send node' do
399
+ it 'checks receiver' do
400
+ node = parse('foo.bar(test)')
401
+ range = node.child_node_range(:receiver)
402
+ expect(range.to_range).to eq(0...3)
403
+
404
+ node = parse('foobar(test)')
405
+ range = node.child_node_range(:receiver)
406
+ expect(range).to be_nil
407
+ end
408
+
409
+ it 'checks dot' do
410
+ node = parse('foo.bar(test)')
411
+ range = node.child_node_range(:dot)
412
+ expect(range.to_range).to eq(3...4)
413
+
414
+ node = parse('foobar(test)')
415
+ range = node.child_node_range(:dot)
416
+ expect(range).to be_nil
417
+ end
418
+
419
+ it 'checks message' do
420
+ node = parse('foo.bar(test)')
421
+ range = node.child_node_range(:message)
422
+ expect(range.to_range).to eq(4...7)
423
+
424
+ node = parse('foobar(test)')
425
+ range = node.child_node_range(:message)
426
+ expect(range.to_range).to eq(0...6)
427
+ end
428
+
429
+ it 'checks arguments' do
430
+ node = parse('foo.bar(test)')
431
+ range = node.child_node_range(:arguments)
432
+ expect(range.to_range).to eq(8...12)
433
+
434
+ node = parse('foobar(test)')
435
+ range = node.child_node_range(:arguments)
436
+ expect(range.to_range).to eq(7...11)
437
+
438
+ node = parse('foo.bar')
439
+ range = node.child_node_range(:arguments)
440
+ expect(range).to be_nil
441
+ end
442
+ end
443
+
444
+ context 'class node' do
445
+ it 'checks name' do
446
+ node = parse('class Post < ActiveRecord::Base; end')
447
+ range = node.child_node_range(:name)
448
+ expect(range.to_range).to eq(6...10)
449
+ end
450
+
451
+ it 'checks parent_class' do
452
+ node = parse('class Post < ActiveRecord::Base; end')
453
+ range = node.child_node_range(:parent_class)
454
+ expect(range.to_range).to eq(13...31)
455
+
456
+ node = parse('class Post; end')
457
+ range = node.child_node_range(:parent_class)
458
+ expect(range).to be_nil
459
+ end
460
+ end
461
+ end
462
+
397
463
  describe '#rewritten_source' do
398
464
  let(:instance) {
399
465
  rewriter = Synvert::Rewriter.new('foo', 'bar')
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Synvert::Core
6
+ describe Rewriter::DeleteAction do
7
+ subject {
8
+ source = "arr.map {}.flatten"
9
+ node = Parser::CurrentRuby.parse(source)
10
+ instance = double(current_node: node)
11
+ Rewriter::DeleteAction.new(instance, :dot, :message)
12
+ }
13
+
14
+ it 'gets begin_pos' do
15
+ expect(subject.begin_pos).to eq "arr.map {}".length
16
+ end
17
+
18
+ it 'gets end_pos' do
19
+ expect(subject.end_pos).to eq "arr.map {}.flatten".length
20
+ end
21
+
22
+ it 'gets rewritten_code' do
23
+ expect(subject.rewritten_code).to eq ''
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Synvert::Core
6
+ describe Rewriter::ReplaceAction do
7
+ context 'replace with single line' do
8
+ subject {
9
+ source = "'slug from title'.gsub(' ', '_')"
10
+ node = Parser::CurrentRuby.parse(source)
11
+ instance = double(current_node: node)
12
+ Rewriter::ReplaceAction.new(instance, :message, with: 'tr')
13
+ }
14
+
15
+ it 'gets begin_pos' do
16
+ expect(subject.begin_pos).to eq "'slug from title'.".length
17
+ end
18
+
19
+ it 'gets end_pos' do
20
+ expect(subject.end_pos).to eq "'slug from title'.gsub".length
21
+ end
22
+
23
+ it 'gets rewritten_code' do
24
+ expect(subject.rewritten_code).to eq 'tr'
25
+ end
26
+ end
27
+ end
28
+ end
@@ -21,7 +21,7 @@ GEM
21
21
  it 'returns true if version in Gemfile.lock is greater than definition' do
22
22
  expect(File).to receive(:exist?).with('./Gemfile.lock').and_return(true)
23
23
  expect(File).to receive(:read).with('./Gemfile.lock').and_return(gemfile_lock_content)
24
- gem_spec = Rewriter::GemSpec.new('ast', { gte: '1.0.0' })
24
+ gem_spec = Rewriter::GemSpec.new('ast', '~> 1.1')
25
25
  expect(gem_spec).to be_match
26
26
  end
27
27
 
@@ -35,7 +35,7 @@ GEM
35
35
  it 'returns false if version in Gemfile.lock is less than definition' do
36
36
  expect(File).to receive(:exist?).with('./Gemfile.lock').and_return(true)
37
37
  expect(File).to receive(:read).with('./Gemfile.lock').and_return(gemfile_lock_content)
38
- gem_spec = Rewriter::GemSpec.new('ast', { gt: '1.2.0' })
38
+ gem_spec = Rewriter::GemSpec.new('ast', '> 1.2.0')
39
39
  expect(gem_spec).not_to be_match
40
40
  end
41
41
 
@@ -117,6 +117,11 @@ module Synvert::Core
117
117
  instance.replace_with 'create {{arguments}}'
118
118
  end
119
119
 
120
+ it 'parses replace with' do
121
+ expect(Rewriter::ReplaceAction).to receive(:new).with(instance, :message, with: 'test')
122
+ instance.replace :message, with: 'test'
123
+ end
124
+
120
125
  it 'parses remove' do
121
126
  expect(Rewriter::RemoveAction).to receive(:new).with(instance)
122
127
  instance.remove
@@ -29,10 +29,10 @@ module Synvert::Core
29
29
  end
30
30
 
31
31
  it 'parses if_gem' do
32
- expect(Rewriter::GemSpec).to receive(:new).with('synvert', { gte: '1.0.0' })
32
+ expect(Rewriter::GemSpec).to receive(:new).with('synvert', '>= 1.0.0')
33
33
  rewriter =
34
34
  Rewriter.new 'group', 'name' do
35
- if_gem 'synvert', { gte: '1.0.0' }
35
+ if_gem 'synvert', '>= 1.0.0'
36
36
  end
37
37
  rewriter.process
38
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synvert-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.0
4
+ version: 0.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-17 00:00:00.000000000 Z
11
+ date: 2021-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -147,9 +147,11 @@ files:
147
147
  - lib/synvert/core/rewriter.rb
148
148
  - lib/synvert/core/rewriter/action.rb
149
149
  - lib/synvert/core/rewriter/action/append_action.rb
150
+ - lib/synvert/core/rewriter/action/delete_action.rb
150
151
  - lib/synvert/core/rewriter/action/insert_action.rb
151
152
  - lib/synvert/core/rewriter/action/insert_after_action.rb
152
153
  - lib/synvert/core/rewriter/action/remove_action.rb
154
+ - lib/synvert/core/rewriter/action/replace_action.rb
153
155
  - lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb
154
156
  - lib/synvert/core/rewriter/action/replace_with_action.rb
155
157
  - lib/synvert/core/rewriter/condition.rb
@@ -170,9 +172,11 @@ files:
170
172
  - spec/synvert/core/engine/erb_spec.rb
171
173
  - spec/synvert/core/node_ext_spec.rb
172
174
  - spec/synvert/core/rewriter/action/append_action_spec.rb
175
+ - spec/synvert/core/rewriter/action/delete_action_spec.rb
173
176
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
174
177
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
175
178
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
179
+ - spec/synvert/core/rewriter/action/replace_action_spec.rb
176
180
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
177
181
  - spec/synvert/core/rewriter/action/replace_with_action_spec.rb
178
182
  - spec/synvert/core/rewriter/action_spec.rb
@@ -219,9 +223,11 @@ test_files:
219
223
  - spec/synvert/core/engine/erb_spec.rb
220
224
  - spec/synvert/core/node_ext_spec.rb
221
225
  - spec/synvert/core/rewriter/action/append_action_spec.rb
226
+ - spec/synvert/core/rewriter/action/delete_action_spec.rb
222
227
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
223
228
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
224
229
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
230
+ - spec/synvert/core/rewriter/action/replace_action_spec.rb
225
231
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
226
232
  - spec/synvert/core/rewriter/action/replace_with_action_spec.rb
227
233
  - spec/synvert/core/rewriter/action_spec.rb