node_mutation 1.21.5 → 1.22.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: f1148a4464a8b1f52500b09be2581a61c0add079b55052ced0e92297885f7082
4
- data.tar.gz: c8e779f8ab34b515c7c991a0b16c3a4aa85c280841fa65d021a1d4fd6a49ec25
3
+ metadata.gz: d1ced556aff645a4d23e98bc7d544ac8d48d89909112fbd875132a97417a7e2b
4
+ data.tar.gz: 9efd16a9ff97cb146b0b3750a53a57721700377d98a9e8c310a9435d6c42d279
5
5
  SHA512:
6
- metadata.gz: 662faf8ca577ab83503429153c5af550a4a3134a8138e4f36400aa6fcfb40b27de367c5a837af6dd6a139fe63627f3343d11d5573e2ae0501d0cfaf25fb8adb3
7
- data.tar.gz: deda4075371317fd3c5decfda04bb8752b38f37679c21e1d940f1ebb2ef775f945ee38956ebea0e78717eb386e3dccaf5ff3b76fb50f550e616a246a880e43d6
6
+ metadata.gz: 0337aee07465f0c897bf23180b6f114a3e1aa08b580040ab787e7df36f69947d8f68b644235fce64b1ea78db44aae8d2e58d5e9349b783c02a8d1499f7514507
7
+ data.tar.gz: c8fdcf2857e1dfddcf36653dddcf48e6d19a10d7d9f99994a7551c9e146dd034e80576e0bf1b58d3b8aad784a11e1edd858ad9e9dae3b9122723c8242122f768
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # NodeMutation
2
2
 
3
+ ## 1.22.0 (2023-11-27)
4
+
5
+ * Add `adapter` parameter to `NodeMutation`
6
+ * Add `adapter` parameter to `NodeMutation::Action`
7
+ * Do not allow to configure an `adapter` globally
8
+
9
+ ## 1.21.6 (2023-11-20)
10
+
11
+ * Flat and sort actions after filtering actions when processing
12
+
3
13
  ## 1.21.5 (2023-11-20)
4
14
 
5
15
  * Rewrite the process and test methods
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_mutation (1.21.5)
4
+ node_mutation (1.22.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -25,7 +25,7 @@ Or install it yourself as:
25
25
  ```ruby
26
26
  require 'node_mutation'
27
27
 
28
- mutation = NodeMutation.new(source)
28
+ mutation = NodeMutation.new(source, adapter: :parser)
29
29
  ```
30
30
 
31
31
  2. call the rewrite apis:
@@ -91,10 +91,6 @@ Different parsers, like parse and ripper, will generate different AST nodes, to
91
91
  we define an [Adapter](https://github.com/xinminlabs/node-mutation-ruby/blob/main/lib/node_mutation/adapter.rb) interface,
92
92
  if you implement the Adapter interface, you can set it as NodeMutation's adapter.
93
93
 
94
- ```ruby
95
- NodeMutation.configure(adapter: SyntaxTreeAdapter.new) // default is ParserAdapter
96
- ```
97
-
98
94
  ### strategy
99
95
 
100
96
  It provides 3 strategies to handle conflicts when processing actions:
@@ -2,8 +2,13 @@
2
2
 
3
3
  # AppendAction appends code to the bottom of node body.
4
4
  class NodeMutation::AppendAction < NodeMutation::Action
5
- def initialize(node, code)
6
- super(node, code)
5
+ # Initialize an AppendAction.
6
+ #
7
+ # @param node [Node]
8
+ # @param code [String] new code to append.
9
+ # @param adapter [NodeMutation::Adapter]
10
+ def initialize(node, code, adapter:)
11
+ super(node, code, adapter: adapter)
7
12
  @type = :insert
8
13
  end
9
14
 
@@ -13,7 +18,7 @@ class NodeMutation::AppendAction < NodeMutation::Action
13
18
 
14
19
  # Calculate the begin the end positions.
15
20
  def calculate_position
16
- @start = NodeMutation.adapter.get_end(@node) - NodeMutation.adapter.get_start_loc(@node).column - END_LENGTH
21
+ @start = @adapter.get_end(@node) - @adapter.get_start_loc(@node).column - END_LENGTH
17
22
  @end = @start
18
23
  end
19
24
 
@@ -22,6 +27,6 @@ class NodeMutation::AppendAction < NodeMutation::Action
22
27
  # @param node [Parser::AST::Node]
23
28
  # @return [String] n times whitesphace
24
29
  def indent(node)
25
- ' ' * (NodeMutation.adapter.get_start_loc(node).column + NodeMutation.tab_width)
30
+ ' ' * (@adapter.get_start_loc(node).column + NodeMutation.tab_width)
26
31
  end
27
32
  end
@@ -6,9 +6,10 @@ class NodeMutation::DeleteAction < NodeMutation::Action
6
6
  #
7
7
  # @param node [Node]
8
8
  # @param selectors [Array<Symbol, String>] used to select child nodes
9
- # @option and_comma [Boolean] delete extra comma.
10
- def initialize(node, *selectors, and_comma: false)
11
- super(node, nil)
9
+ # @param and_comma [Boolean] delete extra comma.
10
+ # @param adapter [NodeMutation::Adapter]
11
+ def initialize(node, *selectors, adapter:, and_comma: false)
12
+ super(node, nil, adapter: adapter)
12
13
  @selectors = selectors
13
14
  @and_comma = and_comma
14
15
  @type = :delete
@@ -23,9 +24,9 @@ class NodeMutation::DeleteAction < NodeMutation::Action
23
24
 
24
25
  # Calculate the begin and end positions.
25
26
  def calculate_position
26
- @start = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector) }
27
+ @start = @selectors.map { |selector| @adapter.child_node_range(@node, selector) }
27
28
  .compact.map(&:start).min
