node_mutation 1.22.3 → 1.22.4
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 +4 -0
- data/Gemfile.lock +1 -1
- data/lib/node_mutation/action/group_action.rb +1 -10
- data/lib/node_mutation/version.rb +1 -1
- data/lib/node_mutation.rb +176 -3
- metadata +1 -2
- data/lib/node_mutation/actionable.rb +0 -181
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9485dffc945cb3b645d4abecc7f878550685459ccd2007845471651d6893e2f1
|
4
|
+
data.tar.gz: 0ab63429232abd2f357b2c791bb3e5bc66a4762ff4175d6444b8c51dbac99a5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc326b1af7d3f13bdd91f24c59d3be4991c20cc751de9bf0b8d48be98dc44fa78c93b4a5ffc75eac2535437ad478a206d54342195737989c17d7eb4121624c8a
|
7
|
+
data.tar.gz: 92cea72b3327755abb2b789cd704809b46258c3a6cc7f7e9f8bac678e2907e93d7fe59e5abfd33308029bc71dee24a1d8e23cbf976f2a1d7d9648876d6e24b78
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,27 +2,18 @@
|
|
2
2
|
|
3
3
|
# GroupAction is compose of multiple actions.
|
4
4
|
class NodeMutation::GroupAction < NodeMutation::Action
|
5
|
-
include NodeMutation::Actionable
|
6
|
-
|
7
5
|
DEFAULT_START = 2**30
|
8
6
|
|
9
7
|
# Initialize a GroupAction.
|
10
|
-
def initialize
|
8
|
+
def initialize
|
11
9
|
@actions = []
|
12
10
|
@type = :group
|
13
|
-
@adapter = adapter
|
14
|
-
@block = block
|
15
11
|
end
|
16
12
|
|
17
13
|
def new_code
|
18
14
|
nil
|
19
15
|
end
|
20
16
|
|
21
|
-
def process
|
22
|
-
instance_eval(&@block)
|
23
|
-
super
|
24
|
-
end
|
25
|
-
|
26
17
|
private
|
27
18
|
|
28
19
|
# Calculate the begin and end positions.
|
data/lib/node_mutation.rb
CHANGED
@@ -7,7 +7,6 @@ class NodeMutation
|
|
7
7
|
class ConflictActionError < StandardError; end
|
8
8
|
class InvalidAdapterError < StandardError; end
|
9
9
|
|
10
|
-
autoload :Actionable, "node_mutation/actionable"
|
11
10
|
autoload :Adapter, "node_mutation/adapter"
|
12
11
|
autoload :ParserAdapter, "node_mutation/adapter/parser"
|
13
12
|
autoload :SyntaxTreeAdapter, "node_mutation/adapter/syntax_tree"
|
@@ -27,8 +26,6 @@ class NodeMutation
|
|
27
26
|
autoload :Struct, 'node_mutation/struct'
|
28
27
|
autoload :Helper, 'node_mutation/helper'
|
29
28
|
|
30
|
-
include Actionable
|
31
|
-
|
32
29
|
# @!attribute [r] actions
|
33
30
|
# @return [Array<NodeMutation::Struct::Action>]
|
34
31
|
attr_reader :actions, :adapter
|
@@ -74,6 +71,182 @@ class NodeMutation
|
|
74
71
|
@adapter = get_adapter_instance(adapter)
|
75
72
|
end
|
76
73
|
|
74
|
+
# Append code to the ast node.
|
75
|
+
# @param node [Node] ast node
|
76
|
+
# @param code [String] new code to append
|
77
|
+
# @example
|
78
|
+
# source code of the ast node is
|
79
|
+
# def teardown
|
80
|
+
# clean_something
|
81
|
+
# end
|
82
|
+
# then we call
|
83
|
+
# mutation.append(node, 'super')
|
84
|
+
# the source code will be rewritten to
|
85
|
+
# def teardown
|
86
|
+
# clean_something
|
87
|
+
# super
|
88
|
+
# end
|
89
|
+
def append(node, code)
|
90
|
+
@actions << AppendAction.new(node, code, adapter: @adapter).process
|
91
|
+
end
|
92
|
+
|
93
|
+
# Delete source code of the child ast node.
|
94
|
+
# @param node [Node] ast node
|
95
|
+
# @param selectors [Array<Symbol>] selector names of child node.
|
96
|
+
# @param and_comma [Boolean] delete extra comma.
|
97
|
+
# @example
|
98
|
+
# source code of the ast node is
|
99
|
+
# FactoryBot.create(...)
|
100
|
+
# then we call
|
101
|
+
# mutation.delete(node, :receiver, :dot)
|
102
|
+
# the source code will be rewritten to
|
103
|
+
# create(...)
|
104
|
+
def delete(node, *selectors, and_comma: false)
|
105
|
+
@actions << DeleteAction.new(node, *selectors, and_comma: and_comma, adapter: @adapter).process
|
106
|
+
end
|
107
|
+
|
108
|
+
# Insert code to the ast node.
|
109
|
+
# @param node [Node] ast node
|
110
|
+
# @param code [String] code need to be inserted.
|
111
|
+
# @param at [String] insert position, beginning or end
|
112
|
+
# @param to [String] where to insert, if it is nil, will insert to current node.
|
113
|
+
# @param and_comma [Boolean] insert extra comma.
|
114
|
+
# @example
|
115
|
+
# source code of the ast node is
|
116
|
+
# open('http://test.com')
|
117
|
+
# then we call
|
118
|
+
# mutation.insert(node, 'URI.', at: 'beginning')
|
119
|
+
# the source code will be rewritten to
|
120
|
+
# URI.open('http://test.com')
|
121
|
+
def insert(node, code, at: 'end', to: nil, and_comma: false)
|
122
|
+
@actions << InsertAction.new(node, code, at: at, to: to, and_comma: and_comma, adapter: @adapter).process
|
123
|
+
end
|
124
|
+
|
125
|
+
# Prepend code to the ast node.
|
126
|
+
# @param node [Node] ast node
|
127
|
+
# @param code [String] new code to prepend.
|
128
|
+
# @example
|
129
|
+
# source code of the ast node is
|
130
|
+
# def setup
|
131
|
+
# do_something
|
132
|
+
# end
|
133
|
+
# then we call
|
134
|
+
# mutation.prepend(node, 'super')
|
135
|
+
# the source code will be rewritten to
|
136
|
+
# def setup
|
137
|
+
# super
|
138
|
+
# do_something
|
139
|
+
# end
|
140
|
+
def prepend(node, code)
|
141
|
+
@actions << PrependAction.new(node, code, adapter: @adapter).process
|
142
|
+
end
|
143
|
+
|
144
|
+
# Remove source code of the ast node.
|
145
|
+
# @param node [Node] ast node
|
146
|
+
# @param and_comma [Boolean] delete extra comma.
|
147
|
+
# @example
|
148
|
+
# source code of the ast node is
|
149
|
+
# puts "test"
|
150
|
+
# then we call
|
151
|
+
# mutation.remove(node)
|
152
|
+
# the source code will be removed
|
153
|
+
def remove(node, and_comma: false)
|
154
|
+
@actions << RemoveAction.new(node, and_comma: and_comma, adapter: @adapter).process
|
155
|
+
end
|
156
|
+
|
157
|
+
# Replace child node of the ast node with new code.
|
158
|
+
# @param node [Node] ast node
|
159
|
+
# @param selectors [Array<Symbol>] selector names of child node.
|
160
|
+
# @param with [String] code need to be replaced with.
|
161
|
+
# @example
|
162
|
+
# source code of the ast node is
|
163
|
+
# assert(object.empty?)
|
164
|
+
# then we call
|
165
|
+
# mutation.replace(node, :message, with: 'assert_empty')
|
166
|
+
# mutation.replace(node, :arguments, with: '{{arguments.first.receiver}}')
|
167
|
+
# the source code will be rewritten to
|
168
|
+
# assert_empty(object)
|
169
|
+
def replace(node, *selectors, with:)
|
170
|
+
@actions << ReplaceAction.new(node, *selectors, with: with, adapter: @adapter).process
|
171
|
+
end
|
172
|
+
|
173
|
+
# Replace source code of the ast node with new code.
|
174
|
+
# @param node [Node] ast node
|
175
|
+
# @param code [String] code need to be replaced with.
|
176
|
+
# @example
|
177
|
+
# source code of the ast node is
|
178
|
+
# obj.stub(:foo => 1, :bar => 2)
|
179
|
+
# then we call
|
180
|
+
# replace_with 'allow({{receiver}}).to receive_messages({{arguments}})'
|
181
|
+
# the source code will be rewritten to
|
182
|
+
# allow(obj).to receive_messages(:foo => 1, :bar => 2)
|
183
|
+
def replace_with(node, code)
|
184
|
+
@actions << ReplaceWithAction.new(node, code, adapter: @adapter).process
|
185
|
+
end
|
186
|
+
|
187
|
+
# Wrap source code of the ast node with prefix and suffix code.
|
188
|
+
# @param node [Node] ast node
|
189
|
+
# @param prefix [String] prefix code need to be wrapped with.
|
190
|
+
# @param suffix [String] suffix code need to be wrapped with.
|
191
|
+
# @param newline [Boolean] add newline after prefix and before suffix.
|
192
|
+
# @example
|
193
|
+
# source code of the ast node is
|
194
|
+
# class Foobar
|
195
|
+
# end
|
196
|
+
# then we call
|
197
|
+
# wrap(node, prefix: 'module Synvert', suffix: 'end', newline: true)
|
198
|
+
# the source code will be rewritten to
|
199
|
+
# module Synvert
|
200
|
+
# class Foobar
|
201
|
+
# end
|
202
|
+
# end
|
203
|
+
def wrap(node, prefix:, suffix:, newline: false)
|
204
|
+
if newline
|
205
|
+
indentation = @adapter.get_start_loc(node).column
|
206
|
+
group do
|
207
|
+
insert node, prefix + "\n" + (' ' * indentation), at: 'beginning'
|
208
|
+
insert node, "\n" + (' ' * indentation) + suffix, at: 'end'
|
209
|
+
indent node
|
210
|
+
end
|
211
|
+
else
|
212
|
+
group do
|
213
|
+
insert node, prefix, at: 'beginning'
|
214
|
+
insert node, suffix, at: 'end'
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Indent source code of the ast node
|
220
|
+
# @param node [Node] ast node
|
221
|
+
# @example
|
222
|
+
# source code of ast node is
|
223
|
+
# class Foobar
|
224
|
+
# end
|
225
|
+
# then we call
|
226
|
+
# indent(node)
|
227
|
+
# the source code will be rewritten to
|
228
|
+
# class Foobar
|
229
|
+
# end
|
230
|
+
def indent(node)
|
231
|
+
@actions << IndentAction.new(node, adapter: @adapter).process
|
232
|
+
end
|
233
|
+
|
234
|
+
# No operation.
|
235
|
+
# @param node [Node] ast node
|
236
|
+
def noop(node)
|
237
|
+
@actions << NoopAction.new(node, adapter: @adapter).process
|
238
|
+
end
|
239
|
+
|
240
|
+
# group multiple actions
|
241
|
+
def group
|
242
|
+
current_actions = @actions
|
243
|
+
group_action = GroupAction.new
|
244
|
+
@actions = group_action.actions
|
245
|
+
yield
|
246
|
+
@actions = current_actions
|
247
|
+
@actions << group_action.process
|
248
|
+
end
|
249
|
+
|
77
250
|
# Process actions and return the new source.
|
78
251
|
#
|
79
252
|
# If there's an action range conflict,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: node_mutation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.22.
|
4
|
+
version: 1.22.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
@@ -37,7 +37,6 @@ files:
|
|
37
37
|
- lib/node_mutation/action/remove_action.rb
|
38
38
|
- lib/node_mutation/action/replace_action.rb
|
39
39
|
- lib/node_mutation/action/replace_with_action.rb
|
40
|
-
- lib/node_mutation/actionable.rb
|
41
40
|
- lib/node_mutation/adapter.rb
|
42
41
|
- lib/node_mutation/adapter/parser.rb
|
43
42
|
- lib/node_mutation/adapter/syntax_tree.rb
|
@@ -1,181 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module NodeMutation::Actionable
|
4
|
-
# Append code to the ast node.
|
5
|
-
# @param node [Node] ast node
|
6
|
-
# @param code [String] new code to append
|
7
|
-
# @example
|
8
|
-
# source code of the ast node is
|
9
|
-
# def teardown
|
10
|
-
# clean_something
|
11
|
-
# end
|
12
|
-
# then we call
|
13
|
-
# mutation.append(node, 'super')
|
14
|
-
# the source code will be rewritten to
|
15
|
-
# def teardown
|
16
|
-
# clean_something
|
17
|
-
# super
|
18
|
-
# end
|
19
|
-
def append(node, code)
|
20
|
-
@actions << NodeMutation::AppendAction.new(node, code, adapter: @adapter).process
|
21
|
-
end
|
22
|
-
|
23
|
-
# Delete source code of the child ast node.
|
24
|
-
# @param node [Node] ast node
|
25
|
-
# @param selectors [Array<Symbol>] selector names of child node.
|
26
|
-
# @param and_comma [Boolean] delete extra comma.
|
27
|
-
# @example
|
28
|
-
# source code of the ast node is
|
29
|
-
# FactoryBot.create(...)
|
30
|
-
# then we call
|
31
|
-
# mutation.delete(node, :receiver, :dot)
|
32
|
-
# the source code will be rewritten to
|
33
|
-
# create(...)
|
34
|
-
def delete(node, *selectors, and_comma: false)
|
35
|
-
@actions << NodeMutation::DeleteAction.new(node, *selectors, and_comma: and_comma, adapter: @adapter).process
|
36
|
-
end
|
37
|
-
|
38
|
-
# Insert code to the ast node.
|
39
|
-
# @param node [Node] ast node
|
40
|
-
# @param code [String] code need to be inserted.
|
41
|
-
# @param at [String] insert position, beginning or end
|
42
|
-
# @param to [String] where to insert, if it is nil, will insert to current node.
|
43
|
-
# @param and_comma [Boolean] insert extra comma.
|
44
|
-
# @example
|
45
|
-
# source code of the ast node is
|
46
|
-
# open('http://test.com')
|
47
|
-
# then we call
|
48
|
-
# mutation.insert(node, 'URI.', at: 'beginning')
|
49
|
-
# the source code will be rewritten to
|
50
|
-
# URI.open('http://test.com')
|
51
|
-
def insert(node, code, at: 'end', to: nil, and_comma: false)
|
52
|
-
@actions << NodeMutation::InsertAction.new(
|
53
|
-
node,
|
54
|
-
code,
|
55
|
-
at: at,
|
56
|
-
to: to,
|
57
|
-
and_comma: and_comma,
|
58
|
-
adapter: @adapter
|
59
|
-
).process
|
60
|
-
end
|
61
|
-
|
62
|
-
# Prepend code to the ast node.
|
63
|
-
# @param node [Node] ast node
|
64
|
-
# @param code [String] new code to prepend.
|
65
|
-
# @example
|
66
|
-
# source code of the ast node is
|
67
|
-
# def setup
|
68
|
-
# do_something
|
69
|
-
# end
|
70
|
-
# then we call
|
71
|
-
# mutation.prepend(node, 'super')
|
72
|
-
# the source code will be rewritten to
|
73
|
-
# def setup
|
74
|
-
# super
|
75
|
-
# do_something
|
76
|
-
# end
|
77
|
-
def prepend(node, code)
|
78
|
-
@actions << NodeMutation::PrependAction.new(node, code, adapter: @adapter).process
|
79
|
-
end
|
80
|
-
|
81
|
-
# Remove source code of the ast node.
|
82
|
-
# @param node [Node] ast node
|
83
|
-
# @param and_comma [Boolean] delete extra comma.
|
84
|
-
# @example
|
85
|
-
# source code of the ast node is
|
86
|
-
# puts "test"
|
87
|
-
# then we call
|
88
|
-
# mutation.remove(node)
|
89
|
-
# the source code will be removed
|
90
|
-
def remove(node, and_comma: false)
|
91
|
-
@actions << NodeMutation::RemoveAction.new(node, and_comma: and_comma, adapter: @adapter).process
|
92
|
-
end
|
93
|
-
|
94
|
-
# Replace child node of the ast node with new code.
|
95
|
-
# @param node [Node] ast node
|
96
|
-
# @param selectors [Array<Symbol>] selector names of child node.
|
97
|
-
# @param with [String] code need to be replaced with.
|
98
|
-
# @example
|
99
|
-
# source code of the ast node is
|
100
|
-
# assert(object.empty?)
|
101
|
-
# then we call
|
102
|
-
# mutation.replace(node, :message, with: 'assert_empty')
|
103
|
-
# mutation.replace(node, :arguments, with: '{{arguments.first.receiver}}')
|
104
|
-
# the source code will be rewritten to
|
105
|
-
# assert_empty(object)
|
106
|
-
def replace(node, *selectors, with:)
|
107
|
-
@actions << NodeMutation::ReplaceAction.new(node, *selectors, with: with, adapter: @adapter).process
|
108
|
-
end
|
109
|
-
|
110
|
-
# Replace source code of the ast node with new code.
|
111
|
-
# @param node [Node] ast node
|
112
|
-
# @param code [String] code need to be replaced with.
|
113
|
-
# @example
|
114
|
-
# source code of the ast node is
|
115
|
-
# obj.stub(:foo => 1, :bar => 2)
|
116
|
-
# then we call
|
117
|
-
# replace_with 'allow({{receiver}}).to receive_messages({{arguments}})'
|
118
|
-
# the source code will be rewritten to
|
119
|
-
# allow(obj).to receive_messages(:foo => 1, :bar => 2)
|
120
|
-
def replace_with(node, code)
|
121
|
-
@actions << NodeMutation::ReplaceWithAction.new(node, code, adapter: @adapter).process
|
122
|
-
end
|
123
|
-
|
124
|
-
# Wrap source code of the ast node with prefix and suffix code.
|
125
|
-
# @param node [Node] ast node
|
126
|
-
# @param prefix [String] prefix code need to be wrapped with.
|
127
|
-
# @param suffix [String] suffix code need to be wrapped with.
|
128
|
-
# @param newline [Boolean] add newline after prefix and before suffix.
|
129
|
-
# @example
|
130
|
-
# source code of the ast node is
|
131
|
-
# class Foobar
|
132
|
-
# end
|
133
|
-
# then we call
|
134
|
-
# wrap(node, prefix: 'module Synvert', suffix: 'end', newline: true)
|
135
|
-
# the source code will be rewritten to
|
136
|
-
# module Synvert
|
137
|
-
# class Foobar
|
138
|
-
# end
|
139
|
-
# end
|
140
|
-
def wrap(node, prefix:, suffix:, newline: false)
|
141
|
-
if newline
|
142
|
-
indentation = @adapter.get_start_loc(node).column
|
143
|
-
group do
|
144
|
-
insert node, prefix + "\n" + (' ' * indentation), at: 'beginning'
|
145
|
-
insert node, "\n" + (' ' * indentation) + suffix, at: 'end'
|
146
|
-
indent node
|
147
|
-
end
|
148
|
-
else
|
149
|
-
group do
|
150
|
-
insert node, prefix, at: 'beginning'
|
151
|
-
insert node, suffix, at: 'end'
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
# Indent source code of the ast node
|
157
|
-
# @param node [Node] ast node
|
158
|
-
# @example
|
159
|
-
# source code of ast node is
|
160
|
-
# class Foobar
|
161
|
-
# end
|
162
|
-
# then we call
|
163
|
-
# indent(node)
|
164
|
-
# the source code will be rewritten to
|
165
|
-
# class Foobar
|
166
|
-
# end
|
167
|
-
def indent(node)
|
168
|
-
@actions << NodeMutation::IndentAction.new(node, adapter: @adapter).process
|
169
|
-
end
|
170
|
-
|
171
|
-
# No operation.
|
172
|
-
# @param node [Node] ast node
|
173
|
-
def noop(node)
|
174
|
-
@actions << NodeMutation::NoopAction.new(node, adapter: @adapter).process
|
175
|
-
end
|
176
|
-
|
177
|
-
# group multiple actions
|
178
|
-
def group(&block)
|
179
|
-
@actions << NodeMutation::GroupAction.new(adapter: @adapter, &block).process
|
180
|
-
end
|
181
|
-
end
|