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 +4 -4
- data/CHANGELOG.md +6 -3
- data/lib/synvert/core/node_ext.rb +74 -22
- data/lib/synvert/core/rewriter/action/replace_action.rb +4 -4
- data/lib/synvert/core/rewriter/instance.rb +4 -4
- data/lib/synvert/core/version.rb +1 -1
- data/spec/synvert/core/node_ext_spec.rb +88 -18
- data/spec/synvert/core/rewriter/action/delete_action_spec.rb +3 -3
- data/spec/synvert/core/rewriter/action/replace_action_spec.rb +5 -5
- data/synvert-core.gemspec +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31ee6b89cd48a4accb2dc71fdec2e487c534e8d6eb4a9bd6050817cd88f7ba3c
|
4
|
+
data.tar.gz: cd4c005e0f7a21e52e984e5279a45d4325d341b92d67feedbbc455ddc062e0fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d1e8642e682a155eedb03c6cdbabca55f53f22c258d4774da7200877159ec18c0a7d568823c5c379fd93810d0baf945a2bc139f8444423855c6279241acb0bc
|
7
|
+
data.tar.gz: 73a369f23d1add90b21ce578faf37a3136a6ffcb384f47fa5b3881fd4241af4b087b19fb0d854143ed1e3d9b76f350fc41b2415cddc29671cde3afe0e46d4709
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
## 0.
|
3
|
+
## 0.29.0 (2021-04-25)
|
4
4
|
|
5
|
-
*
|
5
|
+
* Make `child_name_range` support [:block, :pipe]
|
6
|
+
* Get key value for hash node
|
6
7
|
|
7
|
-
## 0.
|
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
|
104
|
+
ArgumentsNode.new(children[1])
|
105
105
|
when :defs
|
106
|
-
ArgumentsNode.new
|
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
|
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
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
Parser::Source::Range.new('(string)',
|
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
|
-
|
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,
|
6
|
+
def initialize(instance, *selectors, with:)
|
7
7
|
@instance = instance
|
8
|
-
@
|
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(
|
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(
|
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
|
255
|
+
# replace child nodes with code.
|
256
256
|
#
|
257
|
-
# @param
|
257
|
+
# @param selectors [Array<Symbol>] selector names of child node.
|
258
258
|
# @param with [String] code need to be replaced with.
|
259
|
-
def replace(
|
260
|
-
@actions << Rewriter::ReplaceAction.new(self,
|
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
|
data/lib/synvert/core/version.rb
CHANGED
@@ -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 =
|
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
|
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
|
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 =
|
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: '
|
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
|
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
|
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 '
|
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"
|
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.
|
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-
|
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:
|
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:
|
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.
|
216
|
+
rubygems_version: 3.1.6
|
217
217
|
signing_key:
|
218
218
|
specification_version: 4
|
219
219
|
summary: convert ruby code to better syntax.
|