synvert-core 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 +4 -4
- data/.github/workflows/main.yml +0 -1
- data/.gitignore +0 -5
- data/CHANGELOG.md +12 -0
- data/Gemfile +0 -3
- data/Gemfile.lock +101 -0
- data/Guardfile +0 -9
- data/README.md +31 -13
- data/Rakefile +1 -15
- data/lib/synvert/core/engine/erb.rb +1 -1
- data/lib/synvert/core/engine.rb +1 -1
- data/lib/synvert/core/node_ext.rb +0 -639
- data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +20 -17
- data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -5
- data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -5
- data/lib/synvert/core/rewriter/condition.rb +5 -1
- data/lib/synvert/core/rewriter/instance.rb +91 -140
- data/lib/synvert/core/rewriter/scope/query_scope.rb +8 -6
- data/lib/synvert/core/rewriter/scope/within_scope.rb +4 -87
- data/lib/synvert/core/rewriter.rb +0 -10
- data/lib/synvert/core/version.rb +1 -1
- data/lib/synvert/core.rb +4 -6
- data/spec/synvert/core/engine/erb_spec.rb +3 -3
- data/spec/synvert/core/node_ext_spec.rb +0 -965
- data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +21 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +64 -131
- data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -4
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +1 -16
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +22 -13
- data/synvert-core-ruby.gemspec +5 -3
- metadata +46 -62
- data/lib/synvert/core/array_ext.rb +0 -48
- data/lib/synvert/core/node_query/compiler/array.rb +0 -34
- data/lib/synvert/core/node_query/compiler/attribute.rb +0 -39
- data/lib/synvert/core/node_query/compiler/attribute_list.rb +0 -24
- data/lib/synvert/core/node_query/compiler/basic_selector.rb +0 -28
- data/lib/synvert/core/node_query/compiler/boolean.rb +0 -23
- data/lib/synvert/core/node_query/compiler/comparable.rb +0 -86
- data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +0 -51
- data/lib/synvert/core/node_query/compiler/expression.rb +0 -41
- data/lib/synvert/core/node_query/compiler/float.rb +0 -23
- data/lib/synvert/core/node_query/compiler/identifier.rb +0 -41
- data/lib/synvert/core/node_query/compiler/integer.rb +0 -23
- data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +0 -7
- data/lib/synvert/core/node_query/compiler/nil.rb +0 -23
- data/lib/synvert/core/node_query/compiler/parse_error.rb +0 -7
- data/lib/synvert/core/node_query/compiler/regexp.rb +0 -37
- data/lib/synvert/core/node_query/compiler/selector.rb +0 -113
- data/lib/synvert/core/node_query/compiler/string.rb +0 -23
- data/lib/synvert/core/node_query/compiler/symbol.rb +0 -23
- data/lib/synvert/core/node_query/compiler.rb +0 -25
- data/lib/synvert/core/node_query/lexer.rex +0 -99
- data/lib/synvert/core/node_query/lexer.rex.rb +0 -299
- data/lib/synvert/core/node_query/parser.racc.rb +0 -306
- data/lib/synvert/core/node_query/parser.y +0 -60
- data/lib/synvert/core/node_query.rb +0 -36
- data/lib/synvert/core/rewriter/action/append_action.rb +0 -28
- data/lib/synvert/core/rewriter/action/delete_action.rb +0 -34
- data/lib/synvert/core/rewriter/action/insert_action.rb +0 -34
- data/lib/synvert/core/rewriter/action/insert_after_action.rb +0 -22
- data/lib/synvert/core/rewriter/action/prepend_action.rb +0 -44
- data/lib/synvert/core/rewriter/action/remove_action.rb +0 -56
- data/lib/synvert/core/rewriter/action/replace_action.rb +0 -33
- data/lib/synvert/core/rewriter/action/replace_with_action.rb +0 -36
- data/lib/synvert/core/rewriter/action/wrap_action.rb +0 -37
- data/lib/synvert/core/rewriter/action.rb +0 -102
- data/spec/synvert/core/node_query/lexer_spec.rb +0 -580
- data/spec/synvert/core/node_query/parser_spec.rb +0 -337
- data/spec/synvert/core/rewriter/action/append_action_spec.rb +0 -70
- data/spec/synvert/core/rewriter/action/delete_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/insert_action_spec.rb +0 -70
- data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/prepend_action_spec.rb +0 -175
- data/spec/synvert/core/rewriter/action/remove_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/replace_action_spec.rb +0 -28
- data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +0 -59
- data/spec/synvert/core/rewriter/action/wrap_action_spec.rb +0 -31
- data/spec/synvert/core/rewriter/action_spec.rb +0 -14
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Array represents a ruby array value.
|
5
|
-
class Array
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize an Array.
|
9
|
-
# @param value the first value of the array
|
10
|
-
# @param rest the rest value of the array
|
11
|
-
def initialize(value: nil, rest: nil)
|
12
|
-
@value = value
|
13
|
-
@rest = rest
|
14
|
-
end
|
15
|
-
|
16
|
-
# Get the expected value.
|
17
|
-
# @return [Array]
|
18
|
-
def expected_value
|
19
|
-
expected = []
|
20
|
-
expected.push(@value) if @value
|
21
|
-
expected += @rest.expected_value if @rest
|
22
|
-
expected
|
23
|
-
end
|
24
|
-
|
25
|
-
# Get valid operators.
|
26
|
-
def valid_operators
|
27
|
-
ARRAY_VALID_OPERATORS
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
[@value, @rest].compact.join(' ')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Attribute is a pair of key, value and operator,
|
5
|
-
class Attribute
|
6
|
-
# Initialize a Attribute.
|
7
|
-
# @param key [String] the key
|
8
|
-
# @param value the value can be any class implement {Synvert::Core::NodeQuery::Compiler::Comparable}
|
9
|
-
# @param operator [Symbol] the operator
|
10
|
-
def initialize(key:, value:, operator: '==')
|
11
|
-
@key = key
|
12
|
-
@value = value
|
13
|
-
@operator = operator
|
14
|
-
end
|
15
|
-
|
16
|
-
# Check if the node matches the attribute.
|
17
|
-
# @param node [Parser::AST::Node] the node
|
18
|
-
# @return [Boolean]
|
19
|
-
def match?(node)
|
20
|
-
@value.base_node = node if @value.is_a?(DynamicAttribute)
|
21
|
-
node && @value.match?(node.child_node_by_name(@key), @operator)
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_s
|
25
|
-
case @operator
|
26
|
-
when '^=', '$=', '*=', '!=', '=~', '!~', '>=', '>', '<=', '<'
|
27
|
-
"#{@key}#{@operator}#{@value}"
|
28
|
-
when 'in'
|
29
|
-
"#{@key} in (#{@value})"
|
30
|
-
when 'not_in'
|
31
|
-
"#{@key} not in (#{@value})"
|
32
|
-
when 'includes'
|
33
|
-
"#{@key} includes #{@value}"
|
34
|
-
else
|
35
|
-
"#{@key}=#{@value}"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# AttributeList contains one or more {Synvert::Core::NodeQuery::Compiler::Attribute}.
|
5
|
-
class AttributeList
|
6
|
-
# Initialize a AttributeList.
|
7
|
-
# @param attribute [Synvert::Core::NodeQuery::Compiler::Attribute] the attribute
|
8
|
-
# @param rest [Synvert::Core::NodeQuery::Compiler::AttributeList] the rest attribute list
|
9
|
-
def initialize(attribute:, rest: nil)
|
10
|
-
@attribute = attribute
|
11
|
-
@rest = rest
|
12
|
-
end
|
13
|
-
|
14
|
-
# Check if the node matches the attribute list.
|
15
|
-
# @return [Boolean]
|
16
|
-
def match?(node)
|
17
|
-
@attribute.match?(node) && (!@rest || @rest.match?(node))
|
18
|
-
end
|
19
|
-
|
20
|
-
def to_s
|
21
|
-
"[#{@attribute}]#{@rest}"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# BasicSelector used to match nodes, it combines by node type and/or attribute list.
|
5
|
-
class BasicSelector
|
6
|
-
# Initialize a BasicSelector.
|
7
|
-
# @param node_type [String] the node type
|
8
|
-
# @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
|
9
|
-
def initialize(node_type:, attribute_list: nil)
|
10
|
-
@node_type = node_type
|
11
|
-
@attribute_list = attribute_list
|
12
|
-
end
|
13
|
-
|
14
|
-
# Check if node matches the selector.
|
15
|
-
# @param node [Parser::AST::Node] the node
|
16
|
-
def match?(node, _operator = '==')
|
17
|
-
return false unless node
|
18
|
-
|
19
|
-
@node_type.to_sym == node.type && (!@attribute_list || @attribute_list.match?(node))
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_s
|
23
|
-
result = [".#{@node_type}"]
|
24
|
-
result << @attribute_list.to_s if @attribute_list
|
25
|
-
result.join('')
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Boolean represents a ruby boolean value.
|
5
|
-
class Boolean
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize a Boolean.
|
9
|
-
# @param value [Boolean] the boolean value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Get valid operators.
|
15
|
-
def valid_operators
|
16
|
-
SIMPLE_VALID_OPERATORS
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
@value.to_s
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Compare acutal value with expected value.
|
5
|
-
module Comparable
|
6
|
-
SIMPLE_VALID_OPERATORS = ['==', '!=', 'includes']
|
7
|
-
STRING_VALID_OPERATORS = ['==', '!=', '^=', '$=', '*=', 'includes']
|
8
|
-
NUMBER_VALID_OPERATORS = ['==', '!=', '>', '>=', '<', '<=', 'includes']
|
9
|
-
ARRAY_VALID_OPERATORS = ['==', '!=', 'in', 'not_in']
|
10
|
-
REGEXP_VALID_OPERATORS = ['=~', '!~']
|
11
|
-
|
12
|
-
# Check if the actual value matches the expected value.
|
13
|
-
#
|
14
|
-
# @param node [Parser::AST::Node] node to calculate actual value
|
15
|
-
# @param operator [Symbol] operator to compare with expected value, operator can be <code>'=='</code>, <code>'!='</code>, <code>'>'</code>, <code>'>='</code>, <code>'<'</code>, <code>'<='</code>, <code>'includes'</code>, <code>'in'</code>, <code>'not_in'</code>, <code>'=~'</code>, <code>'!~'</code>
|
16
|
-
# @return [Boolean] true if actual value matches the expected value
|
17
|
-
# @raise [Synvert::Core::NodeQuery::Compiler::InvalidOperatorError] if operator is invalid
|
18
|
-
def match?(node, operator)
|
19
|
-
raise InvalidOperatorError, "invalid operator #{operator}" unless valid_operator?(operator)
|
20
|
-
|
21
|
-
case operator
|
22
|
-
when '!='
|
23
|
-
if expected_value.is_a?(::Array)
|
24
|
-
actual = actual_value(node)
|
25
|
-
!actual.is_a?(::Array) || actual.size != expected_value.size ||
|
26
|
-
actual.zip(expected_value).any? { |actual_node, expected_node| expected_node.match?(actual_node, '!=') }
|
27
|
-
else
|
28
|
-
actual_value(node) != expected_value
|
29
|
-
end
|
30
|
-
when '=~'
|
31
|
-
actual_value(node) =~ expected_value
|
32
|
-
when '!~'
|
33
|
-
actual_value(node) !~ expected_value
|
34
|
-
when '^='
|
35
|
-
actual_value(node).start_with?(expected_value)
|
36
|
-
when '$='
|
37
|
-
actual_value(node).end_with?(expected_value)
|
38
|
-
when '*='
|
39
|
-
actual_value(node).include?(expected_value)
|
40
|
-
when '>'
|
41
|
-
actual_value(node) > expected_value
|
42
|
-
when '>='
|
43
|
-
actual_value(node) >= expected_value
|
44
|
-
when '<'
|
45
|
-
actual_value(node) < expected_value
|
46
|
-
when '<='
|
47
|
-
actual_value(node) <= expected_value
|
48
|
-
when 'in'
|
49
|
-
expected_value.any? { |expected| expected.match?(node, '==') }
|
50
|
-
when 'not_in'
|
51
|
-
expected_value.all? { |expected| expected.match?(node, '!=') }
|
52
|
-
when 'includes'
|
53
|
-
actual_value(node).any? { |actual| actual == expected_value }
|
54
|
-
else
|
55
|
-
if expected_value.is_a?(::Array)
|
56
|
-
actual = actual_value(node)
|
57
|
-
actual.is_a?(::Array) && actual.size == expected_value.size &&
|
58
|
-
actual.zip(expected_value).all? { |actual_node, expected_node| expected_node.match?(actual_node, '==') }
|
59
|
-
else
|
60
|
-
actual_value(node) == expected_value
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Get the actual value from ast node.
|
66
|
-
# @return if node is a {Parser::AST::Node}, return the node value, otherwise, return the node itself.
|
67
|
-
def actual_value(node)
|
68
|
-
if node.is_a?(::Parser::AST::Node)
|
69
|
-
node.to_value
|
70
|
-
else
|
71
|
-
node
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Get the expected value
|
76
|
-
def expected_value
|
77
|
-
@value
|
78
|
-
end
|
79
|
-
|
80
|
-
# Check if the operator is valid.
|
81
|
-
# @return [Boolean] true if the operator is valid
|
82
|
-
def valid_operator?(operator)
|
83
|
-
valid_operators.include?(operator)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# DynamicAttribute represents a ruby dynamic attribute.
|
5
|
-
# e.g. code is <code>{ a: a }</code>, query is <code>'.hash > .pair[key={{value}}]'</code>,
|
6
|
-
# <code>{{value}}</code> is the dynamic attribute.
|
7
|
-
class DynamicAttribute
|
8
|
-
include Comparable
|
9
|
-
|
10
|
-
attr_accessor :base_node
|
11
|
-
|
12
|
-
# Initialize a DynamicAttribute.
|
13
|
-
# @param value [String] the dynamic attribute value
|
14
|
-
def initialize(value:)
|
15
|
-
@value = value
|
16
|
-
end
|
17
|
-
|
18
|
-
# Get the actual value of a node.
|
19
|
-
#
|
20
|
-
# @param node the node
|
21
|
-
# @return [String] if node is a {Parser::AST::Node}, return the node source code, otherwise return the node itself.
|
22
|
-
def actual_value(node)
|
23
|
-
if node.is_a?(::Parser::AST::Node)
|
24
|
-
node.to_source
|
25
|
-
else
|
26
|
-
node
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Get the expected value.
|
31
|
-
#
|
32
|
-
# @return [String] Query the node by @valud from base_node, if the node is a {Parser::AST::Node}, return the node source code, otherwise return the node itself.
|
33
|
-
def expected_value
|
34
|
-
node = base_node.child_node_by_name(@value)
|
35
|
-
if node.is_a?(::Parser::AST::Node)
|
36
|
-
node.to_source
|
37
|
-
else
|
38
|
-
node
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Get valid operators.
|
43
|
-
def valid_operators
|
44
|
-
SIMPLE_VALID_OPERATORS
|
45
|
-
end
|
46
|
-
|
47
|
-
def to_s
|
48
|
-
"{{#{@value}}}"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Expression represents a node query expression.
|
5
|
-
class Expression
|
6
|
-
# Initialize a Expression.
|
7
|
-
# @param selector [Synvert::Core::NodeQuery::Compiler::Selector] the selector
|
8
|
-
# @param rest [Synvert::Core::NodeQuery::Compiler::Expression] the rest expression
|
9
|
-
def initialize(selector: nil, rest: nil)
|
10
|
-
@selector = selector
|
11
|
-
@rest = rest
|
12
|
-
end
|
13
|
-
|
14
|
-
# Check if the node matches the expression.
|
15
|
-
# @param node [Parser::AST::Node] the node
|
16
|
-
# @return [Boolean]
|
17
|
-
def match?(node)
|
18
|
-
!query_nodes(node).empty?
|
19
|
-
end
|
20
|
-
|
21
|
-
# Query nodes by the selector and the rest expression.
|
22
|
-
#
|
23
|
-
# @param node [Parser::AST::Node] node to match
|
24
|
-
# @return [Array<Parser::AST::Node>] matching nodes.
|
25
|
-
def query_nodes(node)
|
26
|
-
matching_nodes = @selector.query_nodes(node)
|
27
|
-
return matching_nodes if @rest.nil?
|
28
|
-
|
29
|
-
matching_nodes.flat_map do |matching_node|
|
30
|
-
@rest.query_nodes(matching_node)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_s
|
35
|
-
result = []
|
36
|
-
result << @selector.to_s if @selector
|
37
|
-
result << @rest.to_s if @rest
|
38
|
-
result.join(' ')
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Float represents a ruby float value.
|
5
|
-
class Float
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize a Float.
|
9
|
-
# @param value [Float] the float value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Get valid operators.
|
15
|
-
def valid_operators
|
16
|
-
NUMBER_VALID_OPERATORS
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
@value.to_s
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Identifier represents a ruby identifier value.
|
5
|
-
# e.g. code is `class Synvert; end`, `Synvert` is an identifier.
|
6
|
-
class Identifier
|
7
|
-
include Comparable
|
8
|
-
|
9
|
-
# Initialize an Identifier.
|
10
|
-
# @param value [String] the identifier value
|
11
|
-
def initialize(value:)
|
12
|
-
@value = value
|
13
|
-
end
|
14
|
-
|
15
|
-
# Get the actual value.
|
16
|
-
#
|
17
|
-
# @param node the node
|
18
|
-
# @return [String|Array]
|
19
|
-
# If the node is a {Parser::AST::Node}, return the node source code,
|
20
|
-
# if the node is an Array, return the array of each element's actual value,
|
21
|
-
# otherwise, return the String value.
|
22
|
-
def actual_value(node)
|
23
|
-
if node.is_a?(::Parser::AST::Node)
|
24
|
-
node.to_source
|
25
|
-
elsif node.is_a?(::Array)
|
26
|
-
node.map { |n| actual_value(n) }
|
27
|
-
else
|
28
|
-
node.to_s
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Get valid operators.
|
33
|
-
def valid_operators
|
34
|
-
STRING_VALID_OPERATORS
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_s
|
38
|
-
@value
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Integer represents a ruby integer value.
|
5
|
-
class Integer
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize a Integer.
|
9
|
-
# @param value [Integer] the integer value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Get valid operators.
|
15
|
-
def valid_operators
|
16
|
-
NUMBER_VALID_OPERATORS
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
@value.to_s
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Nil represents a ruby nil value.
|
5
|
-
class Nil
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize a Nil.
|
9
|
-
# @param value [nil] the nil value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Get valid operators.
|
15
|
-
def valid_operators
|
16
|
-
SIMPLE_VALID_OPERATORS
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
'nil'
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Regexp represents a ruby regexp value.
|
5
|
-
class Regexp
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize a Regexp.
|
9
|
-
# @param value [Regexp] the regexp value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Check if the regexp value matches the node value.
|
15
|
-
# @param node [Parser::AST::Node] the node
|
16
|
-
# @param operator [Symbol] 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 node.is_a?(::Parser::AST::Node)
|
21
|
-
@value.match(node.to_source)
|
22
|
-
else
|
23
|
-
@value.match(node.to_s)
|
24
|
-
end
|
25
|
-
operator == '=~' ? match : !match
|
26
|
-
end
|
27
|
-
|
28
|
-
# Get valid operators.
|
29
|
-
def valid_operators
|
30
|
-
REGEXP_VALID_OPERATORS
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_s
|
34
|
-
@value.to_s
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Selector used to match nodes, it combines by node type and/or attribute list, plus index or has expression.
|
5
|
-
class Selector
|
6
|
-
# Initialize a Selector.
|
7
|
-
# @param goto_scope [String] goto scope
|
8
|
-
# @param relationship [Symbol] the relationship between the selectors, it can be descendant <code>nil</code>, child <code>></code>, next sibling <code>+</code> or subsequent sibing <code>~</code>.
|
9
|
-
# @param rest [Synvert::Core::NodeQuery::Compiler::Selector] the rest selector
|
10
|
-
# @param basic_selector [Synvert::Core::NodeQuery::Compiler::BasicSelector] the simple selector
|
11
|
-
# @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
|
12
|
-
# @param pseudo_class [String] the pseudo class, can be <code>has</code> or <code>not_has</code>
|
13
|
-
# @param pseudo_selector [Synvert::Core::NodeQuery::Compiler::Expression] the pseudo selector
|
14
|
-
def initialize(goto_scope: nil, relationship: nil, rest: nil, basic_selector: nil, pseudo_class: nil, pseudo_selector: nil)
|
15
|
-
@goto_scope = goto_scope
|
16
|
-
@relationship = relationship
|
17
|
-
@rest = rest
|
18
|
-
@basic_selector = basic_selector
|
19
|
-
@pseudo_class = pseudo_class
|
20
|
-
@pseudo_selector = pseudo_selector
|
21
|
-
end
|
22
|
-
|
23
|
-
# Check if node matches the selector.
|
24
|
-
# @param node [Parser::AST::Node] the node
|
25
|
-
def match?(node)
|
26
|
-
node.is_a?(::Parser::AST::Node) && (!@basic_selector || @basic_selector.match?(node)) && match_pseudo_class?(node)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Query nodes by the selector.
|
30
|
-
#
|
31
|
-
# * If relationship is nil, it will match in all recursive child nodes and return matching nodes.
|
32
|
-
# * If relationship is decendant, it will match in all recursive child nodes.
|
33
|
-
# * If relationship is child, it will match in direct child nodes.
|
34
|
-
# * If relationship is next sibling, it try to match next sibling node.
|
35
|
-
# * If relationship is subsequent sibling, it will match in all sibling nodes.
|
36
|
-
# @param node [Parser::AST::Node] node to match
|
37
|
-
# @return [Array<Parser::AST::Node>] matching nodes.
|
38
|
-
def query_nodes(node)
|
39
|
-
return find_nodes_by_relationship(node) if @relationship
|
40
|
-
|
41
|
-
if node.is_a?(::Array)
|
42
|
-
return node.flat_map { |child_node| query_nodes(child_node) }
|
43
|
-
end
|
44
|
-
|
45
|
-
return find_nodes_by_goto_scope(node) if @goto_scope
|
46
|
-
|
47
|
-
nodes = []
|
48
|
-
nodes << node if match?(node)
|
49
|
-
if @basic_selector
|
50
|
-
node.recursive_children do |child_node|
|
51
|
-
nodes << child_node if match?(child_node)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
nodes
|
55
|
-
end
|
56
|
-
|
57
|
-
def to_s
|
58
|
-
result = []
|
59
|
-
result << "#{@goto_scope} " if @goto_scope
|
60
|
-
result << "#{@relationship} " if @relationship
|
61
|
-
result << @rest.to_s if @rest
|
62
|
-
result << @basic_selector.to_s if @basic_selector
|
63
|
-
result << ":#{@pseudo_class}(#{@pseudo_selector})" if @pseudo_class
|
64
|
-
result.join('')
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
# Find nodes by @goto_scope
|
70
|
-
# @param node [Parser::AST::Node] node to match
|
71
|
-
def find_nodes_by_goto_scope(node)
|
72
|
-
@goto_scope.split('.').each { |scope| node = node.send(scope) }
|
73
|
-
@rest.query_nodes(node)
|
74
|
-
end
|
75
|
-
|
76
|
-
# Find ndoes by @relationship
|
77
|
-
# @param node [Parser::AST::Node] node to match
|
78
|
-
def find_nodes_by_relationship(node)
|
79
|
-
nodes = []
|
80
|
-
case @relationship
|
81
|
-
when '>'
|
82
|
-
if node.is_a?(::Array)
|
83
|
-
node.each do |child_node|
|
84
|
-
nodes << child_node if @rest.match?(child_node)
|
85
|
-
end
|
86
|
-
else
|
87
|
-
node.children.each do |child_node|
|
88
|
-
nodes << child_node if @rest.match?(child_node)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
when '+'
|
92
|
-
next_sibling = node.siblings.first
|
93
|
-
nodes << next_sibling if @rest.match?(next_sibling)
|
94
|
-
when '~'
|
95
|
-
node.siblings.each do |sibling_node|
|
96
|
-
nodes << sibling_node if @rest.match?(sibling_node)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
nodes
|
100
|
-
end
|
101
|
-
|
102
|
-
def match_pseudo_class?(node)
|
103
|
-
case @pseudo_class
|
104
|
-
when 'has'
|
105
|
-
!@pseudo_selector.query_nodes(node).empty?
|
106
|
-
when 'not_has'
|
107
|
-
@pseudo_selector.query_nodes(node).empty?
|
108
|
-
else
|
109
|
-
true
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# String represents a ruby string value.
|
5
|
-
class String
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initialize a String.
|
9
|
-
# @param value [String] the string value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Get valid operators.
|
15
|
-
def valid_operators
|
16
|
-
STRING_VALID_OPERATORS
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
"\"#{@value}\""
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Synvert::Core::NodeQuery::Compiler
|
4
|
-
# Symbol represents a ruby symbol value.
|
5
|
-
class Symbol
|
6
|
-
include Comparable
|
7
|
-
|
8
|
-
# Initliaze a Symobol.
|
9
|
-
# @param value [Symbol] the symbol value
|
10
|
-
def initialize(value:)
|
11
|
-
@value = value
|
12
|
-
end
|
13
|
-
|
14
|
-
# Get valid operators.
|
15
|
-
def valid_operators
|
16
|
-
SIMPLE_VALID_OPERATORS
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
":#{@value}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|