synvert-core 0.27.2 → 0.29.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: 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.