node_mutation 1.15.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e184fa98da9cbfac3645ec4e89ac2201cdbbfd958c511a03050443a66c79b322
4
- data.tar.gz: 7c7693df11e9cd74df33d5ef6949bc800ab3a6c4367836c799b76073800586d5
3
+ metadata.gz: 7df63f45429db131b4023d42d1fcab4fdac401358376f0d2ed16722627484bf0
4
+ data.tar.gz: a9fdadb2c0dd0d82cd709040b2c154b4e2bd75b95ca71082e00e5768e15f476a
5
5
  SHA512:
6
- metadata.gz: 17c9a5065bb703331ccf1996bb3895ff833336b768aca74751c52b885c0651c9c4bb19b989d026aa39b10cdf03b61ab43ddf3e5e1fe742aa837527b8e680279e
7
- data.tar.gz: ba34afa52b6dacf07f5a9b736a31e2b1ad0c37e3a0717690d302f1a1e91ab366705d7ac840a903ada796d182731731823a7cf438e3d1de6c07ee1fcdb2ae5861
6
+ metadata.gz: 7e6194b0d8d80e3b8e553e06c287663a4595bd259f91dbdc9c469c83f4fbabe0781b1ef959fb57341e4d5499993444f21c7fd09283b22f67908495c770446bb2
7
+ data.tar.gz: 5b99e2f025960eb624f9b82a40a37a1befc63e4787a8cc3a3cd2067e378e9d4b9dfe5f71f7cee2ec922a7171658704a29e0ff799a16389c62b5f27307e818327
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # NodeMutation
2
2
 
3
+ ## 1.17.0 (2023-05-15)
4
+
5
+ * Add `SyntaxTreeAdapter`
6
+
7
+ ## 1.16.0 (2023-05-10)
8
+
9
+ * Support {key}_value for a hash node
10
+
3
11
  ## 1.15.3 (2023-04-18)
4
12
 
5
13
  * Add `type` to `Action`
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.15.3)
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,15 +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
112
  raise NodeMutation::MethodNotSupported,
124
113
  "#{direct_child_name} is not supported for #{get_source(node)}" unless node.respond_to?(direct_child_name)
125
114
 
@@ -197,15 +186,6 @@ class NodeMutation::ParserAdapter < NodeMutation::Adapter
197
186
  return child_node
198
187
  end
199
188
 
200
- if node.is_a?(Parser::AST::Node) && node.type == :hash && direct_child_name.end_with?('_pair')
201
- pair_node = node.pairs.find { |pair| pair.key.to_value.to_s == direct_child_name[0..-6] }
202
- raise NodeMutation::MethodNotSupported,
203
- "#{direct_child_name} is not supported for #{get_source(node)}" unless pair_node
204
- return child_node_by_name(pair_node, nested_child_name) if nested_child_name
205
-
206
- return pair_node
207
- end
208
-
209
189
  if node.respond_to?(direct_child_name)
210
190
  child_node = node.send(direct_child_name)
211
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.15.3"
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.15.3
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-04-18 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