node_mutation 1.16.0 → 1.17.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 +4 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +9 -3
- data/README.md +1 -1
- data/lib/node_mutation/{parser_adapter.rb → adapter/parser.rb} +0 -38
- data/lib/node_mutation/adapter/syntax_tree.rb +115 -0
- data/lib/node_mutation/adapter.rb +2 -0
- data/lib/node_mutation/version.rb +1 -1
- data/lib/node_mutation.rb +2 -1
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7df63f45429db131b4023d42d1fcab4fdac401358376f0d2ed16722627484bf0
|
|
4
|
+
data.tar.gz: a9fdadb2c0dd0d82cd709040b2c154b4e2bd75b95ca71082e00e5768e15f476a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e6194b0d8d80e3b8e553e06c287663a4595bd259f91dbdc9c469c83f4fbabe0781b1ef959fb57341e4d5499993444f21c7fd09283b22f67908495c770446bb2
|
|
7
|
+
data.tar.gz: 5b99e2f025960eb624f9b82a40a37a1befc63e4787a8cc3a3cd2067e378e9d4b9dfe5f71f7cee2ec922a7171658704a29e0ff799a16389c62b5f27307e818327
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
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.17.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -34,10 +34,11 @@ GEM
|
|
|
34
34
|
notiffany (0.1.3)
|
|
35
35
|
nenv (~> 0.1)
|
|
36
36
|
shellany (~> 0.0)
|
|
37
|
-
parser (3.2.1
|
|
37
|
+
parser (3.2.2.1)
|
|
38
38
|
ast (~> 2.4.1)
|
|
39
|
-
parser_node_ext (1.
|
|
39
|
+
parser_node_ext (1.1.0)
|
|
40
40
|
parser
|
|
41
|
+
prettier_print (1.2.1)
|
|
41
42
|
pry (0.14.1)
|
|
42
43
|
coderay (~> 1.1)
|
|
43
44
|
method_source (~> 1.0)
|
|
@@ -59,6 +60,10 @@ GEM
|
|
|
59
60
|
rspec-support (~> 3.11.0)
|
|
60
61
|
rspec-support (3.11.0)
|
|
61
62
|
shellany (0.0.1)
|
|
63
|
+
syntax_tree (6.1.1)
|
|
64
|
+
prettier_print (>= 1.2.0)
|
|
65
|
+
syntax_tree_ext (0.3.0)
|
|
66
|
+
syntax_tree
|
|
62
67
|
thor (1.2.1)
|
|
63
68
|
|
|
64
69
|
PLATFORMS
|
|
@@ -74,6 +79,7 @@ DEPENDENCIES
|
|
|
74
79
|
parser_node_ext
|
|
75
80
|
rake (~> 13.0)
|
|
76
81
|
rspec (~> 3.0)
|
|
82
|
+
syntax_tree_ext
|
|
77
83
|
|
|
78
84
|
BUNDLED WITH
|
|
79
85
|
2.3.7
|
data/README.md
CHANGED
|
@@ -74,7 +74,7 @@ we define an [Adapter](https://github.com/xinminlabs/node-mutation-ruby/blob/mai
|
|
|
74
74
|
if you implement the Adapter interface, you can set it as NodeMutation's adapter.
|
|
75
75
|
|
|
76
76
|
```ruby
|
|
77
|
-
NodeMutation.configure(adapter:
|
|
77
|
+
NodeMutation.configure(adapter: SyntaxTreeAdapter.new) // default is ParserAdapter
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### strategy
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
INDEX_REGEXP = /\A-?\d+\z/
|
|
4
|
-
|
|
5
3
|
class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
6
4
|
def get_source(node)
|
|
7
5
|
if node.is_a?(Array)
|
|
@@ -111,24 +109,6 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
111
109
|
NodeMutation::Struct::Range.new(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
|
112
110
|
end
|
|
113
111
|
else
|
|
114
|
-
if node.type == :hash && child_name.to_s.end_with?('_pair')
|
|
115
|
-
pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == child_name.to_s[0..-6] }
|
|
116
|
-
raise NodeMutation::MethodNotSupported,
|
|
117
|
-
"#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
|
|
118
|
-
return child_node_range(pair, nested_child_name) if nested_child_name
|
|
119
|
-
|
|
120
|
-
return NodeMutation::Struct::Range.new(pair_node.loc.expression.begin_pos, pair_node.loc.expression.end_pos)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
if node.type == :hash && child_name.to_s.end_with?('_value')
|
|
124
|
-
pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == child_name.to_s[0..-7] }
|
|
125
|
-
raise NodeMutation::MethodNotSupported,
|
|
126
|
-
"#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
|
|
127
|
-
return child_node_range(pair.value, nested_child_name) if nested_child_name
|
|
128
|
-
|
|
129
|
-
return NodeMutation::Struct::Range.new(pair_node.value.loc.expression.begin_pos, pair_node.value.loc.expression.end_pos)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
112
|
raise NodeMutation::MethodNotSupported,
|
|
133
113
|
"#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
|
|
134
114
|
|
|
@@ -206,24 +186,6 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
|
|
|
206
186
|
return child_node
|
|
207
187
|
end
|
|
208
188
|
|
|
209
|
-
if node.is_a?(Parser::AST::Node) && node.type == :hash && direct_child_name.end_with?('_pair')
|
|
210
|
-
pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == direct_child_name[0..-6] }
|
|
211
|
-
raise NodeMutation::MethodNotSupported,
|
|
212
|
-
"#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
|
|
213
|
-
return child_node_by_name(pair_node, nested_child_name) if nested_child_name
|
|
214
|
-
|
|
215
|
-
return pair_node
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
if node.is_a?(Parser::AST::Node) && node.type == :hash && direct_child_name.end_with?('_value')
|
|
219
|
-
pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == direct_child_name[0..-7] }
|
|
220
|
-
raise NodeMutation::MethodNotSupported,
|
|
221
|
-
"#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
|
|
222
|
-
return child_node_by_name(pair_node.value, nested_child_name) if nested_child_name
|
|
223
|
-
|
|
224
|
-
return pair_node.value
|
|
225
|
-
end
|
|
226
|
-
|
|
227
189
|
if node.respond_to?(direct_child_name)
|
|
228
190
|
child_node = node.send(direct_child_name)
|
|
229
191
|
elsif direct_child_name.include?('(') && direct_child_name.include?(')')
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class NodeMutation::SyntaxTreeAdapter < NodeMutation::Adapter
|
|
4
|
+
def get_source(node)
|
|
5
|
+
if node.is_a?(Array)
|
|
6
|
+
return node.first.source[node.first.location.start_char...node.last.location.end_char]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
node.source[node.location.start_char...node.location.end_char]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def rewritten_source(node, code)
|
|
13
|
+
code.gsub(/{{(.+?)}}/m) do
|
|
14
|
+
old_code = Regexp.last_match(1)
|
|
15
|
+
evaluated = child_node_by_name(node, old_code)
|
|
16
|
+
case evaluated
|
|
17
|
+
when SyntaxTree::Node
|
|
18
|
+
get_source(evaluated)
|
|
19
|
+
when Array
|
|
20
|
+
if evaluated.size > 0
|
|
21
|
+
source = get_source(evaluated)
|
|
22
|
+
lines = source.split "\n"
|
|
23
|
+
lines_count = lines.length
|
|
24
|
+
if lines_count > 1 && lines_count == evaluated.size
|
|
25
|
+
new_code = []
|
|
26
|
+
lines.each_with_index { |line, index|
|
|
27
|
+
new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
|
|
28
|
+
}
|
|
29
|
+
new_code.join("\n")
|
|
30
|
+
else
|
|
31
|
+
source
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
when String, Symbol, Integer, Float
|
|
35
|
+
evaluated
|
|
36
|
+
when NilClass
|
|
37
|
+
''
|
|
38
|
+
else
|
|
39
|
+
raise "can not parse \"#{code}\""
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def child_node_range(node, child_name)
|
|
45
|
+
child_node = child_node_by_name(node, child_name)
|
|
46
|
+
return nil if child_node.nil?
|
|
47
|
+
|
|
48
|
+
if child_node.is_a?(Array)
|
|
49
|
+
return NodeMutation::Struct::Range.new(child_node.first.location.start_char, child_node.last.location.end_char)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
return NodeMutation::Struct::Range.new(child_node.location.start_char, child_node.location.end_char)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def get_start(node, child_name = nil)
|
|
56
|
+
node = child_node_by_name(node, child_name) if child_name
|
|
57
|
+
node.location.start_char
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_end(node, child_name = nil)
|
|
61
|
+
node = child_node_by_name(node, child_name) if child_name
|
|
62
|
+
node.location.end_char
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def get_start_loc(node, child_name = nil)
|
|
66
|
+
node = child_node_by_name(node, child_name) if child_name
|
|
67
|
+
NodeMutation::Struct::Location.new(node.location.start_line, node.location.start_column)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def get_end_loc(node, child_name = nil)
|
|
71
|
+
node = child_node_by_name(node, child_name) if child_name
|
|
72
|
+
NodeMutation::Struct::Location.new(node.location.end_line, node.location.end_column)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def get_indent(node)
|
|
76
|
+
node.location.start_column
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def child_node_by_name(node, child_name)
|
|
82
|
+
direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
|
|
83
|
+
|
|
84
|
+
if node.is_a?(Array)
|
|
85
|
+
if direct_child_name =~ INDEX_REGEXP
|
|
86
|
+
child_node = node[direct_child_name.to_i]
|
|
87
|
+
raise NodeMutation::MethodNotSupported,
|
|
88
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless child_node
|
|
89
|
+
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
|
90
|
+
|
|
91
|
+
return child_node
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
raise NodeMutation::MethodNotSupported,
|
|
95
|
+
"#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
|
|
96
|
+
|
|
97
|
+
child_node = node.send(direct_child_name)
|
|
98
|
+
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
|
99
|
+
|
|
100
|
+
return child_node
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
if node.respond_to?(direct_child_name)
|
|
104
|
+
child_node = node.send(direct_child_name)
|
|
105
|
+
elsif direct_child_name.include?('(') && direct_child_name.include?(')')
|
|
106
|
+
child_node = node.instance_eval(direct_child_name)
|
|
107
|
+
else
|
|
108
|
+
raise NodeMutation::MethodNotSupported, "#{direct_child_name} is not supported for #{get_source(node)}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
return child_node_by_name(child_node, nested_child_name) if nested_child_name
|
|
112
|
+
|
|
113
|
+
child_node
|
|
114
|
+
end
|
|
115
|
+
end
|
data/lib/node_mutation.rb
CHANGED
|
@@ -7,7 +7,8 @@ class NodeMutation
|
|
|
7
7
|
class ConflictActionError < StandardError; end
|
|
8
8
|
|
|
9
9
|
autoload :Adapter, "node_mutation/adapter"
|
|
10
|
-
autoload :ParserAdapter, "node_mutation/
|
|
10
|
+
autoload :ParserAdapter, "node_mutation/adapter/parser"
|
|
11
|
+
autoload :SyntaxTreeAdapter, "node_mutation/adapter/syntax_tree"
|
|
11
12
|
autoload :Action, 'node_mutation/action'
|
|
12
13
|
autoload :AppendAction, 'node_mutation/action/append_action'
|
|
13
14
|
autoload :DeleteAction, 'node_mutation/action/delete_action'
|
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.17.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-05-
|
|
11
|
+
date: 2023-05-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: ast node mutation apis
|
|
14
14
|
email:
|
|
@@ -37,7 +37,8 @@ files:
|
|
|
37
37
|
- lib/node_mutation/action/replace_action.rb
|
|
38
38
|
- lib/node_mutation/action/replace_with_action.rb
|
|
39
39
|
- lib/node_mutation/adapter.rb
|
|
40
|
-
- lib/node_mutation/
|
|
40
|
+
- lib/node_mutation/adapter/parser.rb
|
|
41
|
+
- lib/node_mutation/adapter/syntax_tree.rb
|
|
41
42
|
- lib/node_mutation/result.rb
|
|
42
43
|
- lib/node_mutation/strategy.rb
|
|
43
44
|
- lib/node_mutation/struct.rb
|