synvert-core 0.23.0 → 0.26.1

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: 03fc53b8833a45acfc449689b313108daf0e98c93dfd8e197fc9b3940e68816b
4
- data.tar.gz: e9563c1fe7e358c748be50638a37ecfb7d155c8c4f4ed6dbcde1cac29ed74b99
3
+ metadata.gz: e3f85c5eb0a82ffb3447ad72ac9f901883a074b1f16c244176008a333b3e90cc
4
+ data.tar.gz: c13b895edc3ef7f9d126795933e2bf01267b0b912e2904a4481baff175eebca4
5
5
  SHA512:
6
- metadata.gz: d053963cb0dfb4e92e515d965a7651d35d60d2d929e2dce1f46c8a32fc4a6101414cd8b47f185c0b43a10470a340614c2d6048184fb869c5e9e6b60a2f16ff27
7
- data.tar.gz: 24307e135f10127b48403cfae69c89c4d71d112a513a83570ae7fd16c625882437e2efadefbd4b683fae6d9ce990ae0c1b104e7da3dbfe5f52a893e6f025df63
6
+ metadata.gz: 16ceb23eaf30909e4950cefbaae20b650f90320a496fee4a095a054dc7996fe91bfbcb79fc6252caa38f09b5998c687d4171bee050fc605cf2c8ee8ddac93c61
7
+ data.tar.gz: fc0202a47909b7bcffdd0e235c198419afcf2653f89bcd9abce626b412ab3c4a92a0bfbc71be8971873d15aeac85e4e2d0f80575ee44f75374d7c755af281c12
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.26.1 (2021-03-31)
4
+
5
+ * Support `:class` in `child_node_range`
6
+
7
+ ## 0.26.0 (2021-03-30)
8
+
9
+ * attr_reader ruby_version and gem_spec
10
+ * Add `replace` action
11
+
12
+ ## 0.25.0 (2021-03-23)
13
+
14
+ * Use `Gem::Dependency#match?` to check gem version
15
+
16
+ ## 0.24.0 (2021-03-17)
17
+
18
+ * Rename helper method `has_key?` to `key?`
19
+
3
20
  ## 0.23.0 (2021-03-14)
4
21
 
5
22
  * Accept a node as goto_node argument
@@ -187,11 +187,11 @@ module Parser::AST
187
187
  # @param [Object] key value.
188
188
  # @return [Boolean] true if specified key exists.
189
189
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
190
- def has_key?(key)
190
+ def key?(key)
191
191
  if :hash == type
192
192
  children.any? { |pair_node| pair_node.key.to_value == key }
193
193
  else
194
- raise Synvert::Core::MethodNotSupported, "has_key? is not handled for #{debug_info}"
194
+ raise Synvert::Core::MethodNotSupported, "key? is not handled for #{debug_info}"
195
195
  end
196
196
  end
197
197
 
@@ -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_key? 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,33 @@ 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 :message
338
+ loc.selector
339
+ when :arguments
340
+ Parser::Source::Range.new('(string)', arguments.first.loc.expression.begin_pos, arguments.last.loc.expression.end_pos) unless arguments.empty?
341
+ end
342
+ else
343
+ raise Synvert::Core::MethodNotSupported, "child_node_range is not handled for #{evaluated.inspect}, child_name: #{child_name}"
344
+ end
345
+ end
346
+
320
347
  # Recursively iterate all child nodes of current node.
321
348
  #
322
349
  # @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,6 +21,7 @@ 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'
26
27
 
@@ -147,7 +148,11 @@ module Synvert::Core
147
148
  # @return [Array<Synvert::Core::Rewriter::Warning>] warning messages.
148
149
  # @!attribute [r] affected_files
149
150
  # @return [Set] affected fileds
150
- attr_reader :group, :name, :sub_snippets, :helpers, :warnings, :affected_files
151
+ # @!attribute [r] ruby_version
152
+ # @return [Rewriter::RubyVersion] the ruby version
153
+ # @!attribute [r] gem_spec
154
+ # @return [Rewriter::GemSpec] the gem spec
155
+ attr_reader :group, :name, :sub_snippets, :helpers, :warnings, :affected_files, :ruby_version, :gem_spec
151
156
 
152
157
  # Initialize a rewriter.
153
158
  # When a rewriter is initialized, it is also registered.
