synvert-core 1.11.0 → 1.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0663ba61695ae5b47f27e9a23f1edbfe31d3746f9b3e02a79315a827fae6f36c
4
- data.tar.gz: 8199c6c8a122555bfbf0df0ef79f6bd96ade0cdfe472d81d6abe4cccde3b6c59
3
+ metadata.gz: d3d907ab2e51c1861a28d12934cf453f63df79fc23e072c1005013c5f9b137be
4
+ data.tar.gz: 16e8425a70a74b779b36265eec12aacca4b6073e5911052b0114726a740f6e99
5
5
  SHA512:
6
- metadata.gz: 3609b9bdb845681c9dd71d9d0eca4985d43203ce28fb1e874e9538322f8205995d77f5b8c2b43fb11caf698a69772c3e7bdd5114a709e4513313339870576a5e
7
- data.tar.gz: 952578268a2c8cba6dcd2883141fe5977917594ea01b76e51e93032fc71225c813b9021ec1852c3a93d76f6438f30f9975ac47b36c5da3d7c5805fa15763fa9e
6
+ metadata.gz: 3a73e71ccb24cbdf40fe515fcb732e242e27e5dbac5b130bc9e88d19b8c3ef315cc7c3e00195d3d4e15f6a24bd4fb89336686ae379451e3fa7433548bd3402c8
7
+ data.tar.gz: c6e026527d96e8766a330626c330d280c6ab650834e71b56c64c4cf81a4dd7d0911d89919c16e0f651208e0d0ce1c9c3b36f6c08f4c9f5f7d04d0af4849a713d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.13.0 (2022-10-17)
4
+
5
+ * Add `insert_before` dsl
6
+ * Update `insert_after` to reuse `NodeMutation#insert`
7
+
8
+ ## 1.12.0 (2022-10-14)
9
+
10
+ * Condition accepts both nql and rules
11
+ * Make `find_node` as an alias to `within_node`
12
+ * Remove skip files only once
13
+
3
14
  ## 1.11.0 (2022-10-11)
4
15
 
5
16
  * Add `Configuration.number_of_workers`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- synvert-core (1.11.0)
4
+ synvert-core (1.13.0)
5
5
  activesupport (< 7.0.0)
6
6
  erubis
7
7
  node_mutation
@@ -50,10 +50,10 @@ GEM
50
50
  method_source (1.0.0)
51
51
  minitest (5.16.3)
52
52
  nenv (0.3.0)
53
- node_mutation (1.4.4)
53
+ node_mutation (1.5.0)
54
54
  activesupport (< 7.0.0)
55
55
  erubis
56
- node_query (1.7.0)
56
+ node_query (1.8.1)
57
57
  activesupport (< 7.0.0)
58
58
  notiffany (0.1.3)
59
59
  nenv (~> 0.1)
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
 
