node_query 1.8.1 → 1.10.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: 3dec6cb33f976a8d4eab33d781441941dad502fe794ced0b22ee37e2ef15afd0
4
- data.tar.gz: 50b703ba607c8efe543fa4a019d84959416795d6fe199b7320eb6f2c0fe454dd
3
+ metadata.gz: cc14f10f4a27631913cd6d9b3b66b100864778756bc317b1529abe45999255b4
4
+ data.tar.gz: 2e04f47d2bbc0eade7ea2a047fe27174ec0e343d875203a0d3cd39fcaea50120
5
5
  SHA512:
6
- metadata.gz: 9b7232c12af438ecbc69dfd24ee62c6f3c60be26760047afa95154d862da50a098c9079f4c744d15f31ab34e319a2bc8a874fb4d4fb396143f2a6e5e802f7d2f
7
- data.tar.gz: 60afc766f3d6e4b3cf44efc3e7bf6fac3b7256b8ce47831311ac3fef6a23768bb40ec5d0c5ae6bdf6193dbba6bf40f6349aa71f9d7726a1c9ecf1841ed565fe3
6
+ metadata.gz: 4b434f39629e544435594f4d299b845841b4610bed644954b0e835a7eed7d1b178d510d2ba5be8bfea0d3365d15f46d73a64ea8e9310037f4a851fa9989d05f3
7
+ data.tar.gz: bee545aae91e3769cb616e156f4cf6a69f628f5cc3a9e25432ea7eb9224a8ea49f1f76518b09601ce692b52790e5f0fd5da518d55650a243c0478d9056ac9a53
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.10.0 (2022-10-26)
4
+
5
+ * Add `NodeQuery::MethodNotSupported` error
6
+ * Add `NodeQuery::AnyValue` to match any value in node rules
7
+
8
+ ## 1.9.0 (2022-10-23)
9
+
10
+ * Support `NOT INCLUDES` operator
11
+ * `includes` / `not_includes` a selector
12
+
3
13
  ## 1.8.1 (2022-10-15)
4
14
 
5
15
  * Fix `filter_by_position` with empty nodes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- node_query (1.8.1)
