synvert-core 0.27.2 → 0.29.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: afa25ca6412906c13399aa27967676033670bcbab36910a7bd528e3a9948e61d
4
- data.tar.gz: f5844fee19d2aec45fd24b50af95decb53b7b33c90e2c83fad4fb62d565d0782
3
+ metadata.gz: 31ee6b89cd48a4accb2dc71fdec2e487c534e8d6eb4a9bd6050817cd88f7ba3c
4
+ data.tar.gz: cd4c005e0f7a21e52e984e5279a45d4325d341b92d67feedbbc455ddc062e0fc
5
5
  SHA512:
6
- metadata.gz: 2d188889dec4144d5508fc2ff3f9c6356703354cc1d37464a4d59fa406c56095fd1be796c5ffa474263bcb9a232f2ebbf48796de778fe80bbfe0a18137b7d048
7
- data.tar.gz: 85a83b35f0b9c60682d75647a63eff485eff55cf41e46e12b7849b00d098c1268e615eee9d363e3ce068c8c4239e05bc499a86cb73d4ba70d1c986366e2f96a0
6
+ metadata.gz: 4d1e8642e682a155eedb03c6cdbabca55f53f22c258d4774da7200877159ec18c0a7d568823c5c379fd93810d0baf945a2bc139f8444423855c6279241acb0bc
7
+ data.tar.gz: 73a369f23d1add90b21ce578faf37a3136a6ffcb384f47fa5b3881fd4241af4b087b19fb0d854143ed1e3d9b76f350fc41b2415cddc29671cde3afe0e46d4709
data/CHANGELOG.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 0.27.2 (2021-03-31)
3
+ ## 0.29.0 (2021-04-25)
4
4
 
5
- * Fix selector with operator in `child_node_range`
5
+ * Make `child_name_range` support [:block, :pipe]
6
+ * Get key value for hash node
6
7
 
7
- ## 0.27.1 (2021-03-31)
8
+ ## 0.28.0 (2021-04-07)
8
9
 
10
+ * Make `child_name_range` support all dsl nodes
11
+ * Make `replace` action support multi child names
9
12
  * Fix `delete` action arguments
10
13
 
11
14
  ## 0.27.0 (2021-03-31)
@@ -101,9 +101,9 @@ module Parser::AST
101
101
  def arguments
102
102
  case type
103
103
  when :def, :block
104
- ArgumentsNode.new children[1]
104
+ ArgumentsNode.new(children[1])
105
105
  when :defs
106
- ArgumentsNode.new children[2]
106
+ ArgumentsNode.new(children[2])
107
107
  when :send
108
108
  children[2..-1]
109
109
  when :defined?
@@ -203,7 +203,7 @@ module Parser::AST
203
203
  def hash_value(key)
204
204
  if :hash == type
205
205
  value_node = children.find { |pair_node| pair_node.key.to_value == key }
206
- value_node ? value_node.value : nil
206
+ value_node&.value
207
207
  else
208
208
  raise Synvert::Core::MethodNotSupported, "hash_value is not handled for #{debug_info}"
209
209
  end
@@ -280,6 +280,29 @@ module Parser::AST
280
280
  end
281
281
  end
282
282
 
283
+ # Respond key value for hash node, e.g.
284
+ #
285
+ # Current node is s(:hash, s(:pair, s(:sym, :number), s(:int, 10)))
286
+ # node.number_value is 10
287
+ def method_missing(method_name, *args, &block)
288
+ if :hash == type && method_name.to_s.include?('_value')
289
+ key = method_name.to_s.sub('_value', '')
290
+ return hash_value(key.to_sym)&.to_value if key?(key.to_sym)
291
+ return hash_value(key.to_s)&.to_value if key?(key.to_s)
292
+ end
293
+
294
+ super
295
+ end
296
+
297
+ def respond_to_missing?(method_name, *args)
298
+ if :hash == type && method_name.to_s.include?('_value')
299
+ key = method_name.to_s.sub('_value', '')
300
+ return true if key?(key.to_sym) || key?(key.to_s)
301
+ end
302
+
303
+ super
304
+ end
305
+
283
306
  def to_s
