node_mutation 1.21.4 → 1.21.6

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: 4c65f57e5d3c315141ac35863689a5391a5c833a794f2f3768f6a12a735f4523
4
- data.tar.gz: 2b1db51fcffc7f7a77a5151b3ee08e07679f6e1e622d884546968c5a50a25aeb
3
+ metadata.gz: 6ae5572567e82e089eefff7f7f696230a17e77fbf0af051dd3a4a46ad21bf9a8
4
+ data.tar.gz: 8448ddd41dadbee697ee58a2d506bd7832fe9792d601e3a969cdc5b8869651fb
5
5
  SHA512:
6
- metadata.gz: aeba2a1cc46bdd0a501701c78f3a93be88d64009d78fba8d616dfb34813ad137168d1f9b51ca40a7aa5e6c1f486db4a507f7ffe95f5c816c5fbd70b20b7320c9
7
- data.tar.gz: 4be674f5fa1abc12c68c0a2f1464465758c8d07523024cb262218d799a96099baace7b340f27044884c67ffbda7e7bcab2e61404e92d92dc753f7eca01fba2f4
6
+ metadata.gz: 603b93346813a1e4a0e6a2fed2c3fb5a0569f592b69de6d3f580b055ad1cae301c03c1984c50e567612f9b9f32b6fe706cd1c8276691b895d387044349c9fb93
7
+ data.tar.gz: 7c2ac5164feb10bbb01d0f355c831032dbccbdb6a80eb341884dc350f33dc95409cec2ced8ead61862fadde4ae71f2244414a43b4cd42ea23b70dc62f1082566
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # NodeMutation
2
2
 
3
+ ## 1.21.6 (2023-11-20)
4
+
5
+ * Flat and sort actions after filtering actions when processing
6
+
7
+ ## 1.21.5 (2023-11-20)
8
+
9
+ * Rewrite the process and test methods
10
+
3
11
  ## 1.21.4 (2023-10-28)
4
12
 
