node_mutation 1.16.0 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14e76d23c3a0be62554de359db928e7f0e70fe75b6c13ecb0655add5af735333
4
- data.tar.gz: 1777be0d1e8c4044fa175dcc8f9f9e3431283fdf039392cba9f8fe4fd656c676
3
+ metadata.gz: 7df63f45429db131b4023d42d1fcab4fdac401358376f0d2ed16722627484bf0
4
+ data.tar.gz: a9fdadb2c0dd0d82cd709040b2c154b4e2bd75b95ca71082e00e5768e15f476a
5
5
  SHA512:
6
- metadata.gz: ef64c7156966a2d80c4bf823e0c3330d8934cf52306a9f179bac7105b52c82e78bb9b0d958510165a541fd1fe550b3eec7c7e78eaf3aa7f3207a5b0df1f9e4e3
7
- data.tar.gz: 969399df03dc8e3f5c15e55f37a3664bf0945a41e5ff244542319b8a2c20d6afff54dc3aee72b6b4e6c90c6ce84428b6008d14d3dc81e343c68296e78b387218
6
+ metadata.gz: 7e6194b0d8d80e3b8e553e06c287663a4595bd259f91dbdc9c469c83f4fbabe0781b1ef959fb57341e4d5499993444f21c7fd09283b22f67908495c770446bb2
7
+ data.tar.gz: 5b99e2f025960eb624f9b82a40a37a1befc63e4787a8cc3a3cd2067e378e9d4b9dfe5f71f7cee2ec922a7171658704a29e0ff799a16389c62b5f27307e818327
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # NodeMutation
2
2
 
3
+ ## 1.17.0 (2023-05-15)
4
+
5
+ * Add `SyntaxTreeAdapter`
6
+
3
7
  ## 1.16.0 (2023-05-10)
4
8
 
5
9
  * Support {key}_value for a hash node
data/Gemfile CHANGED
@@ -11,5 +11,6 @@ gem "rspec", "~> 3.0"
11
11
 
12
12
  gem "parser"
13
13
  gem "parser_node_ext"
14
+ gem "syntax_tree_ext"
14
15
  gem "guard"
15
16
  gem "guard-rspec"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_mutation (1.16.0)
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.0)
37
+ parser (3.2.2.1)
38
38
  ast (~> 2.4.1)
39
- parser_node_ext (1.0.0)
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: ParserAdapter.new) // default is ParserAdapter
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
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeMutation::Adapter
4
+ INDEX_REGEXP = /\A-?\d+\z/
5
+
4
6
  # Get source code of the ast node
5
7
  # @param node [Node] ast node
6
8
  # @return [String] source code
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeMutation
4
- VERSION = "1.16.0"
4
+ VERSION = "1.17.0"
5
5
  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/parser_adapter"
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.16.0
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-10 00:00:00.000000000 Z
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/parser_adapter.rb
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