synvert-core 1.10.1 → 1.12.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 +11 -0
- data/Gemfile.lock +3 -1
- data/README.md +2 -2
- data/lib/synvert/core/configuration.rb +9 -1
- data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +2 -2
- data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/condition.rb +4 -4
- data/lib/synvert/core/rewriter/instance.rb +31 -33
- data/lib/synvert/core/rewriter/scope/within_scope.rb +6 -4
- data/lib/synvert/core/rewriter.rb +0 -1
- data/lib/synvert/core/version.rb +1 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +1 -1
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +105 -60
- data/synvert-core-ruby.gemspec +1 -0
- metadata +16 -5
- data/lib/synvert/core/rewriter/scope/query_scope.rb +0 -38
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e526dbe6f12418da40df7cb5b945f7ed957820573455b575f2a609c334b58e72
|
4
|
+
data.tar.gz: 1f22528b636b548c9ddb05466d366e62dce813794d173c11b8de11ef522b97a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46f29de95717e764a33c0303c20086fb3fc3dcc43c7548c174b4eb46f368e2b0cec6b1ea6ff88eed04654f58cf9dad3066aa679ece8d7a6cfb2a7676095fe4aa
|
7
|
+
data.tar.gz: 7622e84c396751bd49b57464424efee84ba3f45d727c5653528fb11a5da7d26e856c0008ea1dc5967e7ee3afe8f238a8dbb6c67bc5071970312523a426a98dd3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 1.12.0 (2022-10-14)
|
4
|
+
|
5
|
+
* Condition accepts both nql and rules
|
6
|
+
* Make `find_node` as an alias to `within_node`
|
7
|
+
* Remove skip files only once
|
8
|
+
|
9
|
+
## 1.11.0 (2022-10-11)
|
10
|
+
|
11
|
+
* Add `Configuration.number_of_workers`
|
12
|
+
* Test rewriter in parallel
|
13
|
+
|
3
14
|
## 1.10.1 (2022-10-09)
|
4
15
|
|
5
16
|
* Do not reset `@options`
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
synvert-core (1.
|
4
|
+
synvert-core (1.12.0)
|
5
5
|
activesupport (< 7.0.0)
|
6
6
|
erubis
|
7
7
|
node_mutation
|
8
8
|
node_query
|
9
|
+
parallel
|
9
10
|
parser
|
10
11
|
parser_node_ext
|
11
12
|
|
@@ -57,6 +58,7 @@ GEM
|
|
57
58
|
notiffany (0.1.3)
|
58
59
|
nenv (~> 0.1)
|
59
60
|
shellany (~> 0.0)
|
61
|
+
parallel (1.22.1)
|
60
62
|
parser (3.1.2.1)
|
61
63
|
ast (~> 2.4.1)
|
62
64
|
parser_node_ext (0.4.0)
|
data/README.md
CHANGED
@@ -73,16 +73,16 @@ DSLs are as follows
|
|
73
73
|
|
74
74
|
Scopes:
|
75
75
|
|
76
|
-
* [find_node](./Synvert/Core/Rewriter/Instance.html#find_node-instance_method) - recursively find matching ast nodes by node query language
|
77
76
|
* [within_node](./Synvert/Core/Rewriter/Instance.html#within_node-instance_method) - recursively find matching ast nodes
|
78
77
|
* [with_node](./Synvert/Core/Rewriter/Instance.html#with_node-instance_method) - alias to within_node
|
78
|
+
* [find_node](./Synvert/Core/Rewriter/Instance.html#find_node-instance_method) - alias to within_node
|
79
79
|
* [goto_node](./Synvert/Core/Rewriter/Instance.html#goto_node-instance_method) - go to a child node
|
80
80
|
|
81
81
|
Conditions:
|
82
82
|
|
83
83
|
* [if_exist_node](./Synvert/Core/Rewriter/Instance.html#if_exist_node-instance_method) - check if matching node exist in the child nodes
|
84
84
|
* [unless_exist_node](./Synvert/Core/Rewriter/Instance.html#unless_exist_node-instance_method) - check if matching node doesn't exist in the child nodes
|
85
|
-
* [if_only_exist_node](./Synvert/Core/Rewriter/Instance.html#if_only_exist_node-instance_method) - check if current node has only one child node and the child node matches
|
85
|
+
* [if_only_exist_node](./Synvert/Core/Rewriter/Instance.html#if_only_exist_node-instance_method) - check if current node has only one child node and the child node matches
|
86
86
|
|
87
87
|
Actions:
|
88
88
|
|
@@ -8,7 +8,8 @@ module Synvert::Core
|
|
8
8
|
# @!attribute [w] skip_paths
|
9
9
|
# @!attribute [w] only_paths
|
10
10
|
# @!attribute [w] show_run_process
|
11
|
-
|
11
|
+
# @!attribute [w] number_of_workers
|
12
|
+
attr_writer :root_path, :skip_paths, :only_paths, :show_run_process, :number_of_workers
|
12
13
|
|
13
14
|
# Get the path.
|
14
15
|
#
|
@@ -37,6 +38,13 @@ module Synvert::Core
|
|
37
38
|
def show_run_process
|
38
39
|
@show_run_process || false
|
39
40
|
end
|
41
|
+
|
42
|
+
# Number of workers
|
43
|
+
#
|
44
|
+
# @return [Integer] default is 1
|
45
|
+
def number_of_workers
|
46
|
+
@number_of_workers || 1
|
47
|
+
end
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Synvert::Core
|
4
|
-
# IfOnlyExistCondition checks if node has only one child node and the child node matches
|
4
|
+
# IfOnlyExistCondition checks if node has only one child node and the child node matches.
|
5
5
|
class Rewriter::IfOnlyExistCondition < Rewriter::Condition
|
6
6
|
private
|
7
7
|
|
8
|
-
# check if only have one child node and the child node matches
|
8
|
+
# check if only have one child node and the child node matches.
|
9
9
|
#
|
10
10
|
# @return [Boolean]
|
11
11
|
def match?
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Synvert::Core
|
4
|
-
# Condition checks if rules matches.
|
4
|
+
# Condition checks if nql or rules matches.
|
5
5
|
class Rewriter::Condition
|
6
6
|
# Initialize a Condition.
|
7
7
|
#
|
8
8
|
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param
|
9
|
+
# @param nql_or_rules [String|Hash]
|
10
10
|
# @yield run when condition matches
|
11
|
-
def initialize(instance,
|
11
|
+
def initialize(instance, nql_or_rules, &block)
|
12
12
|
@instance = instance
|
13
|
-
@node_query = NodeQuery.new(
|
13
|
+
@node_query = NodeQuery.new(nql_or_rules)
|
14
14
|
@block = block
|
15
15
|
end
|
16
16
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'parallel'
|
2
3
|
|
3
4
|
module Synvert::Core
|
4
5
|
# Instance is an execution unit, it finds specified ast nodes,
|
@@ -41,8 +42,14 @@ module Synvert::Core
|
|
41
42
|
# It finds specified files, for each file, it executes the block code, tests the original code,
|
42
43
|
# then returns the actions.
|
43
44
|
def test
|
44
|
-
|
45
|
-
|
45
|
+
if Configuration.number_of_workers > 1
|
46
|
+
Parallel.map(get_file_paths, in_processes: Configuration.number_of_workers) do |file_path|
|
47
|
+
test_file(file_path)
|
48
|
+
end
|
49
|
+
else
|
50
|
+
get_file_paths.map do |file_path|
|
51
|
+
test_file(file_path)
|
52
|
+
end
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
@@ -78,38 +85,29 @@ module Synvert::Core
|
|
78
85
|
# DSL #
|
79
86
|
#######
|
80
87
|
|
81
|
-
# Parse +find_node+ dsl, it creates {Synvert::Core::Rewriter::QueryScope} to recursively find matching ast nodes,
|
82
|
-
# then continue operating on each matching ast node.
|
83
|
-
# @example
|
84
|
-
# # matches FactoryBot.create(:user)
|
85
|
-
# find_node '.send[receiver=FactoryBot][message=create][arguments.size=1]' do
|
86
|
-
# end
|
87
|
-
# @param nql [String] node query language to find matching ast nodes.
|
88
|
-
# @yield run on the matching nodes.
|
89
|
-
# @raise [Synvert::Core::NodeQuery::Compiler::ParseError] if query string is invalid.
|
90
|
-
def find_node(nql, options = {}, &block)
|
91
|
-
Rewriter::QueryScope.new(self, nql, options, &block).process
|
92
|
-
rescue NodeQueryLexer::ScanError, Racc::ParseError => e
|
93
|
-
raise NodeQuery::Compiler::ParseError, "Invalid query string: #{nql}"
|
94
|
-
end
|
95
|
-
|
96
88
|
# Parse +within_node+ dsl, it creates a {Synvert::Core::Rewriter::WithinScope} to recursively find matching ast nodes,
|
97
89
|
# then continue operating on each matching ast node.
|
98
90
|
# @example
|
99
91
|
# # matches User.find_by_login('test')
|
100
92
|
# with_node type: 'send', message: /^find_by_/ do
|
101
93
|
# end
|
102
|
-
#
|
94
|
+
# # matches FactoryBot.create(:user)
|
95
|
+
# with_node '.send[receiver=FactoryBot][message=create][arguments.size=1]' do
|
96
|
+
# end
|
97
|
+
# @param nql_or_rules [String|Hash] nql or rules to find mathing ast nodes.
|
103
98
|
# @param options [Hash] optional
|
104
99
|
# @option including_self [Boolean] set if query the current node, default is true
|
105
100
|
# @option stop_at_first_match [Boolean] set if stop at first match, default is false
|
106
101
|
# @option recursive [Boolean] set if recursively query child nodes, default is true
|
107
102
|
# @yield run on the matching nodes.
|
108
|
-
def within_node(
|
109
|
-
Rewriter::WithinScope.new(self,
|
103
|
+
def within_node(nql_or_rules, options = {}, &block)
|
104
|
+
Rewriter::WithinScope.new(self, nql_or_rules, options, &block).process
|
105
|
+
rescue NodeQueryLexer::ScanError, Racc::ParseError => e
|
106
|
+
raise NodeQuery::Compiler::ParseError, "Invalid query string: #{nql_or_rules}"
|
110
107
|
end
|
111
108
|
|
112
109
|
alias with_node within_node
|
110
|
+
alias find_node within_node
|
113
111
|
|
114
112
|
# Parse +goto_node+ dsl, it creates a {Synvert::Core::Rewriter::GotoScope} to go to a child node,
|
115
113
|
# then continue operating on the child node.
|
@@ -133,10 +131,10 @@ module Synvert::Core
|
|
133
131
|
# if_exist_node type: 'send', message: 'any_instance' do
|
134
132
|
# end
|
135
133
|
# end
|
136
|
-
# @param
|
134
|
+
# @param nql_or_rules [String|Hash] nql or rules to check mathing ast nodes.
|
137
135
|
# @param block [Block] block code to continue operating on the matching nodes.
|
138
|
-
def if_exist_node(
|
139
|
-
Rewriter::IfExistCondition.new(self,
|
136
|
+
def if_exist_node(nql_or_rules, &block)
|
137
|
+
Rewriter::IfExistCondition.new(self, nql_or_rules, &block).process
|
140
138
|
end
|
141
139
|
|
142
140
|
# Parse +unless_exist_node+ dsl, it creates a {Synvert::Core::Rewriter::UnlessExistCondition} to check
|
@@ -147,14 +145,14 @@ module Synvert::Core
|
|
147
145
|
# unless_exist_node type: 'send', message: 'any_instance' do
|
148
146
|
# end
|
149
147
|
# end
|
150
|
-
# @param
|
148
|
+
# @param nql_or_rules [String|Hash] nql or rules to check mathing ast nodes.
|
151
149
|
# @param block [Block] block code to continue operating on the matching nodes.
|
152
|
-
def unless_exist_node(
|
153
|
-
Rewriter::UnlessExistCondition.new(self,
|
150
|
+
def unless_exist_node(nql_or_rules, &block)
|
151
|
+
Rewriter::UnlessExistCondition.new(self, nql_or_rules, &block).process
|
154
152
|
end
|
155
153
|
|
156
154
|
# Parse +if_only_exist_node+ dsl, it creates a {Synvert::Core::Rewriter::IfOnlyExistCondition} to check
|
157
|
-
# if current node has only one child node and the child node matches
|
155
|
+
# if current node has only one child node and the child node matches,
|
158
156
|
# if so, then continue operating on each matching ast node.
|
159
157
|
# @example
|
160
158
|
# # it { should matcher }
|
@@ -162,10 +160,10 @@ module Synvert::Core
|
|
162
160
|
# if_only_exist_node type: 'send', receiver: nil, message: 'should' do
|
163
161
|
# end
|
164
162
|
# end
|
165
|
-
# @param
|
163
|
+
# @param nql_or_rules [String|Hash] nql or rules to check mathing ast nodes.
|
166
164
|
# @param block [Block] block code to continue operating on the matching nodes.
|
167
|
-
def if_only_exist_node(
|
168
|
-
Rewriter::IfOnlyExistCondition.new(self,
|
165
|
+
def if_only_exist_node(nql_or_rules, &block)
|
166
|
+
Rewriter::IfOnlyExistCondition.new(self, nql_or_rules, &block).process
|
169
167
|
end
|
170
168
|
|
171
169
|
# Parse +append+ dsl, it creates a {Synvert::Core::Rewriter::AppendAction} to
|
@@ -427,16 +425,16 @@ module Synvert::Core
|
|
427
425
|
only_paths.flat_map do |only_path|
|
428
426
|
@file_patterns.flat_map do |file_pattern|
|
429
427
|
pattern = only_path == "." ? file_pattern : File.join(only_path, file_pattern)
|
430
|
-
Dir.glob(pattern)
|
428
|
+
Dir.glob(pattern)
|
431
429
|
end
|
432
|
-
end
|
430
|
+
end - get_skip_files
|
433
431
|
end
|
434
432
|
end
|
435
433
|
|
436
434
|
# Get skip files.
|
437
435
|
# @return [Array<String>] skip files
|
438
436
|
def get_skip_files
|
439
|
-
|
437
|
+
Configuration.skip_paths.flat_map do |skip_path|
|
440
438
|
if File.directory?(skip_path)
|
441
439
|
Dir.glob(File.join(skip_path, "**/*"))
|
442
440
|
elsif File.file?(skip_path)
|
@@ -1,22 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Synvert::Core
|
4
|
-
# WithinScope finds out nodes which match rules, then changes its scope to matching node.
|
4
|
+
# WithinScope finds out nodes which match nql or rules, then changes its scope to matching node.
|
5
5
|
class Rewriter::WithinScope < Rewriter::Scope
|
6
6
|
# Initialize a WithinScope.
|
7
7
|
#
|
8
8
|
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param
|
9
|
+
# @param nql_or_rules [String|Hash]
|
10
10
|
# @param options [Hash]
|
11
11
|
# @yield run on all matching nodes
|
12
|
-
|
12
|
+
# @raise [Synvert::Core::NodeQuery::Compiler::ParseError] if the query string is invalid.
|
13
|
+
def initialize(instance, nql_or_rules, options = {}, &block)
|
13
14
|
super(instance, &block)
|
14
15
|
|
15
16
|
@options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
|
16
|
-
@node_query = NodeQuery.new(
|
17
|
+
@node_query = NodeQuery.new(nql_or_rules)
|
17
18
|
end
|
18
19
|
|
19
20
|
# Find out the matching nodes.
|
21
|
+
#
|
20
22
|
# It checks the current node and iterates all child nodes,
|
21
23
|
# then run the block code on each matching node.
|
22
24
|
def process
|
@@ -17,7 +17,6 @@ module Synvert::Core
|
|
17
17
|
autoload :Instance, 'synvert/core/rewriter/instance'
|
18
18
|
|
19
19
|
autoload :Scope, 'synvert/core/rewriter/scope'
|
20
|
-
autoload :QueryScope, 'synvert/core/rewriter/scope/query_scope'
|
21
20
|
autoload :WithinScope, 'synvert/core/rewriter/scope/within_scope'
|
22
21
|
autoload :GotoScope, 'synvert/core/rewriter/scope/goto_scope'
|
23
22
|
|
data/lib/synvert/core/version.rb
CHANGED
@@ -12,7 +12,7 @@ module Synvert::Core
|
|
12
12
|
it 'parses find_node' do
|
13
13
|
scope = double
|
14
14
|
block = proc {}
|
15
|
-
expect(Rewriter::
|
15
|
+
expect(Rewriter::WithinScope).to receive(:new).with(instance, '.send[message=create]', {}, &block).and_return(scope)
|
16
16
|
expect(scope).to receive(:process)
|
17
17
|
instance.find_node('.send[message=create]', &block)
|
18
18
|
end
|
@@ -23,72 +23,117 @@ module Synvert::Core
|
|
23
23
|
before { instance.current_node = node }
|
24
24
|
|
25
25
|
describe '#process' do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
context 'rules' do
|
27
|
+
it 'not call block if no matching node' do
|
28
|
+
run = false
|
29
|
+
scope =
|
30
|
+
Rewriter::WithinScope.new instance, type: 'send', message: 'missing' do
|
31
|
+
run = true
|
32
|
+
end
|
33
|
+
scope.process
|
34
|
+
expect(run).to be_falsey
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
37
|
+
it 'call block if there is matching node' do
|
38
|
+
run = false
|
39
|
+
type_in_scope = nil
|
40
|
+
scope =
|
41
|
+
Rewriter::WithinScope.new instance,
|
42
|
+
type: 'send',
|
43
|
+
receiver: 'FactoryGirl',
|
44
|
+
message: 'create',
|
45
|
+
arguments: [':user'] do
|
46
|
+
run = true
|
47
|
+
type_in_scope = node.type
|
48
|
+
end
|
49
|
+
scope.process
|
50
|
+
expect(run).to be_truthy
|
51
|
+
expect(type_in_scope).to eq :send
|
52
|
+
expect(instance.current_node.type).to eq :block
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
it 'matches multiple block nodes' do
|
56
|
+
block_nodes = []
|
57
|
+
scope =
|
58
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }) do
|
59
|
+
block_nodes << node
|
60
|
+
end
|
61
|
+
scope.process
|
62
|
+
expect(block_nodes.size).to eq 3
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
65
|
+
it 'matches only 2 block nodes if including_self is false' do
|
66
|
+
block_nodes = []
|
67
|
+
scope =
|
68
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }, { including_self: false }) do
|
69
|
+
block_nodes << node
|
70
|
+
end
|
71
|
+
scope.process
|
72
|
+
expect(block_nodes.size).to eq 2
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
it 'matches only one block node if recursive is false' do
|
76
|
+
block_nodes = []
|
77
|
+
scope =
|
78
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }, { recursive: false }) do
|
79
|
+
block_nodes << node
|
80
|
+
end
|
81
|
+
scope.process
|
82
|
+
expect(block_nodes.size).to eq 1
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'matches only one block node if stop_at_first_match is true' do
|
86
|
+
block_nodes = []
|
87
|
+
scope =
|
88
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }, { stop_at_first_match: true }) do
|
89
|
+
block_nodes << node
|
90
|
+
end
|
91
|
+
scope.process
|
92
|
+
expect(block_nodes.size).to eq 1
|
93
|
+
end
|
82
94
|
end
|
83
95
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
96
|
+
context 'nql' do
|
97
|
+
it 'not call block if no matching node' do
|
98
|
+
run = false
|
99
|
+
scope =
|
100
|
+
described_class.new instance, '.send[message=missing]' do
|
101
|
+
run = true
|
102
|
+
end
|
103
|
+
scope.process
|
104
|
+
expect(run).to be_falsey
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'call block if there is matching node' do
|
108
|
+
run = false
|
109
|
+
type_in_scope = nil
|
110
|
+
scope =
|
111
|
+
described_class.new instance, '.send[receiver=FactoryGirl][message=create][arguments=(:user)]' do
|
112
|
+
run = true
|
113
|
+
type_in_scope = node.type
|
114
|
+
end
|
115
|
+
scope.process
|
116
|
+
expect(run).to be_truthy
|
117
|
+
expect(type_in_scope).to eq :send
|
118
|
+
expect(instance.current_node.type).to eq :block
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'matches multiple block nodes' do
|
122
|
+
block_nodes = []
|
123
|
+
scope =
|
124
|
+
described_class.new(instance, '.block') do
|
125
|
+
block_nodes << node
|
126
|
+
end
|
127
|
+
scope.process
|
128
|
+
expect(block_nodes.size).to eq 3
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'raises InvalidOperatorError' do
|
132
|
+
scope = described_class.new(instance, '.send[receiver IN FactoryGirl]') {}
|
133
|
+
expect {
|
134
|
+
scope.process
|
135
|
+
}.to raise_error(NodeQuery::Compiler::InvalidOperatorError)
|
136
|
+
end
|
92
137
|
end
|
93
138
|
end
|
94
139
|
end
|
data/synvert-core-ruby.gemspec
CHANGED
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: 1.
|
4
|
+
version: 1.12.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: 2022-10-
|
11
|
+
date: 2022-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: parallel
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
description: convert ruby code to better syntax automatically.
|
98
112
|
email:
|
99
113
|
- flyerhzm@gmail.com
|
@@ -130,7 +144,6 @@ files:
|
|
130
144
|
- lib/synvert/core/rewriter/ruby_version.rb
|
131
145
|
- lib/synvert/core/rewriter/scope.rb
|
132
146
|
- lib/synvert/core/rewriter/scope/goto_scope.rb
|
133
|
-
- lib/synvert/core/rewriter/scope/query_scope.rb
|
134
147
|
- lib/synvert/core/rewriter/scope/within_scope.rb
|
135
148
|
- lib/synvert/core/rewriter/warning.rb
|
136
149
|
- lib/synvert/core/utils.rb
|
@@ -149,7 +162,6 @@ files:
|
|
149
162
|
- spec/synvert/core/rewriter/instance_spec.rb
|
150
163
|
- spec/synvert/core/rewriter/ruby_version_spec.rb
|
151
164
|
- spec/synvert/core/rewriter/scope/goto_scope_spec.rb
|
152
|
-
- spec/synvert/core/rewriter/scope/query_scope_spec.rb
|
153
165
|
- spec/synvert/core/rewriter/scope/within_scope_spec.rb
|
154
166
|
- spec/synvert/core/rewriter/scope_spec.rb
|
155
167
|
- spec/synvert/core/rewriter/warning_spec.rb
|
@@ -194,7 +206,6 @@ test_files:
|
|
194
206
|
- spec/synvert/core/rewriter/instance_spec.rb
|
195
207
|
- spec/synvert/core/rewriter/ruby_version_spec.rb
|
196
208
|
- spec/synvert/core/rewriter/scope/goto_scope_spec.rb
|
197
|
-
- spec/synvert/core/rewriter/scope/query_scope_spec.rb
|
198
209
|
- spec/synvert/core/rewriter/scope/within_scope_spec.rb
|
199
210
|
- spec/synvert/core/rewriter/scope_spec.rb
|
200
211
|
- spec/synvert/core/rewriter/warning_spec.rb
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core
|
4
|
-
# QueryScope finds out nodes by using node query language, then changes its scope to matching node.
|
5
|
-
class Rewriter::QueryScope < Rewriter::Scope
|
6
|
-
# Initialize a QueryScope.
|
7
|
-
#
|
8
|
-
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param nql [String]
|
10
|
-
# @param options [Hash]
|
11
|
-
# @yield run on all matching nodes
|
12
|
-
def initialize(instance, nql, options = {}, &block)
|
13
|
-
super(instance, &block)
|
14
|
-
|
15
|
-
@options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
|
16
|
-
@node_query = NodeQuery.new(nql)
|
17
|
-
end
|
18
|
-
|
19
|
-
# Find out the matching nodes.
|
20
|
-
#
|
21
|
-
# It checks the current node and iterates all child nodes,
|
22
|
-
# then run the block code on each matching node.
|
23
|
-
# @raise [Synvert::Core::NodeQuery::Compiler::ParseError] if the query string is invalid.
|
24
|
-
def process
|
25
|
-
current_node = @instance.current_node
|
26
|
-
return unless current_node
|
27
|
-
|
28
|
-
matching_nodes = @node_query.query_nodes(current_node, @options)
|
29
|
-
@instance.process_with_node(current_node) do
|
30
|
-
matching_nodes.each do |node|
|
31
|
-
@instance.process_with_node(node) do
|
32
|
-
@instance.instance_eval(&@block)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
module Synvert::Core
|
6
|
-
describe Rewriter::QueryScope do
|
7
|
-
let(:instance) {
|
8
|
-
rewriter = Rewriter.new('foo', 'bar')
|
9
|
-
Rewriter::Instance.new(rewriter, 'file pattern')
|
10
|
-
}
|
11
|
-
let(:source) { <<~EOS }
|
12
|
-
describe Post do
|
13
|
-
it 'gets post' do
|
14
|
-
FactoryGirl.create :post
|
15
|
-
end
|
16
|
-
end
|
17
|
-
EOS
|
18
|
-
|
19
|
-
let(:node) { Parser::CurrentRuby.parse(source) }
|
20
|
-
|
21
|
-
before { instance.current_node = node }
|
22
|
-
|
23
|
-
describe '#process' do
|
24
|
-
it 'not call block if no matching node' do
|
25
|
-
run = false
|
26
|
-
scope =
|
27
|
-
described_class.new instance, '.send[message=missing]' do
|
28
|
-
run = true
|
29
|
-
end
|
30
|
-
scope.process
|
31
|
-
expect(run).to be_falsey
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'call block if there is matching node' do
|
35
|
-
run = false
|
36
|
-
type_in_scope = nil
|
37
|
-
scope =
|
38
|
-
described_class.new instance, '.send[receiver=FactoryGirl][message=create][arguments=(:post)]' do
|
39
|
-
run = true
|
40
|
-
type_in_scope = node.type
|
41
|
-
end
|
42
|
-
scope.process
|
43
|
-
expect(run).to be_truthy
|
44
|
-
expect(type_in_scope).to eq :send
|
45
|
-
expect(instance.current_node.type).to eq :block
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'matches multiple block nodes' do
|
49
|
-
block_nodes = []
|
50
|
-
scope =
|
51
|
-
described_class.new(instance, '.block') do
|
52
|
-
block_nodes << node
|
53
|
-
end
|
54
|
-
scope.process
|
55
|
-
expect(block_nodes.size).to eq 2
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'raises InvalidOperatorError' do
|
59
|
-
scope = described_class.new(instance, '.send[receiver IN FactoryGirl]') {}
|
60
|
-
expect {
|
61
|
-
scope.process
|
62
|
-
}.to raise_error(NodeQuery::Compiler::InvalidOperatorError)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|