5
13
  * Update `Adapter` rbs
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_mutation (1.21.4)
4
+ node_mutation (1.21.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeMutation
4
- VERSION = "1.21.4"
4
+ VERSION = "1.21.6"
5
5
  end
data/lib/node_mutation.rb CHANGED
@@ -262,20 +262,23 @@ class NodeMutation
262
262
  # if strategy is set to KEEP_RUNNING.
263
263
  # @return {NodeMutation::Result}
264
264
  def process
265
- @actions = flatten_actions(@actions)
266
- if @actions.length == 0
265
+ @actions = optimize_group_actions(@actions)
266
+
267
+ flatten_actions = flat_actions(@actions)
268
+ if flatten_actions.length == 0
267
269
  return NodeMutation::Result.new(affected: false, conflicted: false)
268
270
  end
269
271
 
270
272
  source = +@source
271
273
  @transform_proc.call(@actions) if @transform_proc
272
- sort_actions!(@actions)
273
- conflict_actions = get_conflict_actions(@actions)
274
+ sorted_actions = sort_flatten_actions(flatten_actions)
275
+ conflict_actions = get_conflict_actions(sorted_actions)
274
276
  if conflict_actions.size > 0 && strategy?(Strategy::THROW_ERROR)
275
277
  raise ConflictActionError, "mutation actions are conflicted"
276
278
  end
277
279
 
278
- new_source = rewrite_source(source, @actions)
280
+ actions = sort_flatten_actions(flat_actions(get_filter_actions(conflict_actions)))
281
+ new_source = rewrite_source(source, actions)
279
282
  result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
280
283
  result.new_source = new_source
281
284
  result
@@ -289,63 +292,79 @@ class NodeMutation
289
292
  # if strategy is set to KEEP_RUNNING.
290
293
  # @return {NodeMutation::Result}
291
294
  def test
292
- @actions = flatten_actions(@actions)
293
- if @actions.length == 0
295
+ @actions = optimize_group_actions(@actions)
296
+
297
+ flatten_actions = flat_actions(@actions)
298
+ if flatten_actions.length == 0
294
299
  return NodeMutation::Result.new(affected: false, conflicted: false)
295
300
  end
296
301
 
297
302
  @transform_proc.call(@actions) if @transform_proc
298
- sort_actions!(@actions)
299
- conflict_actions = get_conflict_actions(@actions)
303
+ sorted_actions = sort_flatten_actions(flatten_actions)
304
+ conflict_actions = get_conflict_actions(sorted_actions)
300
305
  if conflict_actions.size > 0 && strategy?(Strategy::THROW_ERROR)
301
306
  raise ConflictActionError, "mutation actions are conflicted"
302
307
  end
303
308
 
304
309
  result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
305
- result.actions = @actions.map(&:to_struct)
310
+ actions = sort_actions(get_filter_actions(conflict_actions))
311
+ result.actions = actions.map(&:to_struct)
306
312
  result
307
313
  end
308
314
 
309
315
  private
310
316
 
311
- # It flattens a series of actions by removing any GroupAction
317
+ # Optimizes a list of actions, recursively optimizing any nested group actions.
318
+ # @param actions [Array<NodeMutation::Action>]
319
+ # @return [Array<NodeMutation::Action>] optimized actions
320
+ def optimize_group_actions(actions)
321
+ actions.map do |action|
322
+ if action.is_a?(GroupAction)
323
+ # If the group action contains only one action, replace the group action with that action
324
+ if action.actions.length === 1
325
+ return optimize_group_actions(action.actions)
326
+ end
327
+
328
+ # If the group action contains more than one action, optimize its sub-actions
329
+ action.actions = optimize_group_actions(action.actions)
330
+ end
331
+ action
332
+ end
333
+ end
334
+
335
+ # It flats a series of actions by removing any GroupAction
312
336
  # objects that contain only a single action. This is done recursively.
313
- def flatten_actions(actions)
314
- new_actions = []
337
+ # @param actions [Array<NodeMutation::Action>]
338
+ # @return [Array<NodeMutation::Action>] flatten actions
339
+ def flat_actions(actions)
340
+ flatten_actions = []
315
341
  actions.each do |action|
316
342
  if action.is_a?(GroupAction)
317
- new_actions << flatten_group_action(action)
343
+ flatten_actions += flat_actions(action.actions)
318
344
  else
319
- new_actions << action
345
+ flatten_actions << action
320
346
  end
321
347
  end
322
- new_actions.compact
348
+ flatten_actions
323
349
  end
324
350
 
325
- # It flattens a group action.
326
- def flatten_group_action(action)
327
- if action.actions.empty?
328
- nil
329
- elsif action.actions.size == 1
330
- if action.actions.first.is_a?(GroupAction)
331
- flatten_group_action(action.actions.first)
332
- else
333
- action.actions.first
351
+ # Recusively sort actions by start position and end position.
352
+ # @param actions [Array<NodeMutation::Action>]
353
+ # @return [Array<NodeMutation::Action>] sorted actions
354
+ def sort_actions(actions)
355
+ actions.each do |action|
356
+ if action.is_a?(GroupAction)
357
+ action.actions = sort_actions(action.actions)
334
358
  end
335
- else
336
- action.actions = flatten_actions(action.actions)
337
- action
338
359
  end
360
+ actions.sort_by { |action| [action.start, action.end] }
339
361
  end
340
362
 
341
363
  # Sort actions by start position and end position.
342
364
  # @param actions [Array<NodeMutation::Action>]
343
365
  # @return [Array<NodeMutation::Action>] sorted actions
344
- def sort_actions!(actions)
345
- actions.sort_by! { |action| [action.start, action.end] }
346
- actions.each do |action|
347
- sort_actions!(action.actions) if action.is_a?(GroupAction)
348
- end
366
+ def sort_flatten_actions(flatten_actions)
367
+ flatten_actions.sort_by { |action| [action.start, action.end] }
349
368
  end
350
369
 
351
370
  # Rewrite source code with actions.
@@ -365,6 +384,8 @@ class NodeMutation
365
384
 
366
385
  # It changes source code from bottom to top, and it can change source code twice at the same time,
367
386
  # So if there is an overlap between two actions, it removes the conflict actions and operate them in the next loop.
387
+ # @param actions [Array<NodeMutation::Action>]
388
+ # @return [Array<NodeMutation::Action>] conflict actions
368
389
  def get_conflict_actions(actions)
369
390
  i = actions.length - 1
370
391
  j = i - 1
@@ -376,7 +397,7 @@ class NodeMutation
376
397
  while j > -1
377
398
  # if we have two actions with overlapped range.
378
399
  if begin_pos < actions[j].end
379
- conflict_actions << actions.delete_at(j)
400
+ conflict_actions << actions[j]
380
401
  else
381
402
  i = j
382
403
  begin_pos = actions[i].start
@@ -384,12 +405,22 @@ class NodeMutation
384
405
  end
385
406
  j -= 1
386
407
  end
387
- actions.each do |action|
388
- conflict_actions.concat(get_conflict_actions(action.actions)) if action.is_a?(GroupAction)
389
- end
390
408
  conflict_actions
391
409
  end
392
410
 
411
+ # It filters conflict actions from actions.
412
+ # @param actions [Array<NodeMutation::Action>]
413
+ # @return [Array<NodeMutation::Action>] filtered actions
414
+ def get_filter_actions(conflict_actions)
415
+ @actions.select do |action|
416
+ if action.is_a?(GroupAction)
417
+ action.actions.all? { |child_action| !conflict_actions.include?(child_action) }
418
+ else
419
+ !conflict_actions.include?(action)
420
+ end
421
+ end
422
+ end
423
+
393
424
  def strategy?(strategy)
394
425
  NodeMutation.strategy & strategy == strategy
395
426
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: node_mutation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.4
4
+ version: 1.21.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-28 00:00:00.000000000 Z
11
+ date: 2023-11-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: ast node mutation apis
14
14
  email: