node_mutation 1.10.0 → 1.10.1
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/delete_action.rb +2 -2
- data/lib/node_mutation/action/replace_action.rb +4 -2
- data/lib/node_mutation/action/wrap_action.rb +1 -1
- data/lib/node_mutation/action.rb +2 -1
- data/lib/node_mutation/location.rb +3 -0
- data/lib/node_mutation/parser_adapter.rb +32 -36
- data/lib/node_mutation/range.rb +3 -0
- data/lib/node_mutation/result.rb +6 -2
- data/lib/node_mutation/version.rb +1 -1
- data/lib/node_mutation.rb +7 -19
- data/node_mutation.gemspec +5 -4
- data/sig/node_mutation/adapter.rbs +3 -3
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3f69bebea36b4152c7edb233d2d179bfee796988977c36f6375a12a240a77615
|
|
4
|
+
data.tar.gz: af1a35eb1b9ec9b3c657d976dd9b0b392d24288de6083f5d98c3d00dc036ff61
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b07a1795e19142226bd48215514d67cf0f3428ec1b03dbcfe49ed4f9825c962427943b6a1f633bc7d1627178354c3c30989af1a5e63dcbe125af54c98f280a45
|
|
7
|
+
data.tar.gz: f87aed954b86a4948939528ce1af8bbb779f4673ef8795cd498d015bce84d3abb271db2b44ffd65fdac2f571acbe8d03cfb2ae0cf54a8bd9d97780799e75a521
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -23,9 +23,9 @@ class NodeMutation::DeleteAction < NodeMutation::Action
|
|
|
23
23
|
# Calculate the begin and end positions.
|
|
24
24
|
def calculate_position
|
|
25
25
|
@start = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector) }
|
|
26
|
-
|
|
26
|
+
.compact.map(&:start).min
|
|
27
27
|
@end = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector) }
|
|
28
|
-
|
|
28
|
+
.compact.map(&:end).max
|
|
29
29
|
squeeze_spaces
|
|
30
30
|
remove_comma if @and_comma
|
|
31
31
|
end
|
|
@@ -23,7 +23,9 @@ class NodeMutation::ReplaceAction < NodeMutation::Action
|
|
|
23
23
|
|
|
24
24
|
# Calculate the begin the end positions.
|
|
25
25
|
def calculate_position
|
|
26
|
-
@start = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector).start }
|
|
27
|
-
|
|
26
|
+
@start = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector).start }
|
|
27
|
+
.min
|
|
28
|
+
@end = @selectors.map { |selector| NodeMutation.adapter.child_node_range(@node, selector).end }
|
|
29
|
+
.max
|
|
28
30
|
end
|
|
29
31
|
end
|
data/lib/node_mutation/action.rb
CHANGED
|
@@ -30,7 +30,8 @@ class NodeMutation::Action
|
|
|
30
30
|
# @return [String] rewritten code.
|
|
31
31
|
def new_code
|
|
32
32
|
if rewritten_source.split("\n").length > 1
|
|
33
|
-
"\n\n" + rewritten_source.split("\n").map { |line| indent(@node) + line }
|
|
33
|
+
"\n\n" + rewritten_source.split("\n").map { |line| indent(@node) + line }
|
|
34
|
+
.join("\n")
|
|
34
35
|
else
|
|
35
36
|
"\n" + indent(@node) + rewritten_source
|
|
36
37
|
end
|
|
@@ -64,53 +64,50 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
64
64
|
if node.is_a?(Array)
|
|
65
65
|
if direct_child_name =~ INDEX_REGEXP
|
|
66
66
|
child_node = node[direct_child_name.to_i]
|
|
67
|
-
raise NodeMutation::MethodNotSupported,
|
|
67
|
+
raise NodeMutation::MethodNotSupported,
|
|
68
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless child_node
|
|
68
69
|
return child_node_range(child_node, nested_child_name) if nested_child_name
|
|
69
|
-
|
|
70
|
+
|
|
71
|
+
return NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
|
70
72
|
end
|
|
71
73
|
|
|
72
|
-
raise NodeMutation::MethodNotSupported,
|
|
74
|
+
raise NodeMutation::MethodNotSupported,
|
|
75
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
|
|
76
|
+
|
|
73
77
|
child_node = node.send(direct_child_name)
|
|
74
78
|
return child_node_range(child_node, nested_child_name) if nested_child_name
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end: child_node.loc.expression.end_pos
|
|
78
|
-
)
|
|
79
|
+
|
|
80
|
+
return NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
|
79
81
|
end
|
|
80
82
|
|
|
81
83
|
case [node.type, child_name.to_sym]
|
|
82
84
|
when %i[block pipes], %i[def parentheses], %i[defs parentheses]
|
|
83
|
-
|
|
84
|
-
start: node.arguments.first.loc.expression.begin_pos - 1,
|
|
85
|
-
end: node.arguments.last.loc.expression.end_pos + 1
|
|
86
|
-
)
|
|
85
|
+
NodeMutation::Range.new(node.arguments.first.loc.expression.begin_pos - 1, node.arguments.last.loc.expression.end_pos + 1)
|
|
87
86
|
when %i[block arguments], %i[def arguments], %i[defs arguments]
|
|
88
|
-
|
|
89
|
-
start: node.arguments.first.loc.expression.begin_pos,
|
|
90
|
-
end: node.arguments.last.loc.expression.end_pos
|
|
91
|
-
)
|
|
87
|
+
NodeMutation::Range.new(node.arguments.first.loc.expression.begin_pos, node.arguments.last.loc.expression.end_pos)
|
|
92
88
|
when %i[class name], %i[const name], %i[def name], %i[defs name]
|
|
93
|
-
|
|
89
|
+
NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
|
94
90
|
when %i[defs dot]
|
|
95
|
-
|
|
91
|
+
NodeMutation::Range.new(node.loc.operator.begin_pos, node.loc.operator.end_pos) if node.loc.operator
|
|
96
92
|
when %i[defs self]
|
|
97
|
-
|
|
93
|
+
NodeMutation::Range.new(node.loc.operator.begin_pos - 'self'.length, node.loc.operator.begin_pos)
|
|
98
94
|
when %i[lvasgn variable], %i[ivasgn variable], %i[cvasgn variable], %i[gvasgn variable]
|
|
99
|
-
|
|
95
|
+
NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
|
100
96
|
when %i[send dot], %i[csend dot]
|
|
101
|
-
|
|
97
|
+
NodeMutation::Range.new(node.loc.dot.begin_pos, node.loc.dot.end_pos) if node.loc.dot
|
|
102
98
|
when %i[send message], %i[csend message]
|
|
103
99
|
if node.loc.operator
|
|
104
|
-
|
|
100
|
+
NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.operator.end_pos)
|
|
105
101
|
else
|
|
106
|
-
|
|
102
|
+
NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.selector.end_pos)
|
|
107
103
|
end
|
|
108
104
|
when %i[send parentheses], %i[csend parentheses]
|
|
109
105
|
if node.loc.begin && node.loc.end
|
|
110
|
-
|
|
106
|
+
NodeMutation::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
|
111
107
|
end
|
|
112
108
|
else
|
|
113
|
-
raise NodeMutation::MethodNotSupported,
|
|
109
|
+
raise NodeMutation::MethodNotSupported,
|
|
110
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
|
|
114
111
|
|
|
115
112
|
child_node = node.send(direct_child_name)
|
|
116
113
|
|
|
@@ -120,10 +117,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
120
117
|
|
|
121
118
|
if child_node.is_a?(Parser::AST::Node)
|
|
122
119
|
return(
|
|
123
|
-
|
|
124
|
-
start: child_node.loc.expression.begin_pos,
|
|
125
|
-
end: child_node.loc.expression.end_pos
|
|
126
|
-
)
|
|
120
|
+
NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
|
127
121
|
)
|
|
128
122
|
end
|
|
129
123
|
|
|
@@ -131,10 +125,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
131
125
|
return nil if child_node.empty?
|
|
132
126
|
|
|
133
127
|
return(
|
|
134
|
-
|
|
135
|
-
start: child_node.first.loc.expression.begin_pos,
|
|
136
|
-
end: child_node.last.loc.expression.end_pos
|
|
137
|
-
)
|
|
128
|
+
NodeMutation::Range.new(child_node.first.loc.expression.begin_pos, child_node.last.loc.expression.end_pos)
|
|
138
129
|
)
|
|
139
130
|
end
|
|
140
131
|
end
|
|
@@ -149,12 +140,12 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
149
140
|
|
|
150
141
|
def get_start_loc(node)
|
|
151
142
|
begin_loc = node.loc.expression.begin
|
|
152
|
-
|
|
143
|
+
NodeMutation::Location.new(begin_loc.line, begin_loc.column)
|
|
153
144
|
end
|
|
154
145
|
|
|
155
146
|
def get_end_loc(node)
|
|
156
147
|
end_loc = node.loc.expression.end
|
|
157
|
-
|
|
148
|
+
NodeMutation::Location.new(end_loc.line, end_loc.column)
|
|
158
149
|
end
|
|
159
150
|
|
|
160
151
|
def get_indent(node)
|
|
@@ -169,14 +160,19 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
169
160
|
if node.is_a?(Array)
|
|
170
161
|
if direct_child_name =~ INDEX_REGEXP
|
|
171
162
|
child_node = node[direct_child_name.to_i]
|
|
172
|
-
raise NodeMutation::MethodNotSupported,
|
|
163
|
+
raise NodeMutation::MethodNotSupported,
|
|
164
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless child_node
|
|
173
165
|
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
|
166
|
+
|
|
174
167
|
return child_node
|
|
175
168
|
end
|
|
176
169
|
|
|
177
|
-
raise NodeMutation::MethodNotSupported,
|
|
170
|
+
raise NodeMutation::MethodNotSupported,
|
|
171
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
|
|
172
|
+
|
|
178
173
|
child_node = node.send(direct_child_name)
|
|
179
174
|
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
|
175
|
+
|
|
180
176
|
return child_node
|
|
181
177
|
end
|
|
182
178
|
|
data/lib/node_mutation/result.rb
CHANGED
|
@@ -30,8 +30,12 @@ class NodeMutation::Result
|
|
|
30
30
|
def to_hash
|
|
31
31
|
hash = { file_path: file_path }
|
|
32
32
|
@options.each do |key, value|
|
|
33
|
-
|
|
33
|
+
if key == :actions
|
|
34
|
+
hash[:actions] = value.map { |action| { start: action.start, end: action.end, new_code: action.new_code } }
|
|
35
|
+
else
|
|
36
|
+
hash[key] = value
|
|
37
|
+
end
|
|
34
38
|
end
|
|
35
39
|
hash
|
|
36
40
|
end
|
|
37
|
-
end
|
|
41
|
+
end
|
data/lib/node_mutation.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'ostruct'
|
|
4
|
-
|
|
5
3
|
require_relative "node_mutation/version"
|
|
6
4
|
|
|
7
5
|
class NodeMutation
|
|
@@ -20,12 +18,14 @@ class NodeMutation
|
|
|
20
18
|
autoload :ReplaceWithAction, 'node_mutation/action/replace_with_action'
|
|
21
19
|
autoload :WrapAction, 'node_mutation/action/wrap_action'
|
|
22
20
|
autoload :NoopAction, 'node_mutation/action/noop_action'
|
|
21
|
+
autoload :Range, 'node_mutation/range'
|
|
22
|
+
autoload :Location, 'node_mutation/location'
|
|
23
23
|
autoload :Result, 'node_mutation/result'
|
|
24
24
|
autoload :Strategy, 'node_mutation/strategy'
|
|
25
25
|
|
|
26
26
|
attr_reader :actions
|
|
27
27
|
|
|
28
|
-
class <<self
|
|
28
|
+
class << self
|
|
29
29
|
# Configure NodeMutation
|
|
30
30
|
# @param [Hash] options options to configure
|
|
31
31
|
# @option options [NodeMutation::Adapter] :adapter the adpater
|
|
@@ -220,21 +220,17 @@ class NodeMutation
|
|
|
220
220
|
return NodeMutation::Result.new(affected: false, conflicted: false)
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
-
conflict_actions = []
|
|
224
223
|
source = +@source
|
|
225
224
|
@actions.sort_by! { |action| [action.start, action.end] }
|
|
226
225
|
conflict_actions = get_conflict_actions
|
|
227
226
|
if conflict_actions.size > 0 && strategy?(Strategy::THROW_ERROR)
|
|
228
227
|
raise ConflictActionError, "mutation actions are conflicted"
|
|
229
228
|
end
|
|
229
|
+
|
|
230
230
|
@actions.reverse_each do |action|
|
|
231
231
|
source[action.start...action.end] = action.new_code if action.new_code
|
|
232
232
|
end
|
|
233
|
-
NodeMutation::Result.new(
|
|
234
|
-
affected: true,
|
|
235
|
-
conflicted: !conflict_actions.empty?,
|
|
236
|
-
new_source: source
|
|
237
|
-
)
|
|
233
|
+
NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?, new_source: source)
|
|
238
234
|
end
|
|
239
235
|
|
|
240
236
|
# Test actions and return the actions.
|
|
@@ -249,17 +245,13 @@ class NodeMutation
|
|
|
249
245
|
return NodeMutation::Result.new(affected: false, conflicted: false, actions: [])
|
|
250
246
|
end
|
|
251
247
|
|
|
252
|
-
conflict_actions = []
|
|
253
248
|
@actions.sort_by! { |action| [action.start, action.end] }
|
|
254
249
|
conflict_actions = get_conflict_actions
|
|
255
250
|
if conflict_actions.size > 0 && strategy?(Strategy::THROW_ERROR)
|
|
256
251
|
raise ConflictActionError, "mutation actions are conflicted"
|
|
257
252
|
end
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
conflicted: !conflict_actions.empty?,
|
|
261
|
-
actions: format_actions(@actions)
|
|
262
|
-
)
|
|
253
|
+
|
|
254
|
+
NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?, actions: @actions)
|
|
263
255
|
end
|
|
264
256
|
|
|
265
257
|
private
|
|
@@ -294,8 +286,4 @@ class NodeMutation
|
|
|
294
286
|
def strategy?(strategy)
|
|
295
287
|
NodeMutation.strategy & strategy == strategy
|
|
296
288
|
end
|
|
297
|
-
|
|
298
|
-
def format_actions(actions)
|
|
299
|
-
actions.map { |action| OpenStruct.new(start: action.start, end: action.end, new_code: action.new_code ) }
|
|
300
|
-
end
|
|
301
289
|
end
|
data/node_mutation.gemspec
CHANGED
|
@@ -19,11 +19,12 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
|
|
20
20
|
# Specify which files should be added to the gem when it is released.
|
|
21
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
22
|
-
spec.files =
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
spec.files =
|
|
23
|
+
Dir.chdir(File.expand_path(__dir__)) do
|
|
24
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
25
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
26
|
+
end
|
|
25
27
|
end
|
|
26
|
-
end
|
|
27
28
|
spec.bindir = "exe"
|
|
28
29
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
29
30
|
spec.require_paths = ["lib"]
|
|
@@ -5,15 +5,15 @@ class NodeMutation::Adapter[T]
|
|
|
5
5
|
|
|
6
6
|
def file_content: (node: T) -> String
|
|
7
7
|
|
|
8
|
-
def child_node_range: (node: T, child_name: String) ->
|
|
8
|
+
def child_node_range: (node: T, child_name: String) -> NodeMutation::Range
|
|
9
9
|
|
|
10
10
|
def get_start: (node: T) -> Integer
|
|
11
11
|
|
|
12
12
|
def get_end: (node: T) -> Integer
|
|
13
13
|
|
|
14
|
-
def get_start_loc: (node: T) ->
|
|
14
|
+
def get_start_loc: (node: T) -> NodeMutation::Location
|
|
15
15
|
|
|
16
|
-
def get_end_loc: (node: T) ->
|
|
16
|
+
def get_end_loc: (node: T) -> NodeMutation::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.10.
|
|
4
|
+
version: 1.10.1
|
|
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-03-
|
|
11
|
+
date: 2023-03-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: erubis
|
|
@@ -51,7 +51,9 @@ files:
|
|
|
51
51
|
- lib/node_mutation/action/replace_with_action.rb
|
|
52
52
|
- lib/node_mutation/action/wrap_action.rb
|
|
53
53
|
- lib/node_mutation/adapter.rb
|
|
54
|
+
- lib/node_mutation/location.rb
|
|
54
55
|
- lib/node_mutation/parser_adapter.rb
|
|
56
|
+
- lib/node_mutation/range.rb
|
|
55
57
|
- lib/node_mutation/result.rb
|
|
56
58
|
- lib/node_mutation/strategy.rb
|
|
57
59
|
- lib/node_mutation/version.rb
|
|
@@ -80,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
80
82
|
- !ruby/object:Gem::Version
|
|
81
83
|
version: '0'
|
|
82
84
|
requirements: []
|
|
83
|
-
rubygems_version: 3.4.
|
|
85
|
+
rubygems_version: 3.4.6
|
|
84
86
|
signing_key:
|
|
85
87
|
specification_version: 4
|
|
86
88
|
summary: ast node mutation apis
|