4
+ node_query (1.10.0)
5
5
  activesupport (< 7.0.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -210,6 +210,12 @@ Value of name is neither User nor Account
210
210
 
211
211
  Value of arguments includes id
212
212
 
213
+ ```
214
+ .def[arguments NOT INCLUDES id]
215
+ ```
216
+
217
+ Value of arguments not includes id
218
+
213
219
  ```
214
220
  .class[name=~/User/]
215
221
  ```
@@ -434,6 +440,12 @@ Value of name is neither User nor Account
434
440
 
435
441
  Value of arguments includes id
436
442
 
443
+ ```
444
+ { node_type: 'def', arguments: { not_includes: 'id' } }
445
+ ```
446
+
447
+ Value of arguments not includes id
448
+
437
449
  ```
438
450
  { node_type: 'class', name: /User/ }
439
451
  ```
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A new type to match any value.
4
+ class NodeQuery::AnyValue
5
+ end
@@ -31,6 +31,8 @@ module NodeQuery::Compiler
31
31
  "#{@key} not in (#{@value})"
32
32
  when 'includes'
33
33
  "#{@key} includes #{@value}"
34
+ when 'not_includes'
35
+ "#{@key} not includes #{@value}"
34
36
  else
35
37
  "#{@key}=#{@value}"
36
38
  end
@@ -3,9 +3,9 @@
3
3
  module NodeQuery::Compiler
4
4
  # Compare acutal value with expected value.
5
5
  module Comparable
6
- SIMPLE_VALID_OPERATORS = ['==', '!=', 'includes']
7
- STRING_VALID_OPERATORS = ['==', '!=', '^=', '$=', '*=', 'includes']
8
- NUMBER_VALID_OPERATORS = ['==', '!=', '>', '>=', '<', '<=', 'includes']
6
+ SIMPLE_VALID_OPERATORS = ['==', '!=', 'includes', 'not_includes']
7
+ STRING_VALID_OPERATORS = ['==', '!=', '^=', '$=', '*=', 'includes', 'not_includes']
8
+ NUMBER_VALID_OPERATORS = ['==', '!=', '>', '>=', '<', '<=', 'includes', 'not_includes']
9
9
  ARRAY_VALID_OPERATORS = ['==', '!=', 'in', 'not_in']
10
10
  REGEXP_VALID_OPERATORS = ['=~', '!~']
11
11
 
@@ -60,7 +60,9 @@ module NodeQuery::Compiler
60
60
  expected.all? { |expected_child| expected_child.match?(node, base_node, '!=') }
61
61
  end
62
62
  when 'includes'
63
- actual.any? { |actual_child| actual_child == expected }
63
+ actual.any? { |actual_child| expected.match?(actual_child) }
64
+ when 'not_includes'
65
+ actual.none? { |actual_child| expected.match?(actual_child) }
64
66
  else
65
67
  if expected.is_a?(::Array)
66
68
  actual.is_a?(::Array) && actual.size == expected.size &&
@@ -25,8 +25,18 @@ module NodeQuery::Compiler
25
25
  # Check if node matches the selector.
26
26
  # @param node [Parser::AST::Node] the node
27
27
  # @param base_node [Parser::AST::Node] the base node for evaluated node
28
- def match?(node, base_node)
29
- NodeQuery.adapter.is_node?(node) && (!@basic_selector || @basic_selector.match?(node, base_node)) && match_pseudo_class?(node)
28
+ def match?(node, base_node, operator = "==")
29
+ if node.is_a?(::Array)
30
+ case operator
31
+ when "not_includes"
32
+ return node.none? { |child_node| match?(child_node, base_node) }
33
+ when "includes"
34
+ return node.any? { |child_node| match?(child_node, base_node) }
35
+ else
36
+ return false
37
+ end
38
+ end
39
+ NodeQuery.adapter.is_node?(node) && (!@basic_selector || (operator == "!=" ? !@basic_selector.match?(node, base_node) : @basic_selector.match?(node, base_node))) && match_pseudo_class?(node)
30
40
  end
31
41
 
32
42
  # Query nodes by the selector.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeQuery::NodeRules
4
- KEYWORDS = %i[any includes not in not_in gt gte lt lte]
4
+ KEYWORDS = %i[not_includes includes not in not_in gt gte lt lte]
5
5
 
6
6
  # Initialize a NodeRules.
7
7
  # @param rules [Hash] the nod rules
@@ -57,8 +57,10 @@ class NodeQuery::NodeRules
57
57
  expected = expected_value(@rules, multi_keys)
58
58
  expected = NodeQuery::Helper.evaluate_node_value(node, expected) if expected.is_a?(String)
59
59
  case last_key
60
- when :any, :includes
60
+ when :includes
61
61
  actual.any? { |actual_value| match_value?(actual_value, expected) }
62
+ when :not_includes
63
+ actual.all? { |actual_value| !match_value?(actual_value, expected) }
62
64
  when :not
63
65
  !match_value?(actual, expected)
64
66
  when :in
@@ -86,7 +88,7 @@ class NodeQuery::NodeRules
86
88
  # @param actual [Object] actual value.
87
89
  # @param expected [Object] expected value.
88
90
  # @return [Boolean]
89
- # @raise [Synvert::Core::MethodNotSupported] if expected class is not supported.
91
+ # @raise [NodeQuery::MethodNotSupported] if expected class is not supported.
90
92
  def match_value?(actual, expected)
91
93
  return true if actual == expected
92
94
 
@@ -134,10 +136,10 @@ class NodeQuery::NodeRules
134
136
  :false == actual.type
135
137
  when Parser::AST::Node
136
138
  actual == expected
137
- when Synvert::Core::Rewriter::AnyValue
139
+ when NodeQuery::AnyValue
138
140
  !actual.nil?
139
141
  else
140
- raise Synvert::Core::MethodNotSupported, "#{expected.class} is not handled for match_value?"
142
+ raise NodeQuery::MethodNotSupported, "#{expected} is not supported"
141
143
  end
142
144
  end
143
145
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class NodeQuery
4
- VERSION = "1.8.1"
4
+ VERSION = "1.10.0"
5
5
  end
data/lib/node_query.rb CHANGED
@@ -7,11 +7,14 @@ require_relative "./node_query_lexer.rex"
7
7
  require_relative "./node_query_parser.racc"
8
8
 
9
9
  class NodeQuery
10
+ class MethodNotSupported < StandardError; end
11
+
10
12
  autoload :Adapter, "node_query/adapter"
11
13
  autoload :ParserAdapter, "node_query/parser_adapter"
12
14
  autoload :Compiler, "node_query/compiler"
13
15
  autoload :Helper, "node_query/helper"
14
16
  autoload :NodeRules, "node_query/node_rules"
17
+ autoload :AnyValue, 'node_query/any_value'
15
18
 
16
19
  # Configure NodeQuery
17
20
  # @param [Hash] options options to configure
@@ -50,6 +50,7 @@ rules
50
50
  :KEY />/ { @state = :VALUE; [:tOPERATOR, '>'] }
51
51
  :KEY /</ { @state = :VALUE; [:tOPERATOR, '<'] }
52
52
  :KEY /=/ { @state = :VALUE; [:tOPERATOR, '=='] }
53
+ :KEY /not includes/i { @state = :VALUE; [:tOPERATOR, 'not_includes'] }
53
54
  :KEY /includes/i { @state = :VALUE; [:tOPERATOR, 'includes'] }
54
55
  :KEY /not in/i { @state = :VALUE; [:tOPERATOR, 'not_in'] }
55
56
  :KEY /in/i { @state = :VALUE; [:tOPERATOR, 'in'] }
@@ -179,6 +179,8 @@ class NodeQueryLexer
179
179
  action { @state = :VALUE; [:tOPERATOR, '<'] }
180
180
  when ss.skip(/=/) then
181
181
  action { @state = :VALUE; [:tOPERATOR, '=='] }
182
+ when ss.skip(/not includes/i) then
183
+ action { @state = :VALUE; [:tOPERATOR, 'not_includes'] }
182
184
  when ss.skip(/includes/i) then
183
185
  action { @state = :VALUE; [:tOPERATOR, 'includes'] }
184
186
  when ss.skip(/not in/i) then
@@ -22,31 +22,31 @@ class NodeQueryParser < Racc::Parser
22
22
  ##### State transition tables begin ###
23
23
 
24
24
  racc_action_table = [
25
- 8, 8, 7, 9, 10, 37, 12, 5, 6, 13,
26
- 28, 17, 18, 22, 23, 24, 25, 30, 31, 32,
27
- 33, 34, 35, 36, 8, 17, 8, 7, 41, 37,
28
- nil, 8, 5, 6, nil, 38, 37, nil, nil, nil,
29
- nil, 30, 31, 32, 33, 34, 35, 36, 30, 31,
30
- 32, 33, 34, 35, 36, 8, 7, 8, 7, 8,
31
- 7, 5, 6, 5, 6, 5, 6, 8, 7, nil,
32
- nil, nil, nil, 5, 6 ]
25
+ 8, 7, 8, 7, 9, 37, 5, 6, 5, 6,
26
+ 28, 10, 12, 13, 17, 18, 22, 30, 31, 32,
27
+ 33, 34, 35, 36, 8, 7, 23, 24, 25, 37,
28
+ 5, 6, 8, 7, 17, 38, 41, 37, 5, 6,
29
+ nil, 30, 31, 32, 33, 34, 35, 36, nil, 30,
30
+ 31, 32, 33, 34, 35, 36, 8, 7, 8, 7,
31
+ 8, 7, 5, 6, 5, 6, 5, 6, 8, 7,
32
+ 8, 7, nil, nil, 5, 6, 5, 6 ]
33
33
 