28
- @end = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector) }
29
+ @end = @selectors.map { |selector| @adapter.child_node_range(@node, selector) }
29
30
  .compact.map(&:end).max
30
31
  remove_comma if @and_comma
31
32
  remove_whitespace
@@ -4,6 +4,7 @@
4
4
  class NodeMutation::GroupAction < NodeMutation::Action
5
5
  DEFAULT_START = 2**30
6
6
 
7
+ # Initialize a GroupAction.
7
8
  def initialize
8
9
  @actions = []
9
10
  @type = :group
@@ -6,8 +6,9 @@ class NodeMutation::IndentAction < NodeMutation::Action
6
6
  #
7
7
  # @param node [Node]
8
8
  # @param tab_size [Integer] tab size
9
- def initialize(node, tab_size = 1)
10
- super(node, nil)
9
+ # @param adapter [NodeMutation::Adapter]
10
+ def initialize(node, tab_size = 1, adapter:)
11
+ super(node, nil, adapter: adapter)
11
12
  @tab_size = tab_size
12
13
  @type = :replace
13
14
  end
@@ -16,7 +17,7 @@ class NodeMutation::IndentAction < NodeMutation::Action
16
17
  #
17
18
  # @return [String] rewritten code.
18
19
  def new_code
19
- source = NodeMutation.adapter.get_source(@node)
20
+ source = @adapter.get_source(@node)
20
21
  source.each_line.map { |line| (' ' * NodeMutation.tab_width * @tab_size) + line }
21
22
  .join
22
23
  end
@@ -25,7 +26,7 @@ class NodeMutation::IndentAction < NodeMutation::Action
25
26
 
26
27
  # Calculate the begin the end positions.
27
28
  def calculate_position
28
- @start = NodeMutation.adapter.get_start(@node)
29
- @end = NodeMutation.adapter.get_end(@node)
29
+ @start = @adapter.get_start(@node)
30
+ @end = @adapter.get_end(@node)
30
31
  end
31
32
  end
@@ -9,8 +9,9 @@ class NodeMutation::InsertAction < NodeMutation::Action
9
9
  # @param at [String] position to insert, beginning or end
10
10
  # @param to [<nil|String>] name of child node
