node_query 1.4.0 → 1.6.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: 95dcf07d501c704e59bb792454be0bae1ddfafb915c77b6a062c6331d654564b
4
- data.tar.gz: 7b835b8479ff5239ea77dcb5ed09f4868b1a09cbdf5edc2f4ab9413d352030be
3
+ metadata.gz: 86cae1819b055b5c50aa47879d3da1902805a24fa484f9697270e1591f4af73f
4
+ data.tar.gz: 59c4f42f81cd67758c0e3e6d237c3e23e3f35aec2175ae9d4798d93b3b4d11c6
5
5
  SHA512:
6
- metadata.gz: e2dbea64418363ad059ea2b6e9d93b3c2d010bdba59317327904b6a48411517a511ab6737fe40bdf4847b2833ec4d81eb5d474be7db7d831a6119c89fe904fea
7
- data.tar.gz: c2cf0bfec6edfa28b644a38957dce1276cc287507c3c3034a39e0ce018f25e420faded6ad0c7c3c3838757df5107082c30d05fcf9f4323c5d5d3f32bc68337f1
6
+ metadata.gz: 1b10e103621f14acc695c6b27c26d15a4751c804a907273b95056516697934d381aefdb8396aa90056385b90a741052bc9d5dc8a2a2c2afe05e69101d06af958
7
+ data.tar.gz: 36063af159d24d01bdf7e447aab58fc0800a95d3c764915635a31f2f26ae7ff401a8243287c3d1b01ca5cae1ddc6753ad952dee7c7f3ffa62c66834114bc572d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.6.0 (2022-09-16)
4
+
5
+ * Rename `nodeType` to `node_type`
6
+
7
+ ## 1.5.0 (2022-09-15)
8
+
9
+ * Add `Helper.to_string`
10
+ * Only check the current node if `including_self` is true and `recursive` is false
11
+ * Fix `Regexp#match?` and `String#match?`
12
+ * Rename `stop_on_match` to `stop_at_first_match`
13
+
3
14
  ## 1.4.0 (2022-09-14)
4
15
 
5
16
  * Add options `including_self`, `stop_on_match` and `recursive`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_query (1.4.0)