284
307
  if :mlhs == type
285
308
  "(#{children.map(&:name).join(', ')})"
@@ -322,27 +345,56 @@ module Parser::AST
322
345
  # @param [String] name of child node.
323
346
  # @return [Parser::Source::Range] source range of child node.
324
347
  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.operator ? Parser::Source::Range.new('(string)', loc.selector.begin_pos, loc.operator.end_pos) : 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?
348
+ case [type, child_name]
349
+ when %i[block pipe]
350
+ Parser::Source::Range.new('(string)', arguments.loc.expression.begin_pos, arguments.loc.expression.end_pos)
351
+ when %i[class name]
352
+ loc.name
353
+ when %i[def name]
354
+ loc.name
355
+ when %i[defs name]
356
+ loc.name
357
+ when %i[defs dot]
358
+ loc.operator
359
+ when %i[defs self]
360
+ Parser::Source::Range.new('(string)', loc.operator.begin_pos - 4, loc.operator.begin_pos)
361
+ when %i[send dot]
362
+ loc.dot
363
+ when %i[send message]
364
+ if loc.operator
365
+ Parser::Source::Range.new('(string)', loc.selector.begin_pos, loc.operator.end_pos)
366
+ else
367
+ loc.selector
343
368
  end
344
369
  else
345
- raise Synvert::Core::MethodNotSupported, "child_node_range is not handled for #{evaluated.inspect}, child_name: #{child_name}"
370
+ if respond_to?(child_name)
371
+ child_node = send(child_name)
372
+ return nil if child_node.nil?
373
+
374
+ if child_node.is_a?(Parser::AST::Node)
375
+ return(
376
+ Parser::Source::Range.new(
377
+ '(string)',
378
+ child_node.loc.expression.begin_pos,
379
+ child_node.loc.expression.end_pos
380
+ )
381
+ )
382
+ end
383
+
384
+ # arguments
385
+ return nil if child_node.empty?
386
+
387
+ return(
388
+ Parser::Source::Range.new(
389
+ '(string)',
390
+ child_node.first.loc.expression.begin_pos,
391
+ child_node.last.loc.expression.end_pos
392
+ )
393
+ )
394
+ end
395
+
396
+ raise Synvert::Core::MethodNotSupported,
397
+ "child_node_range is not handled for #{evaluated.inspect}, child_name: #{child_name}"
346
398
  end
347
399
  end
348
400
 
@@ -3,9 +3,9 @@
3
3
  module Synvert::Core
4
4
  # ReplaceAction to replace child node with code.
5
5
  class Rewriter::ReplaceAction < Rewriter::Action
6
- def initialize(instance, selector, with:)
6
+ def initialize(instance, *selectors, with:)
7
7
  @instance = instance
8
- @selector = selector
8
+ @selectors = selectors
9
9
  @code = with
10
10
  @node = @instance.current_node
11
11
  end
@@ -14,14 +14,14 @@ module Synvert::Core
14
14
  #
15
15
  # @return [Integer] begin position.
16
16
  def begin_pos
17
- @node.child_node_range(@selector).begin_pos
17
+ @selectors.map { |selector| @node.child_node_range(selector).begin_pos }.min
18
18
  end
19
19
 
20
20
  # End position of code to replace.
21
21
  #
22
22
  # @return [Integer] end position.
23
23
  def end_pos
24
- @node.child_node_range(@selector).end_pos
24
+ @selectors.map { |selector| @node.child_node_range(selector).end_pos }.max
25
25
  end
26
26
 
27
27
  # The rewritten source code.
@@ -252,12 +252,12 @@ module Synvert::Core
252
252
  end
253
253
 
254
254
  # Parse replace with dsl, it creates a [Synvert::Core::Rewriter::ReplaceAction] to
255
- # replace child node with code.
255
+ # replace child nodes with code.
256
256
  #
257
- # @param selector [Symbol] selector name of child node.
257
+ # @param selectors [Array<Symbol>] selector names of child node.
258
258
  # @param with [String] code need to be replaced with.