@@ -225,10 +230,9 @@ module Synvert::Core
225
230
  # Parse if_gem dsl, it compares version of the specified gem.
226
231
  #
227
232
  # @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)
233
+ # @param version [String] equal, less than or greater than specified version, e.g. '>= 2.0.0',
234
+ def if_gem(name, version)
235
+ @gem_spec = Rewriter::GemSpec.new(name, version)
232
236
  end
233
237
 
234
238
  # Parse within_files dsl, it finds specified files.
@@ -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,6 +251,15 @@ 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
@@ -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.23.0'
5
+ VERSION = '0.26.1'
6
6
  end
7
7
  end
@@ -186,15 +186,15 @@ describe Parser::AST::Node do
186
186
  end
187
187
  end
188
188
 
189
- describe '#has_key?' do
189
+ describe '#key?' do
190
190
  it 'gets true if key exists' do
191
191
  node = parse('{:foo => :bar}')
192
- expect(node.has_key?(:foo)).to be_truthy
192
+ expect(node.key?(:foo)).to be_truthy
193
193
  end
194
194
 
195
195
  it 'gets false if key does not exist' do
196
196
  node = parse('{:foo => :bar}')
197
- expect(node.has_key?('foo')).to be_falsey
197
+ expect(node.key?('foo')).to be_falsey
198
198
  end
199
199
  end
200
200
 
@@ -394,6 +394,62 @@ 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 message' do
410
+ node = parse('foo.bar(test)')
411
+ range = node.child_node_range(:message)
412
+ expect(range.to_range).to eq(4...7)
413
+
414
+ node = parse('foobar(test)')
415
+ range = node.child_node_range(:message)
416
+ expect(range.to_range).to eq(0...6)
417
+ end
418
+
419
+ it 'checks arguments' do
420
+ node = parse('foo.bar(test)')
421
+ range = node.child_node_range(:arguments)
422
+ expect(range.to_range).to eq(8...12)
423
+
424
+ node = parse('foobar(test)')
425
+ range = node.child_node_range(:arguments)
426
+ expect(range.to_range).to eq(7...11)
427
+
428
+ node = parse('foo.bar')
429
+ range = node.child_node_range(:arguments)
430
+ expect(range).to be_nil
431
+ end
432
+ end
433
+
434
+ context 'class node' do
435
+ it 'checks name' do
436
+ node = parse('class Post < ActiveRecord::Base; end')
437
+ range = node.child_node_range(:name)
438
+ expect(range.to_range).to eq(6...10)
439
+ end
440
+
441
+ it 'checks parent_class' do
442
+ node = parse('class Post < ActiveRecord::Base; end')
443
+ range = node.child_node_range(:parent_class)
444
+ expect(range.to_range).to eq(13...31)
445
+
446
+ node = parse('class Post; end')
447
+ range = node.child_node_range(:parent_class)
448
+ expect(range).to be_nil
449
+ end
450
+ end
451
+ end
452
+
397
453
  describe '#rewritten_source' do
398
454
  let(:instance) {
399
455
  rewriter = Synvert::Rewriter.new('foo', 'bar')
@@ -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.23.0
4
+ version: 0.26.1
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-14 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
@@ -150,6 +150,7 @@ files:
150
150
  - lib/synvert/core/rewriter/action/insert_action.rb
151
151
  - lib/synvert/core/rewriter/action/insert_after_action.rb
152
152
  - lib/synvert/core/rewriter/action/remove_action.rb
153
+ - lib/synvert/core/rewriter/action/replace_action.rb
153
154
  - lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb
154
155
  - lib/synvert/core/rewriter/action/replace_with_action.rb
155
156
  - lib/synvert/core/rewriter/condition.rb
@@ -173,6 +174,7 @@ files:
173
174
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
174
175
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
175
176
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
177
+ - spec/synvert/core/rewriter/action/replace_action_spec.rb
176
178
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
177
179
  - spec/synvert/core/rewriter/action/replace_with_action_spec.rb
178
180
  - spec/synvert/core/rewriter/action_spec.rb
@@ -222,6 +224,7 @@ test_files:
222
224
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
223
225
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
224
226
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
227
+ - spec/synvert/core/rewriter/action/replace_action_spec.rb
225
228
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
226
229
  - spec/synvert/core/rewriter/action/replace_with_action_spec.rb
227
230
  - spec/synvert/core/rewriter/action_spec.rb