11
11
  # @param and_comma [Boolean] insert extra comma.
12
- def initialize(node, code, at: 'end', to: nil, and_comma: false)
13
- super(node, code)
12
+ # @param adapter [NodeMutation::Adapter]
13
+ def initialize(node, code, adapter:, at: 'end', to: nil, and_comma: false)
14
+ super(node, code, adapter: adapter)
14
15
  @at = at
15
16
  @to = to
16
17
  @and_comma = and_comma
@@ -35,15 +36,15 @@ class NodeMutation::InsertAction < NodeMutation::Action
35
36
  @start =
36
37
  if @at == 'end'
37
38
  if @to
38
- NodeMutation.adapter.child_node_range(@node, @to).end
39
+ @adapter.child_node_range(@node, @to).end
39
40
  else
40
- NodeMutation.adapter.get_end(@node)
41
+ @adapter.get_end(@node)
41
42
  end
42
43
  else
43
44
  if @to
44
- NodeMutation.adapter.child_node_range(@node, @to).start
45
+ @adapter.child_node_range(@node, @to).start
45
46
  else
46
- NodeMutation.adapter.get_start(@node)
47
+ @adapter.get_start(@node)
47
48
  end
48
49
  end
49
50
  @end = @start
@@ -2,9 +2,12 @@
2
2
 
3
3
  # NoopAction to do no operation.
4
4
  class NodeMutation::NoopAction < NodeMutation::Action
5
- # Create a NoopAction
6
- def initialize(node)
7
- super(node, nil)
5
+ # Initialize a NoopAction.
6
+ #
7
+ # @param node [Node]
8
+ # @param adapter [NodeMutation::Adapter]
9
+ def initialize(node, adapter:)
10
+ super(node, nil, adapter: adapter)
8
11
  end
9
12
 
10
13
  # The rewritten source code with proper indent.
@@ -18,7 +21,7 @@ class NodeMutation::NoopAction < NodeMutation::Action
18
21
 
19
22
  # Calculate the begin the end positions.
20
23
  def calculate_position
21
- @start = NodeMutation.adapter.get_start(@node)
22
- @end = NodeMutation.adapter.get_end(@node)
24
+ @start = @adapter.get_start(@node)
25
+ @end = @adapter.get_end(@node)
23
26
  end
24
27
  end
@@ -2,8 +2,13 @@
2
2
 
3
3
  # PrependAction to prepend code to the top of node body.
4
4
  class NodeMutation::PrependAction < NodeMutation::Action
5
- def initialize(node, code)
6
- super(node, code)
5
+ # Initialize an PrependAction.
6
+ #
7
+ # @param node [Node]
8
+ # @param code [String] new code to prepend.
9
+ # @param adapter [NodeMutation::Adapter]
10
+ def initialize(node, code, adapter:)
11
+ super(node, code, adapter: adapter)
7
12
  @type = :insert
8
13
  end
9
14
 
@@ -11,8 +16,8 @@ class NodeMutation::PrependAction < NodeMutation::Action
11
16
 
12
17
  # Calculate the begin and end positions.
13
18
  def calculate_position
14
- node_start = NodeMutation.adapter.get_start(@node)
15
- node_source = NodeMutation.adapter.get_source(@node)
19
+ node_start = @adapter.get_start(@node)
20
+ node_source = @adapter.get_source(@node)
16
21
  first_line = node_source.split("\n").first
17
22
  @start = first_line.end_with?("do") ? node_start + first_line.rindex("do") + "do".length : node_start + first_line.length
18
23
  @end = @start
@@ -23,6 +28,6 @@ class NodeMutation::PrependAction < NodeMutation::Action
23
28
  # @param node [Parser::AST::Node]
24
29
  # @return [String] n times whitesphace
25
30
  def indent(node)
26
- ' ' * (NodeMutation.adapter.get_start_loc(node).column + NodeMutation.tab_width)
31
+ ' ' * (@adapter.get_start_loc(node).column + NodeMutation.tab_width)
27
32
  end
28
33
  end
