parser_node_ext 0.1.0 → 0.4.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: c0d6b0cc2e9e72c692cbc566acb7ef8cd180f428b5f473ce82457e26bdffc661
4
- data.tar.gz: 37de56dc2293bb387ca423291bf7a6fa84be97ebf21c1652aba095b76cc9817d
3
+ metadata.gz: 54f47aa3cbd58cec27d151340e935bf687be7c9cb63c523cdd8174869aebaf7e
4
+ data.tar.gz: e3e940453872b9bd0abd24a2b11b8d07c59e35613717b365b9810b0461cd1f28
5
5
  SHA512:
6
- metadata.gz: 998948687de1e0555ae1f8d2e69452c382a4320d69f5106d75ba6855a5ef0b3718bf3a28acf36a3f1a1f0e4fc86f19ed7f5d8c9e482719ddf32d26fdf3887b82
7
- data.tar.gz: f339dfc3553d68ddffa96ffd4903832346cc1d29cb679eb1ec21dbe94a64551af9535de1f0d1548b90ef8e49df017cf8efa3a2f0503268cb4a9dcbdc49ed109a
6
+ metadata.gz: 573b0ae05b18d25c04bc1efeac3f763c3872eee302d1b23fa11c054d32a1ea84afc86e7984e3ae6892f55bc39c4b0c8faadf133da1d53af6b387b8a57f55f685
7
+ data.tar.gz: b8b718a0dec190ce6b563fa9edd842d38869a58f7bc43799297e6ed88268f2fd5427315791c5b4cec62046d510056165b60683d36709d86790675eb19b14b655
data/CHANGELOG.md ADDED
@@ -0,0 +1,19 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.4.0 (2022-07-07)
4
+
5
+ * raise `MethodNotSupported` error
6
+
7
+ ## 0.3.0 (2022-07-04)
8
+
9
+ * Add `Node#to_hash`
10
+
11
+ ## 0.2.0 (2022-06-27)
12
+
13
+ * Add `Node#to_value`
14
+ * Add `Node#to_source`
15
+ * Support `xxx_value` and `xxx_source` for `hash` node
16
+
17
+ ## 0.1.0 (2022-06-26)
18
+
19
+ * Abstract from synvert-core
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parser_node_ext (0.1.0)
4
+ parser_node_ext (0.4.0)
5
5
  parser
6
6
 
7
7
  GEM
@@ -28,6 +28,7 @@ GEM
28
28
 
29
29
  PLATFORMS
30
30
  x86_64-darwin-21
31
+ x86_64-linux
31
32
 
32
33
  DEPENDENCIES
33
34
  parser_node_ext!
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ParserNodeExt
4
- VERSION = "0.1.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -5,8 +5,6 @@ require_relative "parser_node_ext/version"
5
5
  require 'parser'
6
6
 
7
7
  module ParserNodeExt
8
- class Error < StandardError; end
9
-
10
8
  class MethodNotSupported < StandardError; end
11
9
  # Your code goes here...
12
10
 
@@ -95,7 +93,7 @@ module ParserNodeExt
95
93
  index = TYPE_CHILDREN[type]&.index(method_name)
96
94
  return children[index] if index
97
95
 
98
- raise Synvert::Core::MethodNotSupported, "#{method_name} is not handled for #{debug_info}"
96
+ raise MethodNotSupported, "#{method_name} is not handled for #{debug_info}"
99
97
  end
100
98
  end
101
99
 
@@ -105,14 +103,14 @@ module ParserNodeExt
105
103
  # node # s(:or_asgn, s(:lvasgn, :a), s(:int, 1))
106
104
  # node.left_value # :a
107
105
  # @return [Parser::AST::Node] left value of node.
108
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
106
+ # @raise [MethodNotSupported] if calls on other node.
109
107
  def left_value
110
108
  return children[0].children[0] if type == :or_asgn
111
109
 
112
110
  index = TYPE_CHILDREN[type]&.index(:left_value)
113
111
  return children[index] if index
114
112
 
115
- raise Synvert::Core::MethodNotSupported, "#{left_value} is not handled for #{debug_info}"
113
+ raise MethodNotSupported, "#{left_value} is not handled for #{debug_info}"
116
114
  end
117
115
 
118
116
  # Get arguments of node.
@@ -121,7 +119,7 @@ module ParserNodeExt
121
119
  # node # s(:send, s(:const, nil, :FactoryGirl), :create, s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post"))))
122
120
  # node.arguments # [s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post")))]
123
121
  # @return [Array<Parser::AST::Node>] arguments of node.
124
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
122
+ # @raise [MethodNotSupported] if calls on other node.
125
123
  def arguments
126
124
  case type
127
125
  when :def, :block
@@ -133,7 +131,7 @@ module ParserNodeExt
133
131
  when :defined?
134
132
  children
135
133
  else
136
- raise Synvert::Core::MethodNotSupported, "arguments is not handled for #{debug_info}"
134
+ raise MethodNotSupported, "arguments is not handled for #{debug_info}"
137
135
  end
