synvert-core 0.24.0 → 0.27.0

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