@@ -5,10 +5,10 @@ class NodeMutation::RemoveAction < NodeMutation::Action
5
5
  # Initialize a RemoveAction.
6
6
  #
7
7
  # @param node [Node]
8
- # @param options [Hash] options.
9
- # @option and_comma [Boolean] delete extra comma.
10
- def initialize(node, and_comma: false)
11
- super(node, nil)
8
+ # @param and_comma [Boolean] delete extra comma.
9
+ # @param adapter [NodeMutation::Adapter]
10
+ def initialize(node, adapter:, and_comma: false)
11
+ super(node, nil, adapter: adapter)
12
12
  @and_comma = and_comma
13
13
  @type = :delete
14
14
  end
@@ -22,8 +22,8 @@ class NodeMutation::RemoveAction < NodeMutation::Action
22
22
 
23
23
  # Calculate the begin the end positions.
24
24
  def calculate_position
25
- @start = NodeMutation.adapter.get_start(@node)
26
- @end = NodeMutation.adapter.get_end(@node)
25
+ @start = @adapter.get_start(@node)
26
+ @end = @adapter.get_end(@node)
27
27
  remove_comma if @and_comma
28
28
  remove_whitespace
29
29
  if take_whole_line?
@@ -36,7 +36,7 @@ class NodeMutation::RemoveAction < NodeMutation::Action
36
36
  #
37
37
  # @return [Boolean]
38
38
  def take_whole_line?
39
- NodeMutation.adapter.get_source(@node) == file_source[@start...@end].strip.chomp(',')
39
+ @adapter.get_source(@node) == file_source[@start...@end].strip.chomp(',')
40
40
  end
41
41
 
42
42
  def remove_newline
@@ -73,8 +73,8 @@ class NodeMutation::RemoveAction < NodeMutation::Action
73
73
 
74
74
  def squeeze_lines
75
75
  lines = file_source.split("\n")
76
- begin_line = NodeMutation.adapter.get_start_loc(@node).line
77
- end_line = NodeMutation.adapter.get_end_loc(@node).line
76
+ begin_line = @adapter.get_start_loc(@node).line
77
+ end_line = @adapter.get_end_loc(@node).line
78
78
  before_line_is_blank = begin_line == 1 || lines[begin_line - 2] == ''
79
79
  after_line_is_blank = lines[end_line] == ''
80
80
 
@@ -7,8 +7,9 @@ class NodeMutation::ReplaceAction < NodeMutation::Action
7
7
  # @param node [Node]
8
8
  # @param selectors [Array<Symbol|String>] used to select child nodes
9
9
  # @param with [String] the new code
10
- def initialize(node, *selectors, with:)
11
- super(node, with)
10
+ # @param adapter [NodeMutation::Adapter]
11
+ def initialize(node, *selectors, adapter:, with:)
12
+ super(node, with, adapter: adapter)
12
13
  @selectors = selectors
13
14
  @type = :replace
14
15
  end
@@ -24,9 +25,9 @@ class NodeMutation::ReplaceAction < NodeMutation::Action
24
25
 
25
26
  # Calculate the begin the end positions.
26
27
  def calculate_position
27
- @start = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector).start }
28
+ @start = @selectors.map { |selector| @adapter.child_node_range(@node, selector).start }
28
29
  .min
29
- @end = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector).end }
30
+ @end = @selectors.map { |selector| @adapter.child_node_range(@node, selector).end }
30
31
  .max
31
32
  end
32
33
  end
@@ -2,8 +2,13 @@
2
2
 
3
3
  # ReplaceWithAction to replace code.
4
4
  class NodeMutation::ReplaceWithAction < NodeMutation::Action
5
- def initialize(node, code)
6
- super(node, code)
5
+ # Initailize a ReplaceWithAction.
6
+ #
7
+ # @param node [Node]
8
+ # @param code [String] the new code.
9
+ # @param adapter [NodeMutation::Adapter]
10
+ def initialize(node, code, adapter:)
11
+ super(node, code, adapter: adapter)
7
12
  @type = :replace
