synvert-core 1.11.0 → 1.13.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: 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