4
+ node_query (1.6.0)
5
5
  activesupport (< 7.0.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -62,7 +62,7 @@ It provides two apis: `query_nodes` and `match_node?`
62
62
 
63
63
  ```ruby
64
64
  node_query = NodeQuery.new(nqlOrRules: String | Hash) # Initialize NodeQuery
65
- node_query.query_nodes(node: Node, options = { including_self: true, stop_on_match: false, recursive: true }): Node[] # Get the matching nodes.
65
+ node_query.query_nodes(node: Node, options = { including_self: true, stop_at_first_match: false, recursive: true }): Node[] # Get the matching nodes.
66
66
  node_query.match_node?(node: Node): boolean # Check if the node matches nql or rules.
67
67
  ```
68
68
 
@@ -83,7 +83,7 @@ node = Parser::CurrentRuby.parse(source)
83
83
 
84
84
  # It will get the node of initialize.
85
85
  NodeQuery.new('.def[name=initialize]').query_nodes(node)
86
- NodeQuery.new({ nodeType: 'def', name: 'initialize' }).query_nodes(node)
86
+ NodeQuery.new({ node_type: 'def', name: 'initialize' }).query_nodes(node)
87
87
  ```
88
88
 
89
89
  ## Node Query Language
@@ -313,7 +313,7 @@ It matches ivasgn node whose left value is either @id or @name.
313
313
  ### rules matches node type
314
314
 
315
315
  ```
316
- { nodeType: 'class' }
316
+ { node_type: 'class' }
317
317
  ```
318
318
 
319
319
  It matches class node
@@ -321,13 +321,13 @@ It matches class node
321
321
  ### rules matches attribute
322
322
 
323
323
  ```
324
- { nodeType: 'def', name: 'initialize' }
324
+ { node_type: 'def', name: 'initialize' }
325
325
  ```
326
326
 
327
327
  It matches def node whose name is initialize
328
328
 
329
329
  ```
330
- { nodeType: 'def', arguments: { "0": 1, "1": "Murphy" } }
330
+ { node_type: 'def', arguments: { "0": 1, "1": "Murphy" } }
331
331
  ```
332
332
 
333
333
  It matches def node whose arguments are 1 and Murphy.
@@ -335,7 +335,7 @@ It matches def node whose arguments are 1 and Murphy.
335
335
  ### rules matches nested attribute
336
336
 
337
337
  ```
338
- { nodeType: 'class', parent_class: { name: 'Base' } }
338
+ { node_type: 'class', parent_class: { name: 'Base' } }
339
339
  ```
340
340
 
341
341
  It matches class node whose parent class name is Base
@@ -343,7 +343,7 @@ It matches class node whose parent class name is Base
343
343
  ### rules matches evaluated value
344
344
 
345
345
  ```
346
- { nodeType: 'ivasgn', left_value: '@{{right_value}}' }
346
+ { node_type: 'ivasgn', left_value: '@{{right_value}}' }
347
347
  ```
348
348
 
349
349
  It matches ivasgn node whose left value equals '@' plus the evaluated value of right value.
@@ -351,7 +351,7 @@ It matches ivasgn node whose left value equals '@' plus the evaluated value of r
351
351
  ### rules matches nested selector
352
352
 
353
353
  ```
354
- { nodeType: 'def', body: { "0": { nodeType: 'ivasgn' } } }
354
+ { node_type: 'def', body: { "0": { node_type: 'ivasgn' } } }
355
355
  ```
356
356
 
357
357
  It matches def node whose first child node is an ivasgn node.
@@ -359,7 +359,7 @@ It matches def node whose first child node is an ivasgn node.
359
359
  ### rules matches method result
360
360
 
361
361
  ```
362
- { nodeType: 'def', arguments: { size: 2 } }
362
+ { node_type: 'def', arguments: { size: 2 } }
363
363
  ```
364
364
 
365
365
  It matches def node whose arguments size is 2.
@@ -367,73 +367,73 @@ It matches def node whose arguments size is 2.
367
367
  ### rules matches operators
368
368
 
369
369
  ```
370
- { nodeType: 'class', name: 'User' }
370
+ { node_type: 'class', name: 'User' }
371
371
  ```
372
372
 
373
373
  Value of name is equal to User
374
374
 
375
375
  ```
376
- { nodeType: 'def', arguments: { size { not: 2 } }
376
+ { node_type: 'def', arguments: { size { not: 2 } }
377
377
  ```
378
378
 
379
379
  Size of arguments is not equal to 2
380
380
 
381
381
  ```
382
- { nodeType: 'def', arguments: { size { gte: 2 } }
382
+ { node_type: 'def', arguments: { size { gte: 2 } }
383
383
  ```
384
384
 
385
385
  Size of arguments is greater than or equal to 2
386
386
 
387
387
  ```
388
- { nodeType: 'def', arguments: { size { gt: 2 } }
388
+ { node_type: 'def', arguments: { size { gt: 2 } }
389
389
  ```
390
390
 
391
391
  Size of arguments is greater than 2
392
392
 
393
393
  ```
394
- { nodeType: 'def', arguments: { size { lte: 2 } }
394
+ { node_type: 'def', arguments: { size { lte: 2 } }
395
395
  ```
396
396
 
397
397
  Size of arguments is less than or equal to 2
398
398
 
399
399
  ```
400
- { nodeType: 'def', arguments: { size { lt: 2 } }
400
+ { node_type: 'def', arguments: { size { lt: 2 } }
401
401
  ```
402
402
 
403
403
  Size of arguments is less than 2
404
404
 
405
405
  ```
406
- { nodeType: 'class', name: { in: ['User', 'Account'] } }
406
+ { node_type: 'class', name: { in: ['User', 'Account'] } }
407
407
  ```
408
408
 
409
409
  Value of name is either User or Account
410
410
 
411
411
  ```
412
- { nodeType: 'class', name: { not_in: ['User', 'Account'] } }
412
+ { node_type: 'class', name: { not_in: ['User', 'Account'] } }
413
413
  ```
414
414
 
415
415
  Value of name is neither User nor Account
416
416
 
417
417
  ```
418
- { nodeType: 'def', arguments: { includes: 'id' } }
418
+ { node_type: 'def', arguments: { includes: 'id' } }
419
419
  ```
420
420
 
421
421
  Value of arguments includes id
422
422
 
423
423
  ```
424
- { nodeType: 'class', name: /User/ }
424
+ { node_type: 'class', name: /User/ }
425
425
  ```
426
426
 
427
427
  Value of name matches User
428
428
 
429
429
  ```
430
- { nodeType: 'class', name: { not: /User/ } }
430
+ { node_type: 'class', name: { not: /User/ } }
431
431
  ```
432
432
 
433
433
  Value of name does not match User
434
434
 
435
435
  ```
436
- { nodeType: 'class', name: { in: [/User/, /Account/] } }
436
+ { node_type: 'class', name: { in: [/User/, /Account/] } }
437
437
  ```
438
438
 
439
439
  Value of name matches either /User/ or /Account/
@@ -441,7 +441,7 @@ Value of name matches either /User/ or /Account/
441
441
  ### rules matches array nodes attribute
442
442
 
443
443
  ```
444
- { nodeType: 'def', arguments: ['id', 'name'] }
444
+ { node_type: 'def', arguments: ['id', 'name'] }
445
445
  ```
446
446
 
447
447
  It matches def node whose arguments are id and name.
@@ -15,8 +15,8 @@ module NodeQuery::Compiler
15
15
  # @param node [Node] node to match
16
16
  # @param options [Hash] if query the current node
17
17
  # @option options [boolean] :including_self if query the current node, default is ture
18
- # @option options [boolean] :stop_on_match if stop on first match, default is false
19
- # @option options [boolean] :recursive if stop on first match, default is true
18
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
19
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
20
20
  # @return [Array<Node>] matching nodes.
21
21
  def query_nodes(node, options = {})
22
22
  matching_nodes = @selector.query_nodes(node, options)
@@ -15,8 +15,8 @@ module NodeQuery::Compiler
15
15
  # @param node [Node] node to match
16
16
  # @param options [Hash] if query the current node
17
17
  # @option options [boolean] :including_self if query the current node, default is ture
18
- # @option options [boolean] :stop_on_match if stop on first match, default is false
19
- # @option options [boolean] :recursive if stop on first match, default is true
18
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
19
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
20
20
  # @return [Array<Node>] matching nodes.
21
21
  def query_nodes(node, options = {})
22
22
  matching_nodes = @expression.query_nodes(node, options)
@@ -13,13 +13,16 @@ module NodeQuery::Compiler
13
13
 
14
14
  # Check if the regexp value matches the node value.
15
15
  # @param node [Node] the node
16
- # @return [Boolean] true if the regexp value matches the node value.
17
- def is_equal?(node)
18
- if NodeQuery.adapter.is_node?(node)
19
- @value.match(NodeQuery.adapter.get_source(node))
20
- else
21
- @value.match(node.to_s)
22
- end
16
+ # @param operator [String] the operator
17
+ # @return [Boolean] true if the regexp value matches the node value, otherwise, false.
18
+ def match?(node, operator = '=~')
19
+ match =
20
+ if NodeQuery.adapter.is_node?(node)
21
+ @value.match(NodeQuery.adapter.get_source(node))
22
+ else
23
+ @value.match(node.to_s)
24
+ end
25
+ operator == '=~' ? match : !match
23
26
  end
24
27
 
25
28
  # Get valid operators.
@@ -35,11 +35,11 @@ module NodeQuery::Compiler
35
35
  # @param node [Node] node to match
36
36
  # @param options [Hash] if query the current node
37
37
  # @option options [boolean] :including_self if query the current node, default is ture
38
- # @option options [boolean] :stop_on_match if stop on first match, default is false
39
- # @option options [boolean] :recursive if stop on first match, default is true
38
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
39
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
40
40
  # @return [Array<Node>] matching nodes.
41
41
  def query_nodes(node, options = {})
42
- options = { including_self: true, stop_on_match: false, recursive: true }.merge(options)
42
+ options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
43
43
  return find_nodes_by_relationship(node) if @relationship
44
44
 
45
45
  if node.is_a?(::Array)
@@ -48,24 +48,28 @@ module NodeQuery::Compiler
48
48
 
49
49
  return find_nodes_by_goto_scope(node) if @goto_scope
50
50
 
51
+ if options[:including_self] && !options[:recursive]
52
+ return match?(node) ? [node] : []
53
+ end
54
+
51
55
  nodes = []
52
56
  if options[:including_self] && match?(node)
53
57
  nodes << node
54
- return matching_nodes if options[:stop_on_match]
58
+ return nodes if options[:stop_at_first_match]
55
59
  end
56
60
  if @basic_selector
57
61
  if options[:recursive]
58
62
  NodeQuery::Helper.handle_recursive_child(node) do |child_node|
59
63
  if match?(child_node)
60
64
  nodes << child_node
61
- break if options[:stop_on_match]
65
+ break if options[:stop_at_first_match]
62
66
  end
63
67
  end
64
68
  else
65
69
  NodeQuery.adapter.get_children(node).each do |child_node|
66
70
  if match?(child_node)
67
71
  nodes << child_node
68
- break if options[:stop_on_match]
72
+ break if options[:stop_at_first_match]
69
73
  end
70
74
  end
71
75
  end
@@ -27,7 +27,7 @@ module NodeQuery::Compiler
27
27
  # @param node [Node] the node
28
28
  # @return [Boolean] true if the actual value equals the node value.
29
29
  def is_equal?(node)
30
- actual_value(node).to_s == expected_value
30
+ NodeQuery::Helper.to_string(actual_value(node)) == expected_value
31
31
  end
32
32
 
33
33
  # Get valid operators.
@@ -18,7 +18,7 @@ class NodeQuery::Helper
18
18
  child_node = node[first_key.to_i]
19
19
  elsif node.respond_to?(first_key)
20
20
  child_node = node.send(first_key)
21
- elsif first_key == "nodeType"
21
+ elsif first_key == "node_type"
22
22
  child_node = NodeQuery.adapter.get_node_type(node)
23
23
  end
24
24
 
@@ -50,9 +50,17 @@ class NodeQuery::Helper
50
50
  def evaluate_node_value(node, str)
51
51
  str.scan(/{{(.*?)}}/).each do |match_data|
52
52
  target_node = NodeQuery::Helper.get_target_node(node, match_data.first)
53
- str = str.sub("{{#{match_data.first}}}", NodeQuery.adapter.get_source(target_node))
53
+ str = str.sub("{{#{match_data.first}}}", to_string(target_node))
54
54
  end
55
55
  str
56
56
  end
57
+
58
+ def to_string(node)
59
+ if NodeQuery.adapter.is_node?(node)
60
+ return NodeQuery.adapter.get_source(node)
61
+ end
62
+
63
+ node.to_s
64
+ end
57
65
  end
58
66
  end
@@ -13,28 +13,32 @@ class NodeQuery::NodeRules
13
13
  # @param node [Node] node to query
14
14
  # @param options [Hash] if query the current node
15
15
  # @option options [boolean] :including_self if query the current node, default is ture
16
- # @option options [boolean] :stop_on_match if stop on first match, default is false
17
- # @option options [boolean] :recursive if stop on first match, default is true
16
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
17
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
18
18
  # @return [Array<Node>] matching nodes.
19
19
  def query_nodes(node, options = {})
20
- options = { including_self: true, stop_on_match: false, recursive: true }.merge(options)
20
+ options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
21
+ if options[:including_self] && !options[:recursive]
22
+ return match_node?(node) ? [node] : []
23
+ end
24
+
21
25
  matching_nodes = []
22
26
  if options[:including_self] && match_node?(node)
23
27
  matching_nodes.push(node)
24
- return matching_nodes if options[:stop_on_match]
28
+ return matching_nodes if options[:stop_at_first_match]
25
29
  end
26
30
  if options[:recursive]
27
31
  NodeQuery::Helper.handle_recursive_child(node) do |child_node|
28
32
  if match_node?(child_node)
29
33
  matching_nodes.push(child_node)
30
- break if options[:stop_on_match]
34
+ break if options[:stop_at_first_match]
31
35
  end
32
36
  end
33
37
  else
34
38
  NodeQuery.adapter.get_children(node).each do |child_node|
35
39
  if match_node?(child_node)
36
40
  matching_nodes.push(child_node)
37
- break if options[:stop_on_match]
41
+ break if options[:stop_at_first_match]
38
42
  end
39
43
  end
40
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeQuery
4
- VERSION = "1.4.0"
4
+ VERSION = "1.6.0"
5
5
  end
data/lib/node_query.rb CHANGED
@@ -40,8 +40,8 @@ class NodeQuery
40
40
  # @param node [Node] ast node
41
41
  # @param options [Hash] if query the current node
42
42
  # @option options [boolean] :including_self if query the current node, default is ture
43
- # @option options [boolean] :stop_on_match if stop on first match, default is false
44
- # @option options [boolean] :recursive if stop on first match, default is true
43
+ # @option options [boolean] :stop_at_first_match if stop at first match, default is false
44
+ # @option options [boolean] :recursive if recursively query child nodes, default is true
45
45
  # @return [Array<Node>] matching child nodes
46
46
  def query_nodes(node, options = {})
47
47
  if @expression
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: node_query
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.6.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-09-14 00:00:00.000000000 Z
11
+ date: 2022-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport