node_mutation 1.13.2 → 1.15.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 +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -1
- data/README.md +6 -5
- data/lib/node_mutation/action/indent_action.rb +29 -0
- data/lib/node_mutation/action.rb +3 -3
- data/lib/node_mutation/strategy.rb +0 -1
- data/lib/node_mutation/version.rb +1 -1
- data/lib/node_mutation.rb +19 -10
- data/sig/node_mutation/strategy.rbs +0 -2
- metadata +4 -4
- data/lib/node_mutation/action/wrap_action.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11054e72fcf35b7caeb2cee67b421206da2f980d4d1f23afa08f9db75f112f75
|
4
|
+
data.tar.gz: 4dde234a2f4716b82d042b7d9f094469da04942cdca669c40a7d745f75480b77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bfc255f3b2bf599debc4c8d882999d3083f89ec2e9cdb81aa2eb1d4245e65cafb61c9f9ee7db7286b4efddf66b96cb00742696f5215beab1b3cc847c2025b40
|
7
|
+
data.tar.gz: 7c9063056156b1ee4accd50ad204040209c55ca096f543ecccc5f66175b1213a5611a4815263058514d81466e440d6cdf36f65c7208d048c48c3f3736e516706
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# NodeMutation
|
2
2
|
|
3
|
+
## 1.15.0 (2023-04-17)
|
4
|
+
|
5
|
+
* Add `indent` action
|
6
|
+
* Use two `InsertAction` and one `IndentAction` instead of `WrapAction`
|
7
|
+
* Drop `ALLOW_INSERT_AT_SAME_POSITION` strategy
|
8
|
+
|
9
|
+
## 1.14.0 (2023-04-04)
|
10
|
+
|
11
|
+
* Add `transform_proc` to transform the actions
|
12
|
+
* Allow to write `Action` `start` and `end` attributes
|
13
|
+
|
3
14
|
## 1.13.2 (2023-04-01)
|
4
15
|
|
5
16
|
* Support `cvar`, `gvar`, `ivar`, and `lvar` name in `child_node_range`
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -35,18 +35,20 @@ mutation = NodeMutation.new(source)
|
|
35
35
|
mutation.append node, 'include FactoryGirl::Syntax::Methods'
|
36
36
|
# delete source code of the child ast node
|
37
37
|
mutation.delete node, :dot, :message, and_comma: true
|
38
|
+
# indent code
|
39
|
+
mutation.indent node, tab_size: 1
|
38
40
|
# insert code to the ast node.
|
39
41
|
mutation.insert node, 'URI.', at: 'beginning'
|
40
42
|
# prepend code to the ast node.
|
41
43
|
mutation.prepend node, '{{arguments.first}}.include FactoryGirl::Syntax::Methods'
|
42
44
|
# remove source code of the ast node
|
43
|
-
mutation.remove
|
45
|
+
mutation.remove node, and_comma: true
|
44
46
|
# replace child node of the ast node with new code
|
45
47
|
mutation.replace node, :message, with: 'test'
|
46
48
|
# replace the ast node with new code
|
47
49
|
mutation.replace_with node, 'create {{arguments}}'
|
48
|
-
# wrap node
|
49
|
-
mutation.wrap node,
|
50
|
+
# wrap node with prefix and suffix code
|
51
|
+
mutation.wrap node, prefix: 'module Foo', suffix: 'end', newline: true
|
50
52
|
# no operation
|
51
53
|
mutation.noop
|
52
54
|
```
|
@@ -81,10 +83,9 @@ It provides 3 strategies to handle conflicts when processing actions:
|
|
81
83
|
|
82
84
|
1. `Strategy.KEEP_RUNNING`: keep running and ignore the conflict action.
|
83
85
|
2. `Strategy.THROW_ERROR`: throw error when conflict action is found.
|
84
|
-
3. `Strategy.ALLOW_INSERT_AT_SAME_POSITION`: allow insert action at the same position.
|
85
86
|
|
86
87
|
```ruby
|
87
|
-
NodeMutation.configure(strategy: Strategy.KEEP_RUNNING
|
88
|
+
NodeMutation.configure(strategy: Strategy.KEEP_RUNNING); // default is Strategy.THROW_ERROR
|
88
89
|
```
|
89
90
|
|
90
91
|
### tab_width
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# IndentAction to indent code.
|
4
|
+
class NodeMutation::IndentAction < NodeMutation::Action
|
5
|
+
# Initialize a IndentAction.
|
6
|
+
#
|
7
|
+
# @param node [Node]
|
8
|
+
# @param tab_size [Integer] tab size
|
9
|
+
def initialize(node, tab_size = 1)
|
10
|
+
super(node, nil)
|
11
|
+
@tab_size = tab_size
|
12
|
+
end
|
13
|
+
|
14
|
+
# The rewritten source code with proper indent.
|
15
|
+
#
|
16
|
+
# @return [String] rewritten code.
|
17
|
+
def new_code
|
18
|
+
source = NodeMutation.adapter.get_source(@node)
|
19
|
+
source.each_line.map { |line| ' ' * NodeMutation.tab_width * @tab_size + line }.join
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# Calculate the begin the end positions.
|
25
|
+
def calculate_position
|
26
|
+
@start = NodeMutation.adapter.get_start(@node)
|
27
|
+
@end = NodeMutation.adapter.get_end(@node)
|
28
|
+
end
|
29
|
+
end
|
data/lib/node_mutation/action.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
# Action defines rewriter action, insert, replace or delete code.
|
4
4
|
class NodeMutation::Action
|
5
|
-
# @!attribute [
|
5
|
+
# @!attribute [rw] start
|
6
6
|
# @return [Integer] start position
|
7
|
-
# @!attribute [
|
7
|
+
# @!attribute [rw] end
|
8
8
|
# @return [Integer] end position
|
9
|
-
|
9
|
+
attr_accessor :start, :end
|
10
10
|
|
11
11
|
# Initialize an action.
|
12
12
|
#
|
data/lib/node_mutation.rb
CHANGED
@@ -11,19 +11,25 @@ class NodeMutation
|
|
11
11
|
autoload :Action, 'node_mutation/action'
|
12
12
|
autoload :AppendAction, 'node_mutation/action/append_action'
|
13
13
|
autoload :DeleteAction, 'node_mutation/action/delete_action'
|
14
|
+
autoload :IndentAction, 'node_mutation/action/indent_action'
|
14
15
|
autoload :InsertAction, 'node_mutation/action/insert_action'
|
15
16
|
autoload :RemoveAction, 'node_mutation/action/remove_action'
|
16
17
|
autoload :PrependAction, 'node_mutation/action/prepend_action'
|
17
18
|
autoload :ReplaceAction, 'node_mutation/action/replace_action'
|
18
19
|
autoload :ReplaceWithAction, 'node_mutation/action/replace_with_action'
|
19
|
-
autoload :WrapAction, 'node_mutation/action/wrap_action'
|
20
20
|
autoload :NoopAction, 'node_mutation/action/noop_action'
|
21
21
|
autoload :Result, 'node_mutation/result'
|
22
22
|
autoload :Strategy, 'node_mutation/strategy'
|
23
23
|
autoload :Struct, 'node_mutation/struct'
|
24
24
|
|
25
|
+
# @!attribute [r] actions
|
26
|
+
# @return [Array<NodeMutation::Struct::Action>]
|
25
27
|
attr_reader :actions
|
26
28
|
|
29
|
+
# @!attribute [rw] transform_proc
|
30
|
+
# @return [Proc] proc to transfor the actions
|
31
|
+
attr_accessor :transform_proc
|
32
|
+
|
27
33
|
class << self
|
28
34
|
# Configure NodeMutation
|
29
35
|
# @param [Hash] options options to configure
|
@@ -182,22 +188,26 @@ class NodeMutation
|
|
182
188
|
@actions << ReplaceWithAction.new(node, code).process
|
183
189
|
end
|
184
190
|
|
185
|
-
# Wrap source code of the ast node with
|
191
|
+
# Wrap source code of the ast node with prefix and suffix code.
|
186
192
|
# @param node [Node] ast node
|
187
|
-
# @param
|
193
|
+
# @param prefix [String] prefix code need to be wrapped with.
|
194
|
+
# @param suffix [String] suffix code need to be wrapped with.
|
195
|
+
# @param newline [Boolean] add newline after prefix and before suffix.
|
188
196
|
# @example
|
189
197
|
# source code of the ast node is
|
190
198
|
# class Foobar
|
191
199
|
# end
|
192
200
|
# then we call
|
193
|
-
# wrap(node,
|
201
|
+
# wrap(node, prefix: 'module Synvert', suffix: 'end', newline: true)
|
194
202
|
# the source code will be rewritten to
|
195
203
|
# module Synvert
|
196
204
|
# class Foobar
|
197
205
|
# end
|
198
206
|
# end
|
199
|
-
def wrap(node,
|
200
|
-
@actions <<
|
207
|
+
def wrap(node, prefix:, suffix:, newline: false)
|
208
|
+
@actions << InsertAction.new(node, prefix, at: 'beginning').process
|
209
|
+
@actions << InsertAction.new(node, suffix, at: 'end').process
|
210
|
+
@actions << IndentAction.new(node).process if newline
|
201
211
|
end
|
202
212
|
|
203
213
|
# No operation.
|
@@ -219,6 +229,7 @@ class NodeMutation
|
|
219
229
|
end
|
220
230
|
|
221
231
|
source = +@source
|
232
|
+
@transform_proc.call(@actions) if @transform_proc
|
222
233
|
@actions.sort_by! { |action| [action.start, action.end] }
|
223
234
|
conflict_actions = get_conflict_actions
|
224
235
|
if conflict_actions.size > 0 && strategy?(Strategy::THROW_ERROR)
|
@@ -245,6 +256,7 @@ class NodeMutation
|
|
245
256
|
return NodeMutation::Result.new(affected: false, conflicted: false)
|
246
257
|
end
|
247
258
|
|
259
|
+
@transform_proc.call(@actions) if @transform_proc
|
248
260
|
@actions.sort_by! { |action| [action.start, action.end] }
|
249
261
|
conflict_actions = get_conflict_actions
|
250
262
|
if conflict_actions.size > 0 && strategy?(Strategy::THROW_ERROR)
|
@@ -269,11 +281,8 @@ class NodeMutation
|
|
269
281
|
begin_pos = @actions[i].start
|
270
282
|
end_pos = @actions[i].end
|
271
283
|
while j > -1
|
272
|
-
# if we have two insert actions at same position.
|
273
|
-
same_position = begin_pos == @actions[j].start && begin_pos == end_pos && @actions[j].start == @actions[j].end
|
274
284
|
# if we have two actions with overlapped range.
|
275
|
-
|
276
|
-
if (!strategy?(Strategy::ALLOW_INSERT_AT_SAME_POSITION) && same_position) || overlapped_position
|
285
|
+
if begin_pos < @actions[j].end
|
277
286
|
conflict_actions << @actions.delete_at(j)
|
278
287
|
else
|
279
288
|
i = j
|
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.
|
4
|
+
version: 1.15.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-04-
|
11
|
+
date: 2023-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: ast node mutation apis
|
14
14
|
email:
|
@@ -29,13 +29,13 @@ files:
|
|
29
29
|
- lib/node_mutation/action.rb
|
30
30
|
- lib/node_mutation/action/append_action.rb
|
31
31
|
- lib/node_mutation/action/delete_action.rb
|
32
|
+
- lib/node_mutation/action/indent_action.rb
|
32
33
|
- lib/node_mutation/action/insert_action.rb
|
33
34
|
- lib/node_mutation/action/noop_action.rb
|
34
35
|
- lib/node_mutation/action/prepend_action.rb
|
35
36
|
- lib/node_mutation/action/remove_action.rb
|
36
37
|
- lib/node_mutation/action/replace_action.rb
|
37
38
|
- lib/node_mutation/action/replace_with_action.rb
|
38
|
-
- lib/node_mutation/action/wrap_action.rb
|
39
39
|
- lib/node_mutation/adapter.rb
|
40
40
|
- lib/node_mutation/parser_adapter.rb
|
41
41
|
- lib/node_mutation/result.rb
|
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
69
|
- !ruby/object:Gem::Version
|
70
70
|
version: '0'
|
71
71
|
requirements: []
|
72
|
-
rubygems_version: 3.4.
|
72
|
+
rubygems_version: 3.4.10
|
73
73
|
signing_key:
|
74
74
|
specification_version: 4
|
75
75
|
summary: ast node mutation apis
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# WrapAction to wrap node within a block, class or module.
|
4
|
-
#
|
5
|
-
# Note: if WrapAction is conflicted with another action (start and end are overlapped),
|
6
|
-
# we have to put those 2 actions into 2 within_file scopes.
|
7
|
-
class NodeMutation::WrapAction < NodeMutation::Action
|
8
|
-
# Initialize a WrapAction.
|
9
|
-
#
|
10
|
-
# @param node [Node]
|
11
|
-
# @param with [String] new code to wrap
|
12
|
-
def initialize(node, with:)
|
13
|
-
super(node, with)
|
14
|
-
@indent = NodeMutation.adapter.get_start_loc(@node).column
|
15
|
-
end
|
16
|
-
|
17
|
-
# The rewritten source code.
|
18
|
-
#
|
19
|
-
# @return [String] rewritten code.
|
20
|
-
def new_code
|
21
|
-
"#{@code}\n#{' ' * @indent}" +
|
22
|
-
NodeMutation.adapter.get_source(@node).split("\n").map { |line| " #{line}" }
|
23
|
-
.join("\n") +
|
24
|
-
"\n#{' ' * @indent}end"
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
# Calculate the begin the end positions.
|
30
|
-
def calculate_position
|
31
|
-
@start = NodeMutation.adapter.get_start(@node)
|
32
|
-
@end = NodeMutation.adapter.get_end(@node)
|
33
|
-
end
|
34
|
-
end
|