138
136
  end
139
137
 
@@ -143,7 +141,7 @@ module ParserNodeExt
143
141
  # node # s(:block, s(:send, s(:const, nil, :RSpec), :configure), s(:args, s(:arg, :config)), s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers)))
144
142
  # node.body # [s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers))]
145
143
  # @return [Array<Parser::AST::Node>] body of node.
146
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
144
+ # @raise [MethodNotSupported] if calls on other node.
147
145
  def body
148
146
  case type
149
147
  when :begin
@@ -157,7 +155,7 @@ module ParserNodeExt
157
155
 
158
156
  :begin == children[3].type ? children[3].body : children[3..-1]
159
157
  else
160
- raise Synvert::Core::MethodNotSupported, "body is not handled for #{debug_info}"
158
+ raise MethodNotSupported, "body is not handled for #{debug_info}"
161
159
  end
162
160
  end
163
161
 
@@ -167,12 +165,12 @@ module ParserNodeExt
167
165
  # node # s(:if, s(:defined?, s(:const, nil, :Bundler)), nil, nil)
168
166
  # node.condition # s(:defined?, s(:const, nil, :Bundler))
169
167
  # @return [Parser::AST::Node] condition of node.
170
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
168
+ # @raise [MethodNotSupported] if calls on other node.
171
169
  def condition
172
170
  if :if == type
173
171
  children[0]
174
172
  else
175
- raise Synvert::Core::MethodNotSupported, "condition is not handled for #{debug_info}"
173
+ raise MethodNotSupported, "condition is not handled for #{debug_info}"
176
174
  end
177
175
  end
178
176
 
@@ -181,12 +179,12 @@ module ParserNodeExt
181
179
  # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
182
180
  # node.keys # [s(:sym, :foo), s(:str, "foo")]
183
181
  # @return [Array<Parser::AST::Node>] keys of node.
184
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
182
+ # @raise [MethodNotSupported] if calls on other node.
185
183
  def keys
186
184
  if :hash == type
187
185
  children.map { |child| child.children[0] }
188
186
  else
189
- raise Synvert::Core::MethodNotSupported, "keys is not handled for #{debug_info}"
187
+ raise MethodNotSupported, "keys is not handled for #{debug_info}"
190
188
  end
191
189
  end
192
190
 
@@ -195,13 +193,155 @@ module ParserNodeExt
195
193
  # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
196
194
  # node.values # [s(:sym, :bar), s(:str, "bar")]
197
195
  # @return [Array<Parser::AST::Node>] values of node.
198
- # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
196
+ # @raise [MethodNotSupported] if calls on other node.
199
197
  def values
200
198
  if :hash == type
201
199
  children.map { |child| child.children[1] }
202
200
  else