34
34
  racc_action_check = [
35
- 25, 0, 0, 1, 2, 25, 4, 0, 0, 5,
36
- 25, 8, 9, 17, 20, 21, 22, 25, 25, 25,
37
- 25, 25, 25, 25, 28, 24, 3, 3, 39, 28,
38
- nil, 40, 3, 3, nil, 28, 40, nil, nil, nil,
39
- nil, 28, 28, 28, 28, 28, 28, 28, 40, 40,
40
- 40, 40, 40, 40, 40, 6, 6, 7, 7, 10,
41
- 10, 6, 6, 7, 7, 10, 10, 13, 13, nil,
42
- nil, nil, nil, 13, 13 ]
35
+ 25, 25, 0, 0, 1, 25, 25, 25, 0, 0,
36
+ 25, 2, 4, 5, 8, 9, 17, 25, 25, 25,
37
+ 25, 25, 25, 25, 28, 28, 20, 21, 22, 28,
38
+ 28, 28, 40, 40, 24, 28, 39, 40, 40, 40,
39
+ nil, 28, 28, 28, 28, 28, 28, 28, nil, 40,
40
+ 40, 40, 40, 40, 40, 40, 3, 3, 6, 6,
41
+ 7, 7, 3, 3, 6, 6, 7, 7, 10, 10,
42
+ 13, 13, nil, nil, 10, 10, 13, 13 ]
43
43
 
44
44
  racc_action_pointer = [
45
- -2, 3, 2, 23, -11, -6, 52, 54, 0, 12,
46
- 56, nil, nil, 64, nil, nil, nil, 7, nil, nil,
47
- -2, 3, -2, nil, 14, -3, nil, nil, 21, nil,
48
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 14,
49
- 28, nil, nil ]
45
+ -1, 4, 9, 53, -5, -2, 55, 57, 3, 15,
46
+ 65, nil, nil, 67, nil, nil, nil, 10, nil, nil,
47
+ 10, 15, 10, nil, 23, -3, nil, nil, 21, nil,
48
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 22,
49
+ 29, nil, nil ]
50
50
 
51
51
  racc_action_default = [
52
52
  -28, -28, -2, -4, -6, -28, -28, -28, -10, -28,
@@ -56,15 +56,19 @@ racc_action_default = [
56
56
  -18, -16, -17 ]
57
57
 
58
58
  racc_goto_table = [
59
- 16, 39, 29, 11, 1, 29, 21, 27, 14, 15,
60
- nil, nil, nil, 42, 19, 20, 26, 29 ]
59
+ 14, 15, 16, 39, 1, 11, 21, 20, 27, nil,
60
+ nil, nil, nil, nil, 19, 42, nil, nil, 26, 29,
61
+ nil, nil, 29, nil, nil, nil, nil, nil, nil, nil,
62
+ nil, nil, nil, nil, 29 ]
61
63
 
62
64
  racc_goto_check = [
63
- 5, 8, 4, 2, 1, 4, 6, 7, 3, 3,
64
- nil, nil, nil, 8, 1, 3, 5, 4 ]
65
+ 3, 3, 5, 8, 1, 2, 6, 3, 7, nil,
66
+ nil, nil, nil, nil, 1, 8, nil, nil, 5, 3,
67
+ nil, nil, 3, nil, nil, nil, nil, nil, nil, nil,
68
+ nil, nil, nil, nil, 3 ]
65
69
 
66
70
  racc_goto_pointer = [
67
- nil, 4, 0, 2, -23, -8, -11, -18, -27 ]
71
+ nil, 4, 2, -6, nil, -6, -11, -17, -25 ]
68
72
 
69
73
  racc_goto_default = [
70
74
  nil, nil, 2, 3, 4, nil, nil, 40, nil ]
@@ -37,7 +37,7 @@ rule
37
37
  | value { NodeQuery::Compiler::ArrayValue.new(value: val[0]) }
38
38
 
39
39
  value
40
- : basic_selector
40
+ : selector
41
41
  | tBOOLEAN { NodeQuery::Compiler::Boolean.new(value: val[0]) }
42
42
  | tFLOAT { NodeQuery::Compiler::Float.new(value: val[0]) }
43
43
  | tINTEGER { NodeQuery::Compiler::Integer.new(value: val[0])}
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.8.1
4
+ version: 1.10.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-10-15 00:00:00.000000000 Z
11
+ date: 2022-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -40,6 +40,7 @@ files:
40
40
  - Rakefile
41
41
  - lib/node_query.rb
42
42
  - lib/node_query/adapter.rb
43
+ - lib/node_query/any_value.rb
43
44
  - lib/node_query/compiler.rb
44
45
  - lib/node_query/compiler/array_value.rb
45
46
  - lib/node_query/compiler/attribute.rb