8
13
  end
9
14
 
@@ -26,14 +31,14 @@ class NodeMutation::ReplaceWithAction < NodeMutation::Action
26
31
 
27
32
  # Calculate the begin the end positions.
28
33
  def calculate_position
29
- @start = NodeMutation.adapter.get_start(@node)
30
- @end = NodeMutation.adapter.get_end(@node)
34
+ @start = @adapter.get_start(@node)
35
+ @end = @adapter.get_end(@node)
31
36
  end
32
37
 
33
38
  # Indent of the node
34
39
  #
35
40
  # @return [String] n times whitesphace
36
41
  def indent
37
- ' ' * NodeMutation.adapter.get_start_loc(@node).column
42
+ ' ' * @adapter.get_start_loc(@node).column
38
43
  end
39
44
  end
@@ -16,9 +16,11 @@ class NodeMutation::Action
16
16
  #
17
17
  # @param node [Node]
18
18
  # @param code [String] new code to insert, replace or delete.
19
- def initialize(node, code)
19
+ # @param adapter [NodeMutation::Adapter]
20
+ def initialize(node, code, adapter:)
20
21
  @node = node
21
22
  @code = code
23
+ @adapter = adapter
22
24
  end
23
25
 
24
26
  # Calculate begin and end positions, and return self.
@@ -59,7 +61,7 @@ class NodeMutation::Action
59
61
  #
60
62
  # @return [String] rewritten source code.
61
63
  def rewritten_source
62
- @rewritten_source ||= NodeMutation.adapter.rewritten_source(@node, @code)
64
+ @rewritten_source ||= @adapter.rewritten_source(@node, @code)
63
65
  end
64
66
 
65
67
  # remove unused whitespace.
@@ -115,6 +117,6 @@ class NodeMutation::Action
115
117
  #
116
118
  # @return [String]
117
119
  def file_source
118
- @file_source ||= NodeMutation.adapter.file_source(@node)
120
+ @file_source ||= @adapter.file_source(@node)
119
121
  end
120
122
  end
@@ -82,7 +82,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
82
82
  if lines_count > 1 && lines_count == evaluated.size
83
83
  new_code = []
84
84
  lines.each_with_index { |line, index|
85
- new_code << (index == 0 ? line : line[NodeMutation.adapter.get_indent(evaluated.first) - NodeMutation.tab_width..-1])
85
+ new_code << (index == 0 ? line : line[get_indent(evaluated.first) - NodeMutation.tab_width..-1])
86
86
  }
87
87
  new_code.join("\n")
88
88
  else
@@ -74,7 +74,7 @@ class NodeMutation::SyntaxTreeAdapter < NodeMutation::Adapter
74
74
  if lines_count > 1 && lines_count == evaluated.size
75
75
  new_code = []
76
76
  lines.each_with_index { |line, index|
77
- new_code << (index == 0 ? line : line[NodeMutation.adapter.get_indent(evaluated.first) - NodeMutation.tab_width..-1])
77
+ new_code << (index == 0 ? line : line[get_indent(evaluated.first) - NodeMutation.tab_width..-1])
78
78
  }
79
79
  new_code.join("\n")
80
80
  else
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeMutation
4
- VERSION = "1.21.5"
4
+ VERSION = "1.22.0"
5
5
  end
data/lib/node_mutation.rb CHANGED
@@ -5,6 +5,7 @@ require_relative "node_mutation/version"
5
5
  class NodeMutation
6
6
  class MethodNotSupported < StandardError; end
7
7
  class ConflictActionError < StandardError; end
8
+ class InvalidAdapterError < StandardError; end
8
9
 
9
10
  autoload :Adapter, "node_mutation/adapter"
10
11
  autoload :ParserAdapter, "node_mutation/adapter/parser"
@@ -27,7 +28,7 @@ class NodeMutation
27
28
 
28
29
  # @!attribute [r] actions
29
30
  # @return [Array<NodeMutation::Struct::Action>]
30
- attr_reader :actions
31
+ attr_reader :actions, :adapter
31
32
 