@@ -90,6 +90,7 @@ Actions:
90
90
  * [prepend](./Synvert/Core/Rewriter/Instance.html#prepend-instance_method) - prepend the code to the bottom of current node body
91
91
  * [insert](./Synvert/Core/Rewriter/Instance.html#insert-instance_method) - insert code
92
92
  * [insert_after](./Synvert/Core/Rewriter/Instance.html#insert_after-instance_method) - insert the code next to the current node
93
+ * [insert_before](./Synvert/Core/Rewriter/Instance.html#insert_before-instance_method) - insert the code previous to the current node
93
94
  * [replace](./Synvert/Core/Rewriter/Instance.html#replace-instance_method) - replace the code of specified child nodes
94
95
  * [delete](./Synvert/Core/Rewriter/Instance.html#delete-instance_method) - delete the code specified child nodes
95
96
  * [wrap](./Synvert/Core/Rewriter/Instance.html#wrap-instance_method) - wrap the current node with code
@@ -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
 
@@ -85,38 +85,29 @@ module Synvert::Core
85
85
  # DSL #
86
86
  #######
87
87
 
88
- # Parse +find_node+ dsl, it creates {Synvert::Core::Rewriter::QueryScope} to recursively find matching ast nodes,
89
- # then continue operating on each matching ast node.
90
- # @example
91
- # # matches FactoryBot.create(:user)
92
- # find_node '.send[receiver=FactoryBot][message=create][arguments.size=1]' do
93
- # end
94
- # @param nql [String] node query language to find matching ast nodes.
95
- # @yield run on the matching nodes.
96
- # @raise [Synvert::Core::NodeQuery::Compiler::ParseError] if query string is invalid.
97
- def find_node(nql, options = {}, &block)
98
- Rewriter::QueryScope.new(self, nql, options, &block).process
99
- rescue NodeQueryLexer::ScanError, Racc::ParseError => e
100
- raise NodeQuery::Compiler::ParseError, "Invalid query string: #{nql}"
101
- end
102
-
103
88
  # Parse +within_node+ dsl, it creates a {Synvert::Core::Rewriter::WithinScope} to recursively find matching ast nodes,
104
89
  # then continue operating on each matching ast node.
105
90
  # @example
106
91
  # # matches User.find_by_login('test')
107
92
  # with_node type: 'send', message: /^find_by_/ do
108
93
  # end
109
- # @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.
110
98
  # @param options [Hash] optional
111
99
  # @option including_self [Boolean] set if query the current node, default is true
112
100
  # @option stop_at_first_match [Boolean] set if stop at first match, default is false
113
101
  # @option recursive [Boolean] set if recursively query child nodes, default is true
114
102
  # @yield run on the matching nodes.
115
- def within_node(rules, options = {}, &block)
116
- 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}"
117
107
  end
118
108
 
119
109
  alias with_node within_node
110
+ alias find_node within_node
120
111
 
121
112
  # Parse +goto_node+ dsl, it creates a {Synvert::Core::Rewriter::GotoScope} to go to a child node,
122
113
  # then continue operating on the child node.
@@ -140,10 +131,10 @@ module Synvert::Core
140
131
  # if_exist_node type: 'send', message: 'any_instance' do
141
132
  # end
142
133
  # end
143
- # @param rules [Hash] rules to check mathing ast nodes.
134
+ # @param nql_or_rules [String|Hash] nql or rules to check mathing ast nodes.
144
135
  # @param block [Block] block code to continue operating on the matching nodes.
145
- def if_exist_node(rules, &block)
146
- 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
147
138
  end
148
139
 
149
140
  # Parse +unless_exist_node+ dsl, it creates a {Synvert::Core::Rewriter::UnlessExistCondition} to check
@@ -154,14 +145,14 @@ module Synvert::Core
154
145
  # unless_exist_node type: 'send', message: 'any_instance' do
155
146
  # end
156
147
  # end
157
- # @param rules [Hash] rules to check mathing ast nodes.
148
+ # @param nql_or_rules [String|Hash] nql or rules to check mathing ast nodes.
158
149
  # @param block [Block] block code to continue operating on the matching nodes.
159
- def unless_exist_node(rules, &block)
160
- 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
161
152
  end
162
153
 
163
154
  # Parse +if_only_exist_node+ dsl, it creates a {Synvert::Core::Rewriter::IfOnlyExistCondition} to check
164
- # 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,
165
156
  # if so, then continue operating on each matching ast node.
166
157
  # @example
167
158
  # # it { should matcher }
@@ -169,14 +160,13 @@ module Synvert::Core
169
160
  # if_only_exist_node type: 'send', receiver: nil, message: 'should' do
170
161
  # end
171
162
  # end
172
- # @param rules [Hash] rules to check mathing ast nodes.
163
+ # @param nql_or_rules [String|Hash] nql or rules to check mathing ast nodes.
173
164
  # @param block [Block] block code to continue operating on the matching nodes.
174
- def if_only_exist_node(rules, &block)
175
- 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
176
167
  end
177
168
 
178
- # Parse +append+ dsl, it creates a {Synvert::Core::Rewriter::AppendAction} to
179
- # append the code to the bottom of current node body.
169
+ # Parse +append+ dsl, it appends the code to the bottom of current node body.
180
170
  # @example
181
171
  # # def teardown
182
172
  # # clean_something
@@ -194,8 +184,7 @@ module Synvert::Core
194
184
  @current_mutation.append(@current_node, code)
195
185
  end
196
186
 
197
- # Parse +prepend+ dsl, it creates a {Synvert::Core::Rewriter::PrependAction} to
198
- # prepend the code to the top of current node body.
187
+ # Parse +prepend+ dsl, it prepends the code to the top of current node body.
199
188
  # @example
200
189
  # # def setup
201
190
  # # do_something
@@ -213,7 +202,7 @@ module Synvert::Core
213
202
  @current_mutation.prepend(@current_node, code)
214
203
  end
215
204
 
216
- # Parse +insert+ dsl, it creates a {Synvert::Core::Rewriter::InsertAction} to insert code.
205
+ # Parse +insert+ dsl, it inserts code.
217
206
  # @example
218
207
  # # open('http://test.com')
219
208
  # # =>
@@ -228,8 +217,7 @@ module Synvert::Core
228
217
  @current_mutation.insert(@current_node, code, at: at, to: to)
229
218
  end
230
219
 
231
- # Parse +insert_after+ dsl, it creates a {Synvert::Core::Rewriter::InsertAfterAction} to
232
- # insert the code next to the current node.
220
+ # Parse +insert_after+ dsl, it inserts the code next to the current node.
233
221
  # @example
234
222
  # # Synvert::Application.config.secret_token = "0447aa931d42918bfb934750bb78257088fb671186b5d1b6f9fddf126fc8a14d34f1d045cefab3900751c3da121a8dd929aec9bafe975f1cabb48232b4002e4e"
235
223
  # # =>
@@ -240,11 +228,26 @@ module Synvert::Core
240
228
  # end
241
229
  # @param code [String] code need to be inserted.
242
230
  def insert_after(code)
243
- @current_mutation.insert_after(@current_node, code)
231
+ column = ' ' * NodeMutation.adapter.get_start_loc(@current_node).column
232
+ @current_mutation.insert(@current_node, "\n#{column}#{code}", { at: 'end' })
244
233
  end
245
234
 
246
- # Parse +replace_erb_stmt_with_expr+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction} to
247
- # replace erb stmt code to expr code.
235
+ # Parse +insert_before+ dsl, it inserts the code previous to the current node.
236
+ # @example
237
+ # # Synvert::Application.config.secret_token = "0447aa931d42918bfb934750bb78257088fb671186b5d1b6f9fddf126fc8a14d34f1d045cefab3900751c3da121a8dd929aec9bafe975f1cabb48232b4002e4e"
238
+ # # =>
239
+ # # Synvert::Application.config.secret_key_base = "bf4f3f46924ecd9adcb6515681c78144545bba454420973a274d7021ff946b8ef043a95ca1a15a9d1b75f9fbdf85d1a3afaf22f4e3c2f3f78e24a0a188b581df"
240
+ # # Synvert::Application.config.secret_token = "0447aa931d42918bfb934750bb78257088fb671186b5d1b6f9fddf126fc8a14d34f1d045cefab3900751c3da121a8dd929aec9bafe975f1cabb48232b4002e4e"
241
+ # with_node type: 'send', message: 'secret_token=' do
242
+ # insert_before "{{receiver}}.secret_key_base = \"#{SecureRandom.hex(64)}\""
243
+ # end
244
+ # @param code [String] code need to be inserted.
245
+ def insert_before(code)
246
+ column = ' ' * NodeMutation.adapter.get_start_loc(@current_node).column
247
+ @current_mutation.insert(@current_node, "#{code}\n#{column}", { at: 'beginning' })
248
+ end
249
+
250
+ # Parse +replace_erb_stmt_with_expr+ dsl, it replaces erb stmt code to expr code.
248
251
  # @example
249
252
  # # <% form_for post do |f| %>
250
253
  # # <% end %>
@@ -258,8 +261,7 @@ module Synvert::Core
258
261
  @current_mutation.actions << Rewriter::ReplaceErbStmtWithExprAction.new(@current_node).process
259
262
  end
260
263
 
261
- # Parse +replace_with+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceWithAction} to
262
- # replace the whole code of current node.
264
+ # Parse +replace_with+ dsl, it replaces the whole code of current node.
263
265
  # @example
264
266
  # # obj.stub(:foo => 1, :bar => 2)
265
267
  # # =>
@@ -272,8 +274,7 @@ module Synvert::Core
272
274
  @current_mutation.replace_with(@current_node, code)
273
275
  end
274
276
 
275
- # Parse +replace+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceAction} to
276
- # replace the code of specified child nodes.
277
+ # Parse +replace+ dsl, it replaces the code of specified child nodes.
277
278
  # @example
278
279
  # # assert(object.empty?)
279
280
  # # =>
@@ -288,7 +289,7 @@ module Synvert::Core
288
289
  @current_mutation.replace(@current_node, *selectors, with: with)
289
290
  end
290
291
 
291
- # Parse +remove+ dsl, it creates a {Synvert::Core::Rewriter::RemoveAction} to remove current node.
292
+ # Parse +remove+ dsl, it removes current node.
292
293
  # @example
293
294
  # with_node type: 'send', message: { in: %w[puts p] } do
294
295
  # remove
@@ -299,7 +300,7 @@ module Synvert::Core
299
300
  @current_mutation.remove(@current_node, **options)
300
301
  end
301
302
 
302
- # Parse +delete+ dsl, it creates a {Synvert::Core::Rewriter::DeleteAction} to delete child nodes.
303
+ # Parse +delete+ dsl, it deletes child nodes.
303
304
  # @example
304
305
  # # FactoryBot.create(...)
305
306
  # # =>
@@ -314,8 +315,7 @@ module Synvert::Core
314
315
  @current_mutation.delete(@current_node, *selectors, **options)
315
316
  end
316
317
 
317
- # Parse +wrap+ dsl, it creates a {Synvert::Core::Rewriter::WrapAction} to
318
- # wrap current node with code.
318
+ # Parse +wrap+ dsl, it wraps current node with code.
319
319
  # @example
320
320
  # # class Foobar
321
321
  # # end
@@ -434,16 +434,16 @@ module Synvert::Core
434
434
  only_paths.flat_map do |only_path|
435
435
  @file_patterns.flat_map do |file_pattern|
436
436
  pattern = only_path == "." ? file_pattern : File.join(only_path, file_pattern)
437
- Dir.glob(pattern) - get_skip_files
437
+ Dir.glob(pattern)
438
438
  end
439
- end
439
+ end - get_skip_files
440
440
  end
441
441
  end
442
442
 
443
443
  # Get skip files.
444
444
  # @return [Array<String>] skip files
445
445
  def get_skip_files
446
- @skip_files ||= Configuration.skip_paths.flat_map do |skip_path|
446
+ Configuration.skip_paths.flat_map do |skip_path|
447
447
  if File.directory?(skip_path)
448
448
  Dir.glob(File.join(skip_path, "**/*"))
449
449
  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.11.0'
5
+ VERSION = '1.13.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
@@ -127,10 +127,19 @@ module Synvert::Core
127
127
  it 'parses insert_after' do
128
128
  instance.current_mutation = double
129
129
  instance.current_node = double
130
- expect(instance.current_mutation).to receive(:insert_after).with(instance.current_node, 'Foobar')
130
+ expect(NodeMutation).to receive_message_chain(:adapter, :get_start_loc, :column).and_return(2)
131
+ expect(instance.current_mutation).to receive(:insert).with(instance.current_node, "\n Foobar", at: 'end')
131
132
  instance.insert_after 'Foobar'
132
133
  end
133
134
 
135
+ it 'parses insert_before' do
136
+ instance.current_mutation = double
137
+ instance.current_node = double
138
+ expect(NodeMutation).to receive_message_chain(:adapter, :get_start_loc, :column).and_return(2)
139
+ expect(instance.current_mutation).to receive(:insert).with(instance.current_node, "Foobar\n ", at: 'beginning')
140
+ instance.insert_before 'Foobar'
141
+ end
142
+
134
143
  it 'parses replace_erb_stmt_with_expr' do
135
144
  instance.current_mutation = double
136
145
  instance.current_node = double
@@ -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
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.11.0
4
+ version: 1.13.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 00:00:00.000000000 Z
11
+ date: 2022-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -144,7 +144,6 @@ files:
144
144
  - lib/synvert/core/rewriter/ruby_version.rb
145
145
  - lib/synvert/core/rewriter/scope.rb
146
146
  - lib/synvert/core/rewriter/scope/goto_scope.rb
147
- - lib/synvert/core/rewriter/scope/query_scope.rb
148
147
  - lib/synvert/core/rewriter/scope/within_scope.rb
149
148
  - lib/synvert/core/rewriter/warning.rb
150
149
  - lib/synvert/core/utils.rb
@@ -163,7 +162,6 @@ files:
163
162
  - spec/synvert/core/rewriter/instance_spec.rb
164
163
  - spec/synvert/core/rewriter/ruby_version_spec.rb
165
164
  - spec/synvert/core/rewriter/scope/goto_scope_spec.rb
166
- - spec/synvert/core/rewriter/scope/query_scope_spec.rb
167
165
  - spec/synvert/core/rewriter/scope/within_scope_spec.rb
168
166
  - spec/synvert/core/rewriter/scope_spec.rb
169
167
  - spec/synvert/core/rewriter/warning_spec.rb
@@ -208,7 +206,6 @@ test_files:
208
206
  - spec/synvert/core/rewriter/instance_spec.rb
209
207
  - spec/synvert/core/rewriter/ruby_version_spec.rb
210
208
  - spec/synvert/core/rewriter/scope/goto_scope_spec.rb
211
- - spec/synvert/core/rewriter/scope/query_scope_spec.rb
212
209
  - spec/synvert/core/rewriter/scope/within_scope_spec.rb
213
210
  - spec/synvert/core/rewriter/scope_spec.rb
214
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