synvert-core 1.10.1 → 1.12.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: 966c0db8262c57bb94be47d44c5638c9c9607728da335b4bde9d39c49f7bc665
4
- data.tar.gz: e2be9da04e58da3b236d03006883778f6e202d9bbb5a8fa922dd6339117a6a2a
3
+ metadata.gz: e526dbe6f12418da40df7cb5b945f7ed957820573455b575f2a609c334b58e72
4
+ data.tar.gz: 1f22528b636b548c9ddb05466d366e62dce813794d173c11b8de11ef522b97a8
5
5
  SHA512:
6
- metadata.gz: 1e1f6a8a25817ebe46c03bdbf6e7982f559c426bf5537c2ae28549215ad77a03c45768af6b3f74ba84e34105c6d1e8c9cbb365cb1f431220b59028678c373dcd
7
- data.tar.gz: 44f57f854c537825acb57217b216294f226df391b1eb185fd1558f463084a91ad9fcc296f54eba05c5b66e1d995a40c897d267fff662ff5bf85472d83d993be1
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.10.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 rules
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
- attr_writer :root_path, :skip_paths, :only_paths, :show_run_process
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
@@ -5,7 +5,7 @@ module Synvert::Core
5
5
  class Rewriter::IfExistCondition < Rewriter::Condition
6
6
  private
7
7
 
8
- # check if any child node matches the rules.
8
+ # check if any child node matches.
9
9
  #
10
10
  # @return [Boolean]
11
11
  def match?
@@ -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 rules.
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 rules.
8
+ # check if only have one child node and the child node matches.
9
9
  #
10
10
  # @return [Boolean]
11
11
  def match?
@@ -5,7 +5,7 @@ module Synvert::Core
5
5
  class Rewriter::UnlessExistCondition < Rewriter::Condition
6
6
  private
7
7
 
8
- # check if none of child node matches the rules.
8
+ # check if none of 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 rules [Hash]
9
+ # @param nql_or_rules [String|Hash]
10
10
  # @yield run when condition matches
11
- def initialize(instance, rules, &block)
11
+ def initialize(instance, nql_or_rules, &block)
12
12
  @instance = instance
13
- @node_query = NodeQuery.new(rules)
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
- get_file_paths.map do |file_path|
45
- test_file(file_path)
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
- # @param rules [Hash] rules to find mathing ast nodes.
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(rules, options = {}, &block)
109
- Rewriter::WithinScope.new(self, rules, options, &block).process
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 rules [Hash] rules to check mathing ast nodes.
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(rules, &block)
139
- Rewriter::IfExistCondition.new(self, rules, &block).process
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 rules [Hash] rules to check mathing ast nodes.
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(rules, &block)
153
- Rewriter::UnlessExistCondition.new(self, rules, &block).process
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 rules,
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 rules [Hash] rules to check mathing ast nodes.
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(rules, &block)
168
- Rewriter::IfOnlyExistCondition.new(self, rules, &block).process
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) - get_skip_files
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
- @skip_files ||= Configuration.skip_paths.flat_map do |skip_path|
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 rules [Hash]
9
+ # @param nql_or_rules [String|Hash]
10
10
  # @param options [Hash]
11
11
  # @yield run on all matching nodes
12
- def initialize(instance, rules, options = {}, &block)
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(rules)
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
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '1.10.1'
5
+ VERSION = '1.12.0'
6
6
  end
7
7
  end
@@ -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::QueryScope).to receive(:new).with(instance, '.send[message=create]', {}, &block).and_return(scope)
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
- it 'not call block if no matching node' do
27
- run = false
28
- scope =
29
- Rewriter::WithinScope.new instance, type: 'send', message: 'missing' do
30
- run = true
31
- end
32
- scope.process
33
- expect(run).to be_falsey
34
- end
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
- it 'call block if there is matching node' do
37
- run = false
38
- type_in_scope = nil
39
- scope =
40
- Rewriter::WithinScope.new instance,
41
- type: 'send',
42
- receiver: 'FactoryGirl',
43
- message: 'create',
44
- arguments: [':user'] do
45
- run = true
46
- type_in_scope = node.type
47
- end
48
- scope.process
49
- expect(run).to be_truthy
50
- expect(type_in_scope).to eq :send
51
- expect(instance.current_node.type).to eq :block
52
- end
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
- it 'matches multiple block nodes' do
55
- block_nodes = []
56
- scope =
57
- Rewriter::WithinScope.new(instance, { type: 'block' }) do
58
- block_nodes << node
59
- end
60
- scope.process
61
- expect(block_nodes.size).to eq 3
62
- end
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
- it 'matches only 2 block nodes if including_self is false' do
65
- block_nodes = []
66
- scope =
67
- Rewriter::WithinScope.new(instance, { type: 'block' }, { including_self: false }) do
68
- block_nodes << node
69
- end
70
- scope.process
71
- expect(block_nodes.size).to eq 2
72
- end
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
- it 'matches only one block node if recursive is false' do
75
- block_nodes = []
76
- scope =
77
- Rewriter::WithinScope.new(instance, { type: 'block' }, { recursive: false }) do
78
- block_nodes << node
79
- end
80
- scope.process
81
- expect(block_nodes.size).to eq 1
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
- it 'matches only one block node if stop_at_first_match is true' do
85
- block_nodes = []
86
- scope =
87
- Rewriter::WithinScope.new(instance, { type: 'block' }, { stop_at_first_match: true }) do
88
- block_nodes << node
89
- end
90
- scope.process
91
- expect(block_nodes.size).to eq 1
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
@@ -25,4 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency "node_mutation"
26
26
  spec.add_runtime_dependency "parser"
27
27
  spec.add_runtime_dependency "parser_node_ext"
28
+ spec.add_runtime_dependency "parallel"
28
29
  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: 1.10.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-09 00:00:00.000000000 Z
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