32
33
  # @!attribute [rw] transform_proc
33
34
  # @return [Proc] proc to transfor the actions
@@ -36,13 +37,9 @@ class NodeMutation
36
37
  class << self
37
38
  # Configure NodeMutation
38
39
  # @param [Hash] options options to configure
39
- # @option options [NodeMutation::Adapter] :adapter the adpater
40
40
  # @option options [NodeMutation::Strategy] :strategy the strategy
41
41
  # @option options [Integer] :tab_width the tab width
42
42
  def configure(options)
43
- if options[:adapter]
44
- @adapter = options[:adapter]
45
- end
46
43
  if options[:strategy]
47
44
  @strategy = options[:strategy]
48
45
  end
@@ -51,12 +48,6 @@ class NodeMutation
51
48
  end
52
49
  end
53
50
 
54
- # Get the adapter
55
- # @return [NodeMutation::Adapter] current adapter, by default is {NodeMutation::ParserAdapter}
56
- def adapter
57
- @adapter ||= ParserAdapter.new
58
- end
59
-
60
51
  # Get the strategy
61
52
  # @return [Integer] current strategy, could be {NodeMutation::Strategy::KEEP_RUNNING} or {NodeMutation::Strategy::THROW_ERROR},
62
53
  # by default is {NodeMutation::Strategy::KEEP_RUNNING}
@@ -73,9 +64,11 @@ class NodeMutation
73
64
 
74
65
  # Initialize a NodeMutation.
75
66
  # @param source [String] file source
76
- def initialize(source)
67
+ # @param adapter [Symbol] :parser or :syntax_tree
68
+ def initialize(source, adapter:)
77
69
  @source = source
78
70
  @actions = []
71
+ @adapter = get_adapter_instance(adapter)
79
72
  end
80
73
 
81
74
  # Append code to the ast node.
@@ -94,7 +87,7 @@ class NodeMutation
94
87
  # super
95
88
  # end
96
89
  def append(node, code)
97
- @actions << AppendAction.new(node, code).process
90
+ @actions << AppendAction.new(node, code, adapter: @adapter).process
98
91
  end
99
92
 
100
93
  # Delete source code of the child ast node.
@@ -109,7 +102,7 @@ class NodeMutation
109
102
  # the source code will be rewritten to
110
103
  # create(...)
111
104
  def delete(node, *selectors, and_comma: false)
112
- @actions << DeleteAction.new(node, *selectors, and_comma: and_comma).process
105
+ @actions << DeleteAction.new(node, *selectors, and_comma: and_comma, adapter: @adapter).process
113
106
  end
114
107
 
115
108
  # Insert code to the ast node.
@@ -126,7 +119,7 @@ class NodeMutation
126
119
  # the source code will be rewritten to
127
120
  # URI.open('http://test.com')
128
121
  def insert(node, code, at: 'end', to: nil, and_comma: false)
129
- @actions << InsertAction.new(node, code, at: at, to: to, and_comma: and_comma).process
122
+ @actions << InsertAction.new(node, code, at: at, to: to, and_comma: and_comma, adapter: @adapter).process
130
123
  end
131
124
 
132
125
  # Prepend code to the ast node.
@@ -145,7 +138,7 @@ class NodeMutation
145
138
  # do_something
146
139
  # end
147
140
  def prepend(node, code)
148
- @actions << PrependAction.new(node, code).process
141
+ @actions << PrependAction.new(node, code, adapter: @adapter).process
149
142
  end
150
143
 
151
144
  # Remove source code of the ast node.
@@ -158,7 +151,7 @@ class NodeMutation
158
151
  # mutation.remove(node)
159
152
  # the source code will be removed
160
153
  def remove(node, and_comma: false)
161
- @actions << RemoveAction.new(node, and_comma: and_comma).process
154
+ @actions << RemoveAction.new(node, and_comma: and_comma, adapter: @adapter).process
162
155
  end
163
156
 
164
157
  # Replace child node of the ast node with new code.
