node_mutation 1.9.3 → 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 +9 -0
- data/Gemfile.lock +3 -3
- 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 +33 -35
- 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
@@ -1,5 +1,14 @@
|
|
1
1
|
# NodeMutation
|
2
2
|
|
3
|
+
## 1.10.1 (2023-03-13)
|
4
|
+
|
5
|
+
* Remove `OpenStruct`, use `Struct` instead
|
6
|
+
|
7
|
+
## 1.10.0 (2023-03-01)
|
8
|
+
|
9
|
+
* Support `variable` of `lvasgn`, `ivasgn`, `cvasgn`, and `gvasgn` node in `child_node_range`
|
10
|
+
* Update `parser_node_ext` to 1.0.0
|
11
|
+
|
3
12
|
## 1.9.3 (2023-02-15)
|
4
13
|
|
5
14
|
* Remove engine
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
node_mutation (1.
|
4
|
+
node_mutation (1.10.1)
|
5
5
|
erubis
|
6
6
|
|
7
7
|
GEM
|
@@ -36,9 +36,9 @@ GEM
|
|
36
36
|
notiffany (0.1.3)
|
37
37
|
nenv (~> 0.1)
|
38
38
|
shellany (~> 0.0)
|
39
|
-
parser (3.1.
|
39
|
+
parser (3.2.1.0)
|
40
40
|
ast (~> 2.4.1)
|
41
|
-
parser_node_ext (0.
|
41
|
+
parser_node_ext (1.0.0)
|
42
42
|
parser
|
43
43
|
pry (0.14.1)
|
44
44
|
coderay (~> 1.1)
|
@@ -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,51 +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)
|
94
|
+
when %i[lvasgn variable], %i[ivasgn variable], %i[cvasgn variable], %i[gvasgn variable]
|
95
|
+
NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
98
96
|
when %i[send dot], %i[csend dot]
|
99
|
-
|
97
|
+
NodeMutation::Range.new(node.loc.dot.begin_pos, node.loc.dot.end_pos) if node.loc.dot
|
100
98
|
when %i[send message], %i[csend message]
|
101
99
|
if node.loc.operator
|
102
|
-
|
100
|
+
NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.operator.end_pos)
|
103
101
|
else
|
104
|
-
|
102
|
+
NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.selector.end_pos)
|
105
103
|
end
|
106
104
|
when %i[send parentheses], %i[csend parentheses]
|
107
105
|
if node.loc.begin && node.loc.end
|
108
|
-
|
106
|
+
NodeMutation::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
109
107
|
end
|
110
108
|
else
|
111
|
-
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)
|
112
111
|
|
113
112
|
child_node = node.send(direct_child_name)
|
114
113
|
|
@@ -118,10 +117,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
118
117
|
|
119
118
|
if child_node.is_a?(Parser::AST::Node)
|
120
119
|
return(
|
121
|
-
|
122
|
-
start: child_node.loc.expression.begin_pos,
|
123
|
-
end: child_node.loc.expression.end_pos
|
124
|
-
)
|
120
|
+
NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
125
121
|
)
|
126
122
|
end
|
127
123
|
|
@@ -129,10 +125,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
129
125
|
return nil if child_node.empty?
|
130
126
|
|
131
127
|
return(
|
132
|
-
|
133
|
-
start: child_node.first.loc.expression.begin_pos,
|
134
|
-
end: child_node.last.loc.expression.end_pos
|
135
|
-
)
|
128
|
+
NodeMutation::Range.new(child_node.first.loc.expression.begin_pos, child_node.last.loc.expression.end_pos)
|
136
129
|
)
|
137
130
|
end
|
138
131
|
end
|
@@ -147,12 +140,12 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
147
140
|
|
148
141
|
def get_start_loc(node)
|
149
142
|
begin_loc = node.loc.expression.begin
|
150
|
-
|
143
|
+
NodeMutation::Location.new(begin_loc.line, begin_loc.column)
|
151
144
|
end
|
152
145
|
|
153
146
|
def get_end_loc(node)
|
154
147
|
end_loc = node.loc.expression.end
|
155
|
-
|
148
|
+
NodeMutation::Location.new(end_loc.line, end_loc.column)
|
156
149
|
end
|
157
150
|
|
158
151
|
def get_indent(node)
|
@@ -167,14 +160,19 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
167
160
|
if node.is_a?(Array)
|
168
161
|
if direct_child_name =~ INDEX_REGEXP
|
169
162
|
child_node = node[direct_child_name.to_i]
|
170
|
-
raise NodeMutation::MethodNotSupported,
|
163
|
+
raise NodeMutation::MethodNotSupported,
|
164
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless child_node
|
171
165
|
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
166
|
+
|
172
167
|
return child_node
|
173
168
|
end
|
174
169
|
|
175
|
-
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
|
+
|
176
173
|
child_node = node.send(direct_child_name)
|
177
174
|
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
175
|
+
|
178
176
|
return child_node
|
179
177
|
end
|
180
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.
|
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-
|
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
|