259
- def replace(selector, with:)
260
- @actions << Rewriter::ReplaceAction.new(self, selector, with: with)
259
+ def replace(*selectors, with:)
260
+ @actions << Rewriter::ReplaceAction.new(self, *selectors, with: with)
261
261
  end
262
262
 
263
263
  # Parse replace_erb_stmt_with_expr dsl, it creates a [Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction] to
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.27.2'
5
+ VERSION = '0.29.0'
6
6
  end
7
7
  end
@@ -333,6 +333,16 @@ describe Parser::AST::Node do
333
333
  end
334
334
  end
335
335
 
336
+ describe 'key value by method_missing' do
337
+ it 'gets for key value' do
338
+ node = parse("{:foo => :bar}")
339
+ expect(node.foo_value).to eq :bar
340
+
341
+ node = parse("{'foo' => 'bar'}")
342
+ expect(node.foo_value).to eq 'bar'
343
+ end
344
+ end
345
+
336
346
  describe '#recursive_children' do
337
347
  it 'iterates all children recursively' do
338
348
  node = parse('class Synvert; def current_node; @node; end; end')
@@ -395,6 +405,84 @@ describe Parser::AST::Node do
395
405
  end
396
406
 
397
407
  describe '#child_node_range' do
408
+ context 'block node' do
409
+ it 'checks caller' do
410
+ node = parse('Factory.define :user do |user|; end')
411
+ range = node.child_node_range(:caller)
412
+ expect(range.to_range).to eq(0...20)
413
+ end
414
+
415
+ it 'checks arguments' do
416
+ node = parse('Factory.define :user do |user|; end')
417
+ range = node.child_node_range(:arguments)
418
+ expect(range.to_range).to eq(25...29)
419
+ end
420
+
421
+ it 'checks pipe' do
422
+ node = parse('Factory.define :user do |user|; end')
423
+ range = node.child_node_range(:pipe)
424
+ expect(range.to_range).to eq(24...30)
425
+ end
426
+ end
427
+
428
+ context 'class node' do
429
+ it 'checks name' do
430
+ node = parse('class Post < ActiveRecord::Base; end')
431
+ range = node.child_node_range(:name)
432
+ expect(range.to_range).to eq(6...10)
433
+ end
434
+
435
+ it 'checks parent_class' do
436
+ node = parse('class Post < ActiveRecord::Base; end')
437
+ range = node.child_node_range(:parent_class)
438
+ expect(range.to_range).to eq(13...31)
439
+
440
+ node = parse('class Post; end')
441
+ range = node.child_node_range(:parent_class)
442
+ expect(range).to be_nil
443
+ end
444
+ end
445
+
446
+ context 'def node' do
447
+ it 'checks name' do
448
+ node = parse('def foo(bar); end')
449
+ range = node.child_node_range(:name)
450
+ expect(range.to_range).to eq(4...7)
451
+ end
452
+
453
+ it 'checks arguments' do
454
+ node = parse('def foo(bar); end')
455
+ range = node.child_node_range(:arguments)
456
+ expect(range.to_range).to eq(8...11)
457
+ end
458
+ end
459
+
460
+ context 'defs node' do
461
+ it 'checks self' do
462
+ node = parse('def self.foo(bar); end')
463
+ range = node.child_node_range(:self)
464
+ expect(range.to_range).to eq(4...8)
465
+ end
466
+
467
+ it 'checks dot' do
468
+ node = parse('def self.foo(bar); end')
469
+ range = node.child_node_range(:dot)
470
+ expect(range.to_range).to eq(8...9)
471
+ end
472
+
473
+ it 'checks name' do
474
+ node = parse('def self.foo(bar); end')
475
+ range = node.child_node_range(:name)
476
+ expect(range.to_range).to eq(9...12)
477
+ end
478
+
479
+ it 'checks arguments' do
480
+ node = parse('def self.foo(bar); end')
481
+ range = node.child_node_range(:arguments)
482
+ expect(range.to_range).to eq(13...16)
483
+ end
484
+ end
485
+
398
486
  context 'send node' do
399
487
  it 'checks receiver' do