@@ -174,7 +167,7 @@ class NodeMutation
174
167
  # the source code will be rewritten to
175
168
  # assert_empty(object)
176
169
  def replace(node, *selectors, with:)
177
- @actions << ReplaceAction.new(node, *selectors, with: with).process
170
+ @actions << ReplaceAction.new(node, *selectors, with: with, adapter: @adapter).process
178
171
  end
179
172
 
180
173
  # Replace source code of the ast node with new code.
@@ -188,7 +181,7 @@ class NodeMutation
188
181
  # the source code will be rewritten to
189
182
  # allow(obj).to receive_messages(:foo => 1, :bar => 2)
190
183
  def replace_with(node, code)
191
- @actions << ReplaceWithAction.new(node, code).process
184
+ @actions << ReplaceWithAction.new(node, code, adapter: @adapter).process
192
185
  end
193
186
 
194
187
  # Wrap source code of the ast node with prefix and suffix code.
@@ -209,7 +202,7 @@ class NodeMutation
209
202
  # end
210
203
  def wrap(node, prefix:, suffix:, newline: false)
211
204
  if newline
212
- indentation = NodeMutation.adapter.get_start_loc(node).column
205
+ indentation = @adapter.get_start_loc(node).column
213
206
  group do
214
207
  insert node, prefix + "\n" + (' ' * indentation), at: 'beginning'
215
208
  insert node, "\n" + (' ' * indentation) + suffix, at: 'end'
@@ -235,13 +228,13 @@ class NodeMutation
235
228
  # class Foobar
236
229
  # end
237
230
  def indent(node)
238
- @actions << IndentAction.new(node).process
231
+ @actions << IndentAction.new(node, adapter: @adapter).process
239
232
  end
240
233
 
241
234
  # No operation.
242
235
  # @param node [Node] ast node
243
236
  def noop(node)
244
- @actions << NoopAction.new(node).process
237
+ @actions << NoopAction.new(node, adapter: @adapter).process
245
238
  end
246
239
 
247
240
  # group multiple actions
@@ -277,7 +270,8 @@ class NodeMutation
277
270
  raise ConflictActionError, "mutation actions are conflicted"
278
271
  end
279
272
 
280
- new_source = rewrite_source(source, sort_actions(get_filter_actions(conflict_actions)))
273
+ actions = sort_flatten_actions(flat_actions(get_filter_actions(conflict_actions)))
274
+ new_source = rewrite_source(source, actions)
281
275
  result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
282
276
  result.new_source = new_source
283
277
  result
@@ -423,4 +417,15 @@ class NodeMutation
423
417
  def strategy?(strategy)
424
418
  NodeMutation.strategy & strategy == strategy
425
419
  end
420
+
421
+ def get_adapter_instance(adapter)
422
+ case adapter.to_sym
423
+ when :parser
424
+ ParserAdapter.new
425
+ when :syntax_tree
426
+ SyntaxTreeAdapter.new
427
+ else
428
+ raise InvalidAdapterError, "adapter #{adapter} is not supported"
429
+ end
430
+ end
426
431
  end
@@ -9,15 +9,13 @@ class NodeMutation[T]
9
9
 
10
10
  attr_reader actions: Array[NodeMutation::Action]
11
11
 
12
- def self.configure: (options: { adapter: NodeMutation::Adapter, strategy: Integer, tab_width: Integer }) -> void
13
-
14
- def self.adapter: () -> NodeMutation::Adapter
12
+ def self.configure: (options: { strategy: Integer, tab_width: Integer }) -> void
15
13
 
16
14
  def self.strategy: () -> Integer
17
15
 
18
16
  def self.tab_width: () -> Integer
19
17
 
20
- def initialize: (source: String) -> NodeMutation
18
+ def initialize: (source: String, adapter: Symbol) -> NodeMutation
21
19
 
22
20
  def append: (node: T, code: String) -> void
23
21
 
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.5
4
+ version: 1.22.0
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-11-19 00:00:00.000000000 Z
11
+ date: 2023-11-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: ast node mutation apis
14
14
  email: