node_mutation 1.21.4 → 1.21.5

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