node_mutation 1.21.3 → 1.21.5

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: 2db42bf57c1ecb342033989ea018607b34f25647565ad8db86d44cb0f0713b10
4
- data.tar.gz: 9ab4cad235711dee0ff3c60a8547a0fa68bff99f47a12b331091a88c03edd08b
3
+ metadata.gz: f1148a4464a8b1f52500b09be2581a61c0add079b55052ced0e92297885f7082
4
+ data.tar.gz: c8e779f8ab34b515c7c991a0b16c3a4aa85c280841fa65d021a1d4fd6a49ec25
5
5
  SHA512:
6
- metadata.gz: 5f9efba9693d6792033c04ef34313f2effed85b0f4f7392a6c669d71e383520420faa258f44dd7e72252785c60bbdb4cfe0e109af3e489a1046174f8370dc8c3
7
- data.tar.gz: cd092b7e5babc2bf96f8fbd7b9009ef0b39ba056e68d9db92f4e175568e040465ce3da636a423674ade58a57621f03b86af35ee8ac38d5f82fc9d938956dc70f
6
+ metadata.gz: 662faf8ca577ab83503429153c5af550a4a3134a8138e4f36400aa6fcfb40b27de367c5a837af6dd6a139fe63627f3343d11d5573e2ae0501d0cfaf25fb8adb3
7
+ data.tar.gz: deda4075371317fd3c5decfda04bb8752b38f37679c21e1d940f1ebb2ef775f945ee38956ebea0e78717eb386e3dccaf5ff3b76fb50f550e616a246a880e43d6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # NodeMutation
2
2
 
3
+ ## 1.21.5 (2023-11-20)
4
+
5
+ * Rewrite the process and test methods
6
+
7
+ ## 1.21.4 (2023-10-28)
8
+
9
+ * Update `Adapter` rbs
10
+
3
11
  ## 1.21.3 (2023-10-03)
4
12
 
5
13
  * Call `Action#to_struct` explicitly
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_mutation (1.21.3)
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.3"
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
@@ -7,13 +7,13 @@ class NodeMutation::Adapter[T]
7
7
 
8
8
  def child_node_range: (node: T, child_name: String) -> NodeMutation::Struct::Range
9
9
 
10
- def get_start: (node: T) -> Integer
10
+ def get_start: (node: T, ?child_name: String) -> Integer
11
11
 
12
- def get_end: (node: T) -> Integer
12
+ def get_end: (node: T, ?child_name: String) -> Integer
13
13
 
14
- def get_start_loc: (node: T) -> NodeMutation::Struct::Location
14
+ def get_start_loc: (node: T, ?child_name: String) -> NodeMutation::Struct::Location
15
15
 
16
- def get_end_loc: (node: T) -> NodeMutation::Struct::Location
16
+ def get_end_loc: (node: T, ?child_name: String) -> NodeMutation::Struct::Location
17
17
 
18
18
  def get_indent: (node: T) -> Integer
19
19
  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.3
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-02 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: