synvert-core 0.57.0 → 0.58.3
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 +14 -0
- data/lib/synvert/core/node_ext.rb +11 -4
- data/lib/synvert/core/rewriter/action.rb +6 -6
- data/lib/synvert/core/rewriter/instance.rb +5 -3
- data/lib/synvert/core/rewriter/ruby_version.rb +1 -1
- data/lib/synvert/core/rewriter/scope/within_scope.rb +66 -22
- data/lib/synvert/core/version.rb +1 -1
- data/spec/synvert/core/node_ext_spec.rb +28 -0
- data/spec/synvert/core/rewriter/instance_spec.rb +12 -2
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +27 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c6266f727e24e5cd93cc1db656d84dc177dc0fceb0ab435a14164216d6dec80
|
4
|
+
data.tar.gz: 53e06769f132ac67ee113af6fecdb327184adc034b00aa58c0af8eab376ef45f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb0db8ed1e6636145f25ec8ca3cc3653ce415e7381c8e5d2126e7da7174782c57a2a4d60a3693794ae93ac02bd178b40f55971ffbf721e0d86b7c73fd17b930a
|
7
|
+
data.tar.gz: ee6222b098f64dcc809d0d54ed9c1bad84f54816e05602b601c7ae8b0211f26fb41c05e46fe9728dc362536971021cc2a6e232a5e9f8ac34eff3f6ef55e94cb3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.58.3 (2021-11-16)
|
4
|
+
|
5
|
+
* Return block value by `next`
|
6
|
+
* Add `Node#filename` method
|
7
|
+
|
8
|
+
## 0.58.2 (2021-10-23)
|
9
|
+
|
10
|
+
* Do not break the whole `recursive_children`
|
11
|
+
|
12
|
+
## 0.58.0 (2021-10-23)
|
13
|
+
|
14
|
+
* Support `left_value` and `right_value` for `and` and `or` node
|
15
|
+
* Rewrite `within_node` and `within_direct_node`, `WithinScope` accepts `recursive` and `direct` options
|
16
|
+
|
3
17
|
## 0.57.0 (2021-10-02)
|
4
18
|
|
5
19
|
* Compare ruby version in `.ruby-version` or `.rvmrc`
|
@@ -215,7 +215,7 @@ module Parser::AST
|
|
215
215
|
# @return [Parser::AST::Node] variable nodes.
|
216
216
|
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
217
217
|
def left_value
|
218
|
-
if %i[masgn lvasgn ivasgn cvasgn].include? type
|
218
|
+
if %i[masgn lvasgn ivasgn cvasgn and or].include? type
|
219
219
|
children[0]
|
220
220
|
elsif :or_asgn == type
|
221
221
|
children[0].children[0]
|
@@ -229,7 +229,7 @@ module Parser::AST
|
|
229
229
|
# @return [Array<Parser::AST::Node>] variable nodes.
|
230
230
|
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
231
231
|
def right_value
|
232
|
-
if %i[masgn lvasgn ivasgn cvasgn or_asgn].include? type
|
232
|
+
if %i[masgn lvasgn ivasgn cvasgn or_asgn and or].include? type
|
233
233
|
children[1]
|
234
234
|
else
|
235
235
|
raise Synvert::Core::MethodNotSupported, "right_value is not handled for #{debug_info}"
|
@@ -315,6 +315,13 @@ module Parser::AST
|
|
315
315
|
].join("\n")
|
316
316
|
end
|
317
317
|
|
318
|
+
# Get the file name of the current node.
|
319
|
+
#
|
320
|
+
# @return [String] file name.
|
321
|
+
def filename
|
322
|
+
loc.expression&.source_buffer.name
|
323
|
+
end
|
324
|
+
|
318
325
|
# Get the source code of current node.
|
319
326
|
#
|
320
327
|
# @return [String] source code.
|
@@ -432,8 +439,8 @@ module Parser::AST
|
|
432
439
|
def recursive_children(&block)
|
433
440
|
children.each do |child|
|
434
441
|
if child.is_a?(Parser::AST::Node)
|
435
|
-
yield child
|
436
|
-
child.recursive_children(&block)
|
442
|
+
stop = yield child
|
443
|
+
child.recursive_children(&block) unless stop == :stop
|
437
444
|
end
|
438
445
|
end
|
439
446
|
end
|
@@ -55,7 +55,7 @@ module Synvert::Core
|
|
55
55
|
|
56
56
|
def squeeze_spaces
|
57
57
|
if file_source[@begin_pos - 1] == ' ' && file_source[@end_pos] == ' '
|
58
|
-
@begin_pos
|
58
|
+
@begin_pos -= 1
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -67,19 +67,19 @@ module Synvert::Core
|
|
67
67
|
after_line_is_blank = lines[end_line] == ''
|
68
68
|
|
69
69
|
if lines.length > 1 && before_line_is_blank && after_line_is_blank
|
70
|
-
@end_pos
|
70
|
+
@end_pos += "\n".length
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
def remove_comma
|
75
75
|
if ',' == file_source[@begin_pos - 1]
|
76
|
-
@begin_pos
|
76
|
+
@begin_pos -= 1
|
77
77
|
elsif ', ' == file_source[@begin_pos - 2, 2]
|
78
|
-
@begin_pos
|
78
|
+
@begin_pos -= 2
|
79
79
|
elsif ', ' == file_source[@end_pos, 2]
|
80
|
-
@end_pos
|
80
|
+
@end_pos += 2
|
81
81
|
elsif ',' == file_source[@end_pos]
|
82
|
-
@end_pos
|
82
|
+
@end_pos += 1
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -161,9 +161,11 @@ module Synvert::Core
|
|
161
161
|
# then continue operating on each matching ast node.
|
162
162
|
#
|
163
163
|
# @param rules [Hash] rules to find mathing ast nodes.
|
164
|
+
# @param options [Hash] optional, set if recursive or not.
|
164
165
|
# @param block [Block] block code to continue operating on the matching nodes.
|
165
|
-
def within_node(rules, &block)
|
166
|
-
|
166
|
+
def within_node(rules, options = nil, &block)
|
167
|
+
options ||= { recursive: true }
|
168
|
+
Rewriter::WithinScope.new(self, rules, options, &block).process
|
167
169
|
end
|
168
170
|
|
169
171
|
alias with_node within_node
|
@@ -174,7 +176,7 @@ module Synvert::Core
|
|
174
176
|
# @param rules [Hash] rules to find mathing ast nodes.
|
175
177
|
# @param block [Block] block code to continue operating on the matching nodes.
|
176
178
|
def within_direct_node(rules, &block)
|
177
|
-
Rewriter::WithinScope.new(self, rules, {
|
179
|
+
Rewriter::WithinScope.new(self, rules, { direct: true }, &block).process
|
178
180
|
end
|
179
181
|
|
180
182
|
alias with_direct_node within_direct_node
|
@@ -21,7 +21,7 @@ module Synvert::Core
|
|
21
21
|
elsif File.exist?(File.join(Configuration.path, '.rvmrc'))
|
22
22
|
versionFile = '.rvmrc'
|
23
23
|
end
|
24
|
-
return true
|
24
|
+
return true unless versionFile
|
25
25
|
|
26
26
|
version = File.read(File.join(Configuration.path, versionFile))
|
27
27
|
Gem::Version.new(version) >= Gem::Version.new(@version)
|
@@ -9,7 +9,7 @@ module Synvert::Core
|
|
9
9
|
# @param rules [Hash]
|
10
10
|
# @param options [Hash]
|
11
11
|
# @param block [Block]
|
12
|
-
def initialize(instance, rules, options = {
|
12
|
+
def initialize(instance, rules, options = {}, &block)
|
13
13
|
@instance = instance
|
14
14
|
@rules = rules
|
15
15
|
@options = options
|
@@ -23,7 +23,14 @@ module Synvert::Core
|
|
23
23
|
current_node = @instance.current_node
|
24
24
|
return unless current_node
|
25
25
|
|
26
|
-
matching_nodes =
|
26
|
+
matching_nodes =
|
27
|
+
if @options[:direct]
|
28
|
+
find_direct_matching_nodes(current_node)
|
29
|
+
elsif @options[:recursive]
|
30
|
+
find_recursive_matching_nodes(current_node)
|
31
|
+
else
|
32
|
+
find_matching_nodes(current_node)
|
33
|
+
end
|
27
34
|
@instance.process_with_node current_node do
|
28
35
|
matching_nodes.each do |matching_node|
|
29
36
|
@instance.process_with_node matching_node do
|
@@ -35,36 +42,73 @@ module Synvert::Core
|
|
35
42
|
|
36
43
|
private
|
37
44
|
|
38
|
-
|
45
|
+
# Find the matching nodes only in current or direct children.
|
46
|
+
def find_direct_matching_nodes(current_node)
|
39
47
|
matching_nodes = []
|
40
|
-
if
|
41
|
-
if current_node.is_a?(Parser::AST::Node)
|
42
|
-
matching_nodes << current_node if current_node.match? @rules
|
43
|
-
current_node.recursive_children do |child_node|
|
44
|
-
matching_nodes << child_node if child_node.match? @rules
|
45
|
-
end
|
46
|
-
else
|
47
|
-
current_node.each do |node|
|
48
|
-
matching_nodes << node if node.match? @rules
|
49
|
-
node.recursive_children do |child_node|
|
50
|
-
matching_nodes << child_node if child_node.match? @rules
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
elsif current_node.is_a?(Parser::AST::Node)
|
48
|
+
if current_node.is_a?(Parser::AST::Node)
|
55
49
|
if current_node.type == :begin
|
56
50
|
current_node.children.each do |child_node|
|
57
|
-
matching_nodes << child_node if child_node.match?
|
51
|
+
matching_nodes << child_node if child_node.match?(@rules)
|
58
52
|
end
|
59
|
-
elsif current_node.match?
|
53
|
+
elsif current_node.match?(@rules)
|
60
54
|
matching_nodes << current_node
|
61
55
|
end
|
62
56
|
else
|
63
57
|
current_node.each do |child_node|
|
64
|
-
matching_nodes << child_node if child_node.match?
|
58
|
+
matching_nodes << child_node if child_node.match?(@rules)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
matching_nodes
|
62
|
+
end
|
63
|
+
|
64
|
+
# Find matching nodes in all recursive children.
|
65
|
+
def find_recursive_matching_nodes(current_node)
|
66
|
+
matching_nodes = []
|
67
|
+
if current_node.is_a?(Parser::AST::Node)
|
68
|
+
matching_nodes << current_node if current_node.match?(@rules)
|
69
|
+
current_node.recursive_children do |child_node|
|
70
|
+
matching_nodes << child_node if child_node.match?(@rules)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
current_node.each do |node|
|
74
|
+
matching_nodes << node if node.match?(@rules)
|
75
|
+
node.recursive_children do |child_node|
|
76
|
+
matching_nodes << child_node if child_node.match?(@rules)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
matching_nodes
|
81
|
+
end
|
82
|
+
|
83
|
+
# Find matching nodes in recursive children but do not continue on matching nodes.
|
84
|
+
def find_matching_nodes(current_node)
|
85
|
+
matching_nodes = []
|
86
|
+
if current_node.is_a?(Parser::AST::Node)
|
87
|
+
if current_node.match?(@rules)
|
88
|
+
matching_nodes << current_node
|
89
|
+
return matching_nodes
|
90
|
+
end
|
91
|
+
current_node.recursive_children do |child_node|
|
92
|
+
if child_node.match?(@rules)
|
93
|
+
matching_nodes << child_node
|
94
|
+
next :stop
|
95
|
+
end
|
96
|
+
end
|
97
|
+
else
|
98
|
+
current_node.each do |node|
|
99
|
+
if node.match?(@rules)
|
100
|
+
matching_nodes << node
|
101
|
+
next
|
102
|
+
end
|
103
|
+
node.recursive_children do |child_node|
|
104
|
+
if child_node.match?(@rules)
|
105
|
+
matching_nodes << child_node
|
106
|
+
next :stop
|
107
|
+
end
|
108
|
+
end
|
65
109
|
end
|
66
110
|
end
|
67
111
|
matching_nodes
|
68
112
|
end
|
69
113
|
end
|
70
|
-
end
|
114
|
+
end
|
data/lib/synvert/core/version.rb
CHANGED
@@ -291,6 +291,16 @@ describe Parser::AST::Node do
|
|
291
291
|
node = parse('a ||= 1')
|
292
292
|
expect(node.left_value).to eq :a
|
293
293
|
end
|
294
|
+
|
295
|
+
it 'gets for and' do
|
296
|
+
node = parse('foo && bar')
|
297
|
+
expect(node.left_value).to eq parse('foo')
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'gets for or' do
|
301
|
+
node = parse('foo || bar')
|
302
|
+
expect(node.left_value).to eq parse('foo')
|
303
|
+
end
|
294
304
|
end
|
295
305
|
|
296
306
|
describe '#right_value' do
|
@@ -323,6 +333,16 @@ describe Parser::AST::Node do
|
|
323
333
|
node = parse('a ||= 1')
|
324
334
|
expect(node.right_value).to eq parse('1')
|
325
335
|
end
|
336
|
+
|
337
|
+
it 'gets for and' do
|
338
|
+
node = parse('foo && bar')
|
339
|
+
expect(node.right_value).to eq parse('bar')
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'gets for or' do
|
343
|
+
node = parse('foo || bar')
|
344
|
+
expect(node.right_value).to eq parse('bar')
|
345
|
+
end
|
326
346
|
end
|
327
347
|
|
328
348
|
describe '#to_value' do
|
@@ -376,6 +396,14 @@ describe Parser::AST::Node do
|
|
376
396
|
end
|
377
397
|
end
|
378
398
|
|
399
|
+
describe '#filename' do
|
400
|
+
it 'gets file name' do
|
401
|
+
source = 'foobar'
|
402
|
+
node = parse(source)
|
403
|
+
expect(node.filename).to eq '(string)'
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
379
407
|
describe '#to_source' do
|
380
408
|
it 'gets for node' do
|
381
409
|
source = 'params[:user][:email]'
|
@@ -31,13 +31,23 @@ module Synvert::Core
|
|
31
31
|
instance.with_node(type: 'send', message: 'create', &block)
|
32
32
|
end
|
33
33
|
|
34
|
-
it 'parses
|
34
|
+
it 'parses within_node with recursive false' do
|
35
35
|
scope = double
|
36
36
|
block = proc {}
|
37
37
|
expect(Rewriter::WithinScope).to receive(:new)
|
38
38
|
.with(instance, { type: 'send', message: 'create' }, { recursive: false }, &block)
|
39
39
|
.and_return(scope)
|
40
40
|
expect(scope).to receive(:process)
|
41
|
+
instance.within_node({ type: 'send', message: 'create' }, { recursive: false }, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'parses within_direct_node' do
|
45
|
+
scope = double
|
46
|
+
block = proc {}
|
47
|
+
expect(Rewriter::WithinScope).to receive(:new)
|
48
|
+
.with(instance, { type: 'send', message: 'create' }, { direct: true }, &block)
|
49
|
+
.and_return(scope)
|
50
|
+
expect(scope).to receive(:process)
|
41
51
|
instance.within_direct_node(type: 'send', message: 'create', &block)
|
42
52
|
end
|
43
53
|
|
@@ -45,7 +55,7 @@ module Synvert::Core
|
|
45
55
|
scope = double
|
46
56
|
block = proc {}
|
47
57
|
expect(Rewriter::WithinScope).to receive(:new)
|
48
|
-
.with(instance, { type: 'send', message: 'create' }, {
|
58
|
+
.with(instance, { type: 'send', message: 'create' }, { direct: true }, &block)
|
49
59
|
.and_return(scope)
|
50
60
|
expect(scope).to receive(:process)
|
51
61
|
instance.with_direct_node(type: 'send', message: 'create', &block)
|
@@ -51,6 +51,33 @@ module Synvert::Core
|
|
51
51
|
expect(type_in_scope).to eq :send
|
52
52
|
expect(instance.current_node.type).to eq :block
|
53
53
|
end
|
54
|
+
|
55
|
+
it 'matches multiple block nodes' do
|
56
|
+
block_nodes = []
|
57
|
+
scope = Rewriter::WithinScope.new(instance, { type: 'block' }, { recursive: true }) do
|
58
|
+
block_nodes << node
|
59
|
+
end
|
60
|
+
scope.process
|
61
|
+
expect(block_nodes.size).to eq 2
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'matches only one block node if no recursive' do
|
65
|
+
block_nodes = []
|
66
|
+
scope = Rewriter::WithinScope.new(instance, { type: 'block' } , { recursive: false }) do
|
67
|
+
block_nodes << node
|
68
|
+
end
|
69
|
+
scope.process
|
70
|
+
expect(block_nodes.size).to eq 1
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'matches only one direct node' do
|
74
|
+
block_nodes = []
|
75
|
+
scope = Rewriter::WithinScope.new(instance, { type: 'block' } , { direct: true }) do
|
76
|
+
block_nodes << node
|
77
|
+
end
|
78
|
+
scope.process
|
79
|
+
expect(block_nodes.size).to eq 1
|
80
|
+
end
|
54
81
|
end
|
55
82
|
end
|
56
83
|
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.
|
4
|
+
version: 0.58.3
|
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-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|