400
488
  node = parse('foo.bar(test)')
@@ -444,24 +532,6 @@ describe Parser::AST::Node do
444
532
  expect(range).to be_nil
445
533
  end
446
534
  end
447
-
448
- context 'class node' do
449
- it 'checks name' do
450
- node = parse('class Post < ActiveRecord::Base; end')
451
- range = node.child_node_range(:name)
452
- expect(range.to_range).to eq(6...10)
453
- end
454
-
455
- it 'checks parent_class' do
456
- node = parse('class Post < ActiveRecord::Base; end')
457
- range = node.child_node_range(:parent_class)
458
- expect(range.to_range).to eq(13...31)
459
-
460
- node = parse('class Post; end')
461
- range = node.child_node_range(:parent_class)
462
- expect(range).to be_nil
463
- end
464
- end
465
535
  end
466
536
 
467
537
  describe '#rewritten_source' do
@@ -5,18 +5,18 @@ require 'spec_helper'
5
5
  module Synvert::Core
6
6
  describe Rewriter::DeleteAction do
7
7
  subject {
8
- source = "arr.map {}.flatten"
8
+ source = 'arr.map {}.flatten'
9
9
  node = Parser::CurrentRuby.parse(source)
10
10
  instance = double(current_node: node)
11
11
  Rewriter::DeleteAction.new(instance, :dot, :message)
12
12
  }
13
13
 
14
14
  it 'gets begin_pos' do
15
- expect(subject.begin_pos).to eq "arr.map {}".length
15
+ expect(subject.begin_pos).to eq 'arr.map {}'.length
16
16
  end
17
17
 
18
18
  it 'gets end_pos' do
19
- expect(subject.end_pos).to eq "arr.map {}.flatten".length
19
+ expect(subject.end_pos).to eq 'arr.map {}.flatten'.length
20
20
  end
21
21
 
22
22
  it 'gets rewritten_code' do
@@ -6,22 +6,22 @@ module Synvert::Core
6
6
  describe Rewriter::ReplaceAction do
7
7
  context 'replace with single line' do
8
8
  subject {
9
- source = "'slug from title'.gsub(' ', '_')"
9
+ source = 'FactoryBot.create(:user)'
10
10
  node = Parser::CurrentRuby.parse(source)
11
11
  instance = double(current_node: node)
12
- Rewriter::ReplaceAction.new(instance, :message, with: 'tr')
12
+ Rewriter::ReplaceAction.new(instance, :receiver, :dot, :message, with: 'create')
13
13
  }
14
14
 
15
15
  it 'gets begin_pos' do
16
- expect(subject.begin_pos).to eq "'slug from title'.".length
16
+ expect(subject.begin_pos).to eq 0
17
17
  end
18
18
 
19
19
  it 'gets end_pos' do
20
- expect(subject.end_pos).to eq "'slug from title'.gsub".length
20
+ expect(subject.end_pos).to eq 'FactoryBot.create'.length
21
21
  end
22
22
 
23
23
  it 'gets rewritten_code' do
24
- expect(subject.rewritten_code).to eq 'tr'
24
+ expect(subject.rewritten_code).to eq 'create'
25
25
  end
26
26
  end
27
27
  end
data/synvert-core.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.add_runtime_dependency "activesupport"
23
23
  spec.add_runtime_dependency "erubis"
24
- spec.add_runtime_dependency "parser", "~> 3.0.0"
24
+ spec.add_runtime_dependency "parser"
25
25
 
26
26
  spec.add_development_dependency "bundler"
27
27
  spec.add_development_dependency "guard"
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.27.2
4
+ version: 0.29.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-31 00:00:00.000000000 Z
11
+ date: 2021-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: parser
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 3.0.0
47
+ version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 3.0.0
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -213,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
213
213
  - !ruby/object:Gem::Version
214
214
  version: '0'
215
215
  requirements: []
216
- rubygems_version: 3.1.4
216
+ rubygems_version: 3.1.6
217
217
  signing_key:
218
218
  specification_version: 4
219
219
  summary: convert ruby code to better syntax.