node_mutation 1.11.0 → 1.12.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 +8 -0
- data/Gemfile.lock +1 -1
- data/lib/node_mutation/parser_adapter.rb +69 -47
- data/lib/node_mutation/result.rb +14 -24
- data/lib/node_mutation/struct.rb +7 -0
- data/lib/node_mutation/version.rb +1 -1
- data/lib/node_mutation.rb +8 -5
- data/sig/node_mutation/adapter.rbs +3 -3
- data/sig/node_mutation/result.rbs +2 -4
- data/sig/node_mutation/strategy.rbs +7 -0
- data/sig/node_mutation/struct.rbs +17 -0
- data/sig/node_mutation.rbs +1 -5
- metadata +6 -5
- data/lib/node_mutation/location.rb +0 -3
- data/lib/node_mutation/range.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 377cc05adfb7a9f55647b1850a325d9ddcb20004e2574af39657248bd05a51b4
|
4
|
+
data.tar.gz: 233c08e3fa49855270f62c11e1d9587b77886e9a6edded54f27096a9dc951849
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 593a0319dc715d587137e840d66694ed6f8c5d4a73312eb20847eee8383b4f47910f25d1d14f1e3fb95bee3ee1ab6627a08fdd2fa40c837c1a4d8e3422237066
|
7
|
+
data.tar.gz: 9aca39fb58ae4b02687a310fdcc3a7f388ebc86bcdce29b8efff24069077e3ed9194c9556bd833737160c8a220af87c010eedfd588e71f98c5b3bdae0d578cd3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# NodeMutation
|
2
2
|
|
3
|
+
## 1.12.1 (2023-03-23)
|
4
|
+
|
5
|
+
* Define `Action`, `Location` and `Range` in `NodeMutation::Struct`
|
6
|
+
|
7
|
+
## 1.12.0 (2023-03-23)
|
8
|
+
|
9
|
+
* Support `{key}_pair` for a `hash` node
|
10
|
+
|
3
11
|
## 1.11.0 (2023-03-20)
|
4
12
|
|
5
13
|
* Calculate position properly for `add_comma`
|
data/Gemfile.lock
CHANGED
@@ -17,41 +17,36 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
17
17
|
def rewritten_source(node, code)
|
18
18
|
code.gsub(/{{(.+?)}}/m) do
|
19
19
|
old_code = Regexp.last_match(1)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
20
|
+
evaluated = child_node_by_name(node, old_code)
|
21
|
+
case evaluated
|
22
|
+
when Parser::AST::Node
|
23
|
+
if evaluated.type == :args
|
24
|
+
evaluated.loc.expression.source[1...-1]
|
25
|
+
else
|
26
|
+
evaluated.loc.expression.source
|
27
|
+
end
|
28
|
+
when Array
|
29
|
+
if evaluated.size > 0
|
30
|
+
file_source = file_content(evaluated.first)
|
31
|
+
source = file_source[evaluated.first.loc.expression.begin_pos...evaluated.last.loc.expression.end_pos]
|
32
|
+
lines = source.split "\n"
|
33
|
+
lines_count = lines.length
|
34
|
+
if lines_count > 1 && lines_count == evaluated.size
|
35
|
+
new_code = []
|
36
|
+
lines.each_with_index { |line, index|
|
37
|
+
new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
|
38
|
+
}
|
39
|
+
new_code.join("\n")
|
27
40
|
else
|
28
|
-
|
41
|
+
source
|
29
42
|
end
|
30
|
-
when Array
|
31
|
-
if evaluated.size > 0
|
32
|
-
file_source = file_content(evaluated.first)
|
33
|
-
source = file_source[evaluated.first.loc.expression.begin_pos...evaluated.last.loc.expression.end_pos]
|
34
|
-
lines = source.split "\n"
|
35
|
-
lines_count = lines.length
|
36
|
-
if lines_count > 1 && lines_count == evaluated.size
|
37
|
-
new_code = []
|
38
|
-
lines.each_with_index { |line, index|
|
39
|
-
new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
|
40
|
-
}
|
41
|
-
new_code.join("\n")
|
42
|
-
else
|
43
|
-
source
|
44
|
-
end
|
45
|
-
end
|
46
|
-
when String, Symbol, Integer, Float
|
47
|
-
evaluated
|
48
|
-
when NilClass
|
49
|
-
''
|
50
|
-
else
|
51
|
-
raise "can not parse \"#{code}\""
|
52
43
|
end
|
44
|
+
when String, Symbol, Integer, Float
|
45
|
+
evaluated
|
46
|
+
when NilClass
|
47
|
+
''
|
53
48
|
else
|
54
|
-
raise
|
49
|
+
raise "can not parse \"#{code}\""
|
55
50
|
end
|
56
51
|
end
|
57
52
|
end
|
@@ -70,7 +65,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
70
65
|
"#{direct_child_name} is not supported for #{get_source(node)}" unless child_node
|
71
66
|
return child_node_range(child_node, nested_child_name) if nested_child_name
|
72
67
|
|
73
|
-
return NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
68
|
+
return NodeMutation::Struct::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
74
69
|
end
|
75
70
|
|
76
71
|
raise NodeMutation::MethodNotSupported,
|
@@ -79,35 +74,50 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
79
74
|
child_node = node.send(direct_child_name)
|
80
75
|
return child_node_range(child_node, nested_child_name) if nested_child_name
|
81
76
|
|
82
|
-
return NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
77
|
+
return NodeMutation::Struct::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
83
78
|
end
|
84
79
|
|
85
80
|
case [node.type, child_name.to_sym]
|
86
81
|
when %i[block pipes], %i[def parentheses], %i[defs parentheses]
|
87
|
-
NodeMutation::Range.new(
|
82
|
+
NodeMutation::Struct::Range.new(
|
83
|
+
node.arguments.first.loc.expression.begin_pos - 1,
|
84
|
+
node.arguments.last.loc.expression.end_pos + 1
|
85
|
+
)
|
88
86
|
when %i[block arguments], %i[def arguments], %i[defs arguments]
|
89
|
-
NodeMutation::Range.new(
|
87
|
+
NodeMutation::Struct::Range.new(
|
88
|
+
node.arguments.first.loc.expression.begin_pos,
|
89
|
+
node.arguments.last.loc.expression.end_pos
|
90
|
+
)
|
90
91
|
when %i[class name], %i[const name], %i[def name], %i[defs name]
|
91
|
-
NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
92
|
+
NodeMutation::Struct::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
92
93
|
when %i[defs dot]
|
93
|
-
NodeMutation::Range.new(node.loc.operator.begin_pos, node.loc.operator.end_pos) if node.loc.operator
|
94
|
+
NodeMutation::Struct::Range.new(node.loc.operator.begin_pos, node.loc.operator.end_pos) if node.loc.operator
|
94
95
|
when %i[defs self]
|
95
|
-
NodeMutation::Range.new(node.loc.operator.begin_pos - 'self'.length, node.loc.operator.begin_pos)
|
96
|
+
NodeMutation::Struct::Range.new(node.loc.operator.begin_pos - 'self'.length, node.loc.operator.begin_pos)
|
96
97
|
when %i[lvasgn variable], %i[ivasgn variable], %i[cvasgn variable], %i[gvasgn variable]
|
97
|
-
NodeMutation::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
98
|
+
NodeMutation::Struct::Range.new(node.loc.name.begin_pos, node.loc.name.end_pos)
|
98
99
|
when %i[send dot], %i[csend dot]
|
99
|
-
NodeMutation::Range.new(node.loc.dot.begin_pos, node.loc.dot.end_pos) if node.loc.dot
|
100
|
+
NodeMutation::Struct::Range.new(node.loc.dot.begin_pos, node.loc.dot.end_pos) if node.loc.dot
|
100
101
|
when %i[send message], %i[csend message]
|
101
102
|
if node.loc.operator
|
102
|
-
NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.operator.end_pos)
|
103
|
+
NodeMutation::Struct::Range.new(node.loc.selector.begin_pos, node.loc.operator.end_pos)
|
103
104
|
else
|
104
|
-
NodeMutation::Range.new(node.loc.selector.begin_pos, node.loc.selector.end_pos)
|
105
|
+
NodeMutation::Struct::Range.new(node.loc.selector.begin_pos, node.loc.selector.end_pos)
|
105
106
|
end
|
106
107
|
when %i[send parentheses], %i[csend parentheses]
|
107
108
|
if node.loc.begin && node.loc.end
|
108
|
-
NodeMutation::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
109
|
+
NodeMutation::Struct::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
109
110
|
end
|
110
111
|
else
|
112
|
+
if node.type == :hash && child_name.to_s.end_with?('_pair')
|
113
|
+
pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == child_name.to_s[0..-6] }
|
114
|
+
raise NodeMutation::MethodNotSupported,
|
115
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
|
116
|
+
return child_node_range(pair, nested_child_name) if nested_child_name
|
117
|
+
|
118
|
+
return NodeMutation::Struct::Range.new(pair_node.loc.expression.begin_pos, pair_node.loc.expression.end_pos)
|
119
|
+
end
|
120
|
+
|
111
121
|
raise NodeMutation::MethodNotSupported,
|
112
122
|
"#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
|
113
123
|
|
@@ -119,7 +129,7 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
119
129
|
|
120
130
|
if child_node.is_a?(Parser::AST::Node)
|
121
131
|
return(
|
122
|
-
NodeMutation::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
132
|
+
NodeMutation::Struct::Range.new(child_node.loc.expression.begin_pos, child_node.loc.expression.end_pos)
|
123
133
|
)
|
124
134
|
end
|
125
135
|
|
@@ -127,7 +137,10 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
127
137
|
return nil if child_node.empty?
|
128
138
|
|
129
139
|
return(
|
130
|
-
NodeMutation::Range.new(
|
140
|
+
NodeMutation::Struct::Range.new(
|
141
|
+
child_node.first.loc.expression.begin_pos,
|
142
|
+
child_node.last.loc.expression.end_pos
|
143
|
+
)
|
131
144
|
)
|
132
145
|
end
|
133
146
|
end
|
@@ -142,12 +155,12 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
142
155
|
|
143
156
|
def get_start_loc(node)
|
144
157
|
begin_loc = node.loc.expression.begin
|
145
|
-
NodeMutation::Location.new(begin_loc.line, begin_loc.column)
|
158
|
+
NodeMutation::Struct::Location.new(begin_loc.line, begin_loc.column)
|
146
159
|
end
|
147
160
|
|
148
161
|
def get_end_loc(node)
|
149
162
|
end_loc = node.loc.expression.end
|
150
|
-
NodeMutation::Location.new(end_loc.line, end_loc.column)
|
163
|
+
NodeMutation::Struct::Location.new(end_loc.line, end_loc.column)
|
151
164
|
end
|
152
165
|
|
153
166
|
def get_indent(node)
|
@@ -178,6 +191,15 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
178
191
|
return child_node
|
179
192
|
end
|
180
193
|
|
194
|
+
if node.is_a?(Parser::AST::Node) && node.type == :hash && direct_child_name.end_with?('_pair')
|
195
|
+
pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == direct_child_name[0..-6] }
|
196
|
+
raise NodeMutation::MethodNotSupported,
|
197
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
|
198
|
+
return child_node_by_name(pair_node, nested_child_name) if nested_child_name
|
199
|
+
|
200
|
+
return pair_node
|
201
|
+
end
|
202
|
+
|
181
203
|
if node.respond_to?(direct_child_name)
|
182
204
|
child_node = node.send(direct_child_name)
|
183
205
|
elsif direct_child_name.include?('(') && direct_child_name.include?(')')
|
data/lib/node_mutation/result.rb
CHANGED
@@ -1,41 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class NodeMutation::Result
|
4
|
-
attr_accessor :file_path
|
4
|
+
attr_accessor :file_path, :new_source
|
5
|
+
attr_reader :actions
|
5
6
|
|
6
|
-
def initialize(
|
7
|
-
@
|
7
|
+
def initialize(affected:, conflicted:)
|
8
|
+
@affected = affected
|
9
|
+
@conflicted = conflicted
|
10
|
+
@actions = []
|
8
11
|
end
|
9
12
|
|
10
13
|
def affected?
|
11
|
-
@
|
14
|
+
@affected
|
12
15
|
end
|
13
16
|
|
14
17
|
def conflicted?
|
15
|
-
@
|
18
|
+
@conflicted
|
16
19
|
end
|
17
20
|
|
18
|
-
def actions
|
19
|
-
@
|
20
|
-
end
|
21
|
-
|
22
|
-
def new_source
|
23
|
-
@options[:new_source]
|
21
|
+
def actions=(actions)
|
22
|
+
@actions = actions.map { |action| NodeMutation::Struct::Action.new(action.start, action.end, action.new_code) }
|
24
23
|
end
|
25
24
|
|
26
25
|
def to_json(*args)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
hash = { file_path: file_path }
|
32
|
-
@options.each do |key, value|
|
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
|
38
|
-
end
|
39
|
-
hash
|
26
|
+
data = { affected: affected?, conflicted: conflicted? }
|
27
|
+
data[:new_source] = new_source if new_source
|
28
|
+
data[:actions] = actions unless actions.empty?
|
29
|
+
data.to_json(*args)
|
40
30
|
end
|
41
31
|
end
|
data/lib/node_mutation.rb
CHANGED
@@ -18,10 +18,9 @@ class NodeMutation
|
|
18
18
|
autoload :ReplaceWithAction, 'node_mutation/action/replace_with_action'
|
19
19
|
autoload :WrapAction, 'node_mutation/action/wrap_action'
|
20
20
|
autoload :NoopAction, 'node_mutation/action/noop_action'
|
21
|
-
autoload :Range, 'node_mutation/range'
|
22
|
-
autoload :Location, 'node_mutation/location'
|
23
21
|
autoload :Result, 'node_mutation/result'
|
24
22
|
autoload :Strategy, 'node_mutation/strategy'
|
23
|
+
autoload :Struct, 'node_mutation/struct'
|
25
24
|
|
26
25
|
attr_reader :actions
|
27
26
|
|
@@ -229,7 +228,9 @@ class NodeMutation
|
|
229
228
|
@actions.reverse_each do |action|
|
230
229
|
source[action.start...action.end] = action.new_code if action.new_code
|
231
230
|
end
|
232
|
-
NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty
|
231
|
+
result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
|
232
|
+
result.new_source = source
|
233
|
+
result
|
233
234
|
end
|
234
235
|
|
235
236
|
# Test actions and return the actions.
|
@@ -241,7 +242,7 @@ class NodeMutation
|
|
241
242
|
# @return {NodeMutation::Result}
|
242
243
|
def test
|
243
244
|
if @actions.length == 0
|
244
|
-
return NodeMutation::Result.new(affected: false, conflicted: false
|
245
|
+
return NodeMutation::Result.new(affected: false, conflicted: false)
|
245
246
|
end
|
246
247
|
|
247
248
|
@actions.sort_by! { |action| [action.start, action.end] }
|
@@ -250,7 +251,9 @@ class NodeMutation
|
|
250
251
|
raise ConflictActionError, "mutation actions are conflicted"
|
251
252
|
end
|
252
253
|
|
253
|
-
NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty
|
254
|
+
result = NodeMutation::Result.new(affected: true, conflicted: !conflict_actions.empty?)
|
255
|
+
result.actions = @actions
|
256
|
+
result
|
254
257
|
end
|
255
258
|
|
256
259
|
private
|
@@ -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) -> NodeMutation::Range
|
8
|
+
def child_node_range: (node: T, child_name: String) -> NodeMutation::Struct::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) -> NodeMutation::Location
|
14
|
+
def get_start_loc: (node: T) -> NodeMutation::Struct::Location
|
15
15
|
|
16
|
-
def get_end_loc: (node: T) -> NodeMutation::Location
|
16
|
+
def get_end_loc: (node: T) -> NodeMutation::Struct::Location
|
17
17
|
|
18
18
|
def get_indent: (node: T) -> Integer
|
19
19
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
class NodeMutation::Result
|
2
2
|
attr_accessor file_path (): String
|
3
|
+
attr_accessor new_source (): String
|
4
|
+
attr_accessor actions (): Array[NodeMutation::Struct::Action]
|
3
5
|
|
4
6
|
def initialize: (source: String) -> NodeMutation::Result
|
5
7
|
|
@@ -7,9 +9,5 @@ class NodeMutation::Result
|
|
7
9
|
|
8
10
|
def conflicted?: () -> bool
|
9
11
|
|
10
|
-
def new_source: () -> String
|
11
|
-
|
12
|
-
def actions: () -> Array[Hash]
|
13
|
-
|
14
12
|
def to_json: (*args) -> String
|
15
13
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class NodeMutation::Struct
|
2
|
+
class Action < ::Struct
|
3
|
+
prop :start, Integer
|
4
|
+
prop :end, Integer
|
5
|
+
prop :new_code, String
|
6
|
+
end
|
7
|
+
|
8
|
+
class Location < ::Struct
|
9
|
+
prop :line, Integer
|
10
|
+
prop :column, Integer
|
11
|
+
end
|
12
|
+
|
13
|
+
class Range < ::Struct
|
14
|
+
prop :start, Integer
|
15
|
+
prop :end, Integer
|
16
|
+
end
|
17
|
+
end
|
data/sig/node_mutation.rbs
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module NodeMutation[T]
|
2
|
-
VERSION:
|
2
|
+
VERSION: String
|
3
3
|
|
4
4
|
class MethodNotSupported < StandardError
|
5
5
|
end
|
@@ -7,10 +7,6 @@ module NodeMutation[T]
|
|
7
7
|
class ConflictActionError < StandardError
|
8
8
|
end
|
9
9
|
|
10
|
-
KEEP_RUNNING: Integer
|
11
|
-
|
12
|
-
THROW_ERROR: Integer
|
13
|
-
|
14
10
|
attr_reader actions: Array[NodeMutation::Action]
|
15
11
|
|
16
12
|
def self.configure: (options: { adapter: NodeMutation::Adapter, strategy: Integer, tab_width: Integer }) -> void
|
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.12.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-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: erubis
|
@@ -51,16 +51,17 @@ 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
|
55
54
|
- lib/node_mutation/parser_adapter.rb
|
56
|
-
- lib/node_mutation/range.rb
|
57
55
|
- lib/node_mutation/result.rb
|
58
56
|
- lib/node_mutation/strategy.rb
|
57
|
+
- lib/node_mutation/struct.rb
|
59
58
|
- lib/node_mutation/version.rb
|
60
59
|
- node_mutation.gemspec
|
61
60
|
- sig/node_mutation.rbs
|
62
61
|
- sig/node_mutation/adapter.rbs
|
63
62
|
- sig/node_mutation/result.rbs
|
63
|
+
- sig/node_mutation/strategy.rbs
|
64
|
+
- sig/node_mutation/struct.rbs
|
64
65
|
homepage: https://github.com/xinminlabs/node-mutation-ruby
|
65
66
|
licenses: []
|
66
67
|
metadata:
|
@@ -82,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
83
|
- !ruby/object:Gem::Version
|
83
84
|
version: '0'
|
84
85
|
requirements: []
|
85
|
-
rubygems_version: 3.4.
|
86
|
+
rubygems_version: 3.4.7
|
86
87
|
signing_key:
|
87
88
|
specification_version: 4
|
88
89
|
summary: ast node mutation apis
|
data/lib/node_mutation/range.rb
DELETED