203
- raise Synvert::Core::MethodNotSupported, "keys is not handled for #{debug_info}"
201
+ raise MethodNotSupported, "keys is not handled for #{debug_info}"
202
+ end
203
+ end
204
+
205
+ # Check if :hash node contains specified key.
206
+ # @example
207
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
208
+ # node.key?(:foo) # true
209
+ # @param [Symbol, String] key value.
210
+ # @return [Boolean] true if specified key exists.
211
+ # @raise [MethodNotSupported] if calls on other node.
212
+ def key?(key)
213
+ if :hash == type
214
+ children.any? { |pair_node| pair_node.key.to_value == key }
215
+ else
216
+ raise MethodNotSupported, "key? is not handled for #{debug_info}"
217
+ end
218
+ end
219
+
220
+ # Get :hash value node according to specified key.
221
+ # @example
222
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
223
+ # node.hash_value(:foo) # s(:sym, :bar)
224
+ # @param [Symbol, String] key value.
225
+ # @return [Parser::AST::Node] hash value of node.
226
+ # @raise [MethodNotSupported] if calls on other node.
227
+ def hash_value(key)
228
+ if :hash == type
229
+ value_node = children.find { |pair_node| pair_node.key.to_value == key }
230
+ value_node&.value
231
+ else
232
+ raise MethodNotSupported, "hash_value is not handled for #{debug_info}"
233
+ end
234
+ end
235
+
236
+ # Return the exact value of node.
237
+ # It supports :array, :begin, :erange, :false, :float, :irange, :int, :str, :sym and :true nodes.
238
+ # @example
239
+ # node # s(:array, s(:str, "str"), s(:sym, :str))
240
+ # node.to_value # ['str', :str]
241
+ # @return [Object] exact value.
242
+ # @raise [MethodNotSupported] if calls on other node.
243
+ def to_value
244
+ case type
245
+ when :int, :float, :str, :sym
246
+ children.last
247
+ when :true
248
+ true
249
+ when :false
250
+ false
251
+ when :nil
252
+ nil
253
+ when :array
254
+ children.map(&:to_value)
255
+ when :irange
256
+ (children.first.to_value..children.last.to_value)
257
+ when :erange
258
+ (children.first.to_value...children.last.to_value)
259
+ when :begin
260
+ children.first.to_value
261
+ else
262
+ self
263
+ end
264
+ end
265
+
266
+ # Get the source code of node.
267
+ #
268
+ # @return [String] source code.
269
+ def to_source
270
+ loc.expression&.source
271
+ end
272
+
273
+ # Convert node to a hash, so that it can be converted to a json.
274
+ def to_hash
275
+ result = { type: type }
276
+ if TYPE_CHILDREN[type]
277
+ TYPE_CHILDREN[type].each do |key|
278
+ value = send(key)
279
+ result[key] =
280
+ case value
281
+ when Array
282
+ value.map { |v| v.respond_to?(:to_hash) ? v.to_hash : v }
283
+ when Parser::AST::Node
284
+ value.to_hash
285
+ else
286
+ value
287
+ end
288
+ end
289
+ else
290
+ result[:children] = children.map { |c| c.respond_to?(:to_hash) ? c.to_hash : c }
291
+ end
292
+ result
293
+ end
294
+
295
+ # Respond key value and source for hash node, e.g.
296
+ # @example
297
+ # node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
298
+ # node.foo_value # :bar
299
+ # node.foo_source # ":bar"
300
+ def method_missing(method_name, *args, &block)
301
+ if :args == type && children.respond_to?(method_name)
302
+ return children.send(method_name, *args, &block)
303
+ elsif :hash == type && method_name.to_s.include?('_value')
304
+ key = method_name.to_s.sub('_value', '')
305
+ return hash_value(key.to_sym)&.to_value if key?(key.to_sym)
306
+ return hash_value(key.to_s)&.to_value if key?(key.to_s)
307
+
308
+ return nil
309
+ elsif :hash == type && method_name.to_s.include?('_source')
310
+ key = method_name.to_s.sub('_source', '')
311
+ return hash_value(key.to_sym)&.to_source if key?(key.to_sym)
312
+ return hash_value(key.to_s)&.to_source if key?(key.to_s)
313
+
314
+ return nil
315
+ end
316
+
317
+ super
318
+ end
319
+
320
+ def respond_to_missing?(method_name, *args)
321
+ if :args == type && children.respond_to?(method_name)
322
+ return true
323
+ elsif :hash == type && method_name.to_s.include?('_value')
324
+ key = method_name.to_s.sub('_value', '')
325
+ return true if key?(key.to_sym) || key?(key.to_s)
326
+ elsif :hash == type && method_name.to_s.include?('_source')
327
+ key = method_name.to_s.sub('_source', '')
328
+ return true if key?(key.to_sym) || key?(key.to_s)
204
329
  end
330
+
331
+ super
332
+ end
333
+
334
+ # Return the debug info.
335
+ #
336
+ # @return [String] file, line, source and node.
337
+ def debug_info
338
+ "\n" +
339
+ [
340
+ "file: #{loc.expression.source_buffer.name}",
341
+ "line: #{loc.expression.line}",
342
+ "source: #{to_source}",
343
+ "node: #{inspect}"
344
+ ].join("\n")
205
345
  end
206
346
  end
207
347
  end
@@ -2,17 +2,19 @@ module ParserNodeExt
2
2
  VERSION: String
3
3
  # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
4
 
5
- def arguments: Array[Parser::AST::Node]
6
- def body: Array[Parser::AST::Node]
7
- def caller: Parser::AST::Node
8
- def key: Parser::AST::Node
9
- def left_value: Parser::AST::Node | Symbol
10
- def message: Symbol
11
- def name: Parser::AST::Node | Symbol
12
- def pairs: Array[Parser::AST::Node]
13
- def parent_class: Parser::AST::Node
14
- def receiver: Parser::AST::Node
15
- def right_value: Parser::AST::Node
16
- def self: Parser::AST::Node
17
- def value: Parser::AST::Node
5
+ def arguments: () -> Array[Parser::AST::Node]
6
+ def body: () -> Array[Parser::AST::Node]
7
+ def caller: () -> Parser::AST::Node
8
+ def key: () -> Parser::AST::Node
9
+ def left_value: () -> Parser::AST::Node | Symbol
10
+ def message: () -> Symbol
11
+ def name: () -> Parser::AST::Node | Symbol
12
+ def pairs: () -> Array[Parser::AST::Node]
13
+ def parent_class: () -> Parser::AST::Node
14
+ def receiver: () -> Parser::AST::Node
15
+ def right_value: () -> Parser::AST::Node
16
+ def self: () -> Parser::AST::Node
17
+ def value: () -> Parser::AST::Node
18
+
19
+ def to_hash: () -> Hash
18
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parser_node_ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.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: 2022-06-26 00:00:00.000000000 Z
11
+ date: 2022-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -33,6 +33,7 @@ extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
35
  - ".rspec"
36
+ - CHANGELOG.md
36
37
  - Gemfile
37
38
  - Gemfile.lock
38
39
  - README.md