synvert-core 0.63.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/.gitignore +4 -0
  4. data/CHANGELOG.md +9 -1
  5. data/Guardfile +11 -2
  6. data/README.md +74 -34
  7. data/Rakefile +15 -1
  8. data/lib/synvert/core/array_ext.rb +41 -0
  9. data/lib/synvert/core/configuration.rb +12 -0
  10. data/lib/synvert/core/engine/erb.rb +9 -8
  11. data/lib/synvert/core/exceptions.rb +0 -4
  12. data/lib/synvert/core/node_ext.rb +232 -128
  13. data/lib/synvert/core/node_query/compiler/array.rb +34 -0
  14. data/lib/synvert/core/node_query/compiler/attribute.rb +51 -0
  15. data/lib/synvert/core/node_query/compiler/attribute_list.rb +24 -0
  16. data/lib/synvert/core/node_query/compiler/boolean.rb +23 -0
  17. data/lib/synvert/core/node_query/compiler/comparable.rb +79 -0
  18. data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +51 -0
  19. data/lib/synvert/core/node_query/compiler/expression.rb +88 -0
  20. data/lib/synvert/core/node_query/compiler/float.rb +23 -0
  21. data/lib/synvert/core/node_query/compiler/identifier.rb +41 -0
  22. data/lib/synvert/core/node_query/compiler/integer.rb +23 -0
  23. data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +7 -0
  24. data/lib/synvert/core/node_query/compiler/nil.rb +23 -0
  25. data/lib/synvert/core/node_query/compiler/parse_error.rb +7 -0
  26. data/lib/synvert/core/node_query/compiler/regexp.rb +37 -0
  27. data/lib/synvert/core/node_query/compiler/selector.rb +51 -0
  28. data/lib/synvert/core/node_query/compiler/string.rb +34 -0
  29. data/lib/synvert/core/node_query/compiler/symbol.rb +23 -0
  30. data/lib/synvert/core/node_query/compiler.rb +24 -0
  31. data/lib/synvert/core/node_query/lexer.rex +96 -0
  32. data/lib/synvert/core/node_query/lexer.rex.rb +293 -0
  33. data/lib/synvert/core/node_query/parser.racc.rb +518 -0
  34. data/lib/synvert/core/node_query/parser.y +84 -0
  35. data/lib/synvert/core/node_query.rb +36 -0
  36. data/lib/synvert/core/rewriter/action/append_action.rb +4 -3
  37. data/lib/synvert/core/rewriter/action/delete_action.rb +17 -8
  38. data/lib/synvert/core/rewriter/action/insert_action.rb +16 -7
  39. data/lib/synvert/core/rewriter/action/insert_after_action.rb +3 -2
  40. data/lib/synvert/core/rewriter/action/prepend_action.rb +3 -2
  41. data/lib/synvert/core/rewriter/action/remove_action.rb +16 -10
  42. data/lib/synvert/core/rewriter/action/replace_action.rb +15 -5
  43. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +18 -11
  44. data/lib/synvert/core/rewriter/action/replace_with_action.rb +6 -5
  45. data/lib/synvert/core/rewriter/action/wrap_action.rb +16 -7
  46. data/lib/synvert/core/rewriter/action.rb +22 -10
  47. data/lib/synvert/core/rewriter/any_value.rb +1 -0
  48. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +4 -0
  49. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +4 -0
  50. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +4 -0
  51. data/lib/synvert/core/rewriter/condition.rb +11 -3
  52. data/lib/synvert/core/rewriter/gem_spec.rb +6 -3
  53. data/lib/synvert/core/rewriter/helper.rb +7 -4
  54. data/lib/synvert/core/rewriter/instance.rb +217 -104
  55. data/lib/synvert/core/rewriter/ruby_version.rb +4 -4
  56. data/lib/synvert/core/rewriter/scope/goto_scope.rb +5 -6
  57. data/lib/synvert/core/rewriter/scope/query_scope.rb +36 -0
  58. data/lib/synvert/core/rewriter/scope/within_scope.rb +10 -5
  59. data/lib/synvert/core/rewriter/scope.rb +8 -0
  60. data/lib/synvert/core/rewriter/warning.rb +1 -1
  61. data/lib/synvert/core/rewriter.rb +91 -43
  62. data/lib/synvert/core/version.rb +1 -1
  63. data/lib/synvert/core.rb +22 -6
  64. data/spec/synvert/core/engine/erb_spec.rb +2 -2
  65. data/spec/synvert/core/node_ext_spec.rb +36 -12
  66. data/spec/synvert/core/node_query/lexer_spec.rb +512 -0
  67. data/spec/synvert/core/node_query/parser_spec.rb +270 -0
  68. data/spec/synvert/core/rewriter/action_spec.rb +0 -4
  69. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +1 -6
  70. data/spec/synvert/core/rewriter/gem_spec_spec.rb +1 -1
  71. data/spec/synvert/core/rewriter/helper_spec.rb +4 -1
  72. data/spec/synvert/core/rewriter/instance_spec.rb +31 -20
  73. data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +74 -0
  74. data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +12 -9
  75. data/spec/synvert/core/rewriter_spec.rb +4 -2
  76. data/synvert-core-ruby.gemspec +7 -2
  77. metadata +91 -4
@@ -0,0 +1,51 @@
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}!=#{@value}"
28
+ when :=~
29
+ "#{@key}=~#{@value}"
30
+ when :!~
31
+ "#{@key}!~#{@value}"
32
+ when :>
33
+ "#{@key}>#{@value}"
34
+ when :>=
35
+ "#{@key}>=#{@value}"
36
+ when :<
37
+ "#{@key}<#{@value}"
38
+ when :<=
39
+ "#{@key}<=#{@value}"
40
+ when :in
41
+ "#{@key} in (#{@value})"
42
+ when :not_in
43
+ "#{@key} not in (#{@value})"
44
+ when :includes
45
+ "#{@key} includes #{@value}"
46
+ else
47
+ "#{@key}=#{@value}"
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,24 @@
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
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,79 @@
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
+ NUMBER_VALID_OPERATORS = [:==, :!=, :>, :>=, :<, :<=, :includes]
8
+ ARRAY_VALID_OPERATORS = [:==, :!=, :in, :not_in]
9
+ REGEXP_VALID_OPERATORS = [:=~, :!~]
10
+
11
+ # Check if the actual value matches the expected value.
12
+ #
13
+ # @param node [Parser::AST::Node] node to calculate actual value
14
+ # @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>
15
+ # @return [Boolean] true if actual value matches the expected value
16
+ # @raise [Synvert::Core::NodeQuery::Compiler::InvalidOperatorError] if operator is invalid
17
+ def match?(node, operator)
18
+ raise InvalidOperatorError, "invalid operator #{operator}" unless valid_operator?(operator)
19
+
20
+ case operator
21
+ when :!=
22
+ if expected_value.is_a?(::Array)
23
+ actual = actual_value(node)
24
+ !actual.is_a?(::Array) || actual.size != expected_value.size ||
25
+ actual.zip(expected_value).any? { |actual_node, expected_node| expected_node.match?(actual_node, :!=) }
26
+ else
27
+ actual_value(node) != expected_value
28
+ end
29
+ when :=~
30
+ actual_value(node) =~ expected_value
31
+ when :!~
32
+ actual_value(node) !~ expected_value
33
+ when :>
34
+ actual_value(node) > expected_value
35
+ when :>=
36
+ actual_value(node) >= expected_value
37
+ when :<
38
+ actual_value(node) < expected_value
39
+ when :<=
40
+ actual_value(node) <= expected_value
41
+ when :in
42
+ expected_value.any? { |expected| expected.match?(node, :==) }
43
+ when :not_in
44
+ expected_value.all? { |expected| expected.match?(node, :!=) }
45
+ when :includes
46
+ actual_value(node).any? { |actual| actual == expected_value }
47
+ else
48
+ if expected_value.is_a?(::Array)
49
+ actual = actual_value(node)
50
+ actual.is_a?(::Array) && actual.size == expected_value.size &&
51
+ actual.zip(expected_value).all? { |actual_node, expected_node| expected_node.match?(actual_node, :==) }
52
+ else
53
+ actual_value(node) == expected_value
54
+ end
55
+ end
56
+ end
57
+
58
+ # Get the actual value from ast node.
59
+ # @return if node is a {Parser::AST::Node}, return the node value, otherwise, return the node itself.
60
+ def actual_value(node)
61
+ if node.is_a?(::Parser::AST::Node)
62
+ node.to_value
63
+ else
64
+ node
65
+ end
66
+ end
67
+
68
+ # Get the expected value
69
+ def expected_value
70
+ @value
71
+ end
72
+
73
+ # Check if the operator is valid.
74
+ # @return [Boolean] true if the operator is valid
75
+ def valid_operator?(operator)
76
+ valid_operators.include?(operator)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,51 @@
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
@@ -0,0 +1,88 @@
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
+ # @param relationship [Symbol] the relationship between the selector and rest expression, it can be <code>:descendant</code>, <code>:child</code>, <code>:next_sibling</code>, <code>:subsequent_sibling</code> or <code>nil</code>.
10
+ def initialize(selector: nil, rest: nil, relationship: nil)
11
+ @selector = selector
12
+ @rest = rest
13
+ @relationship = relationship
14
+ end
15
+
16
+ # Check if the node matches the expression.
17
+ # @param node [Parser::AST::Node] the node
18
+ # @return [Boolean]
19
+ def match?(node)
20
+ !query_nodes(node).empty?
21
+ end
22
+
23
+ # Query nodes by the expression.
24
+ #
25
+ # * If relationship is nil, it will match in all recursive child nodes and return matching nodes.
26
+ # * If relationship is :decendant, it will match in all recursive child nodes.
27
+ # * If relationship is :child, it will match in direct child nodes.
28
+ # * If relationship is :next_sibling, it try to match next sibling node.
29
+ # * If relationship is :subsequent_sibling, it will match in all sibling nodes.
30
+ # @param node [Parser::AST::Node] node to match
31
+ # @param descendant_match [Boolean] whether to match in descendant node
32
+ # @return [Array<Parser::AST::Node>] matching nodes.
33
+ def query_nodes(node, descendant_match: true)
34
+ matching_nodes = find_nodes_without_relationship(node, descendant_match: descendant_match)
35
+ if @relationship.nil?
36
+ return matching_nodes
37
+ end
38
+
39
+ expression_nodes = matching_nodes.map do |matching_node|
40
+ case @relationship
41
+ when :descendant
42
+ nodes = []
43
+ matching_node.recursive_children { |child_node|
44
+ nodes += @rest.query_nodes(child_node, descendant_match: false)
45
+ }
46
+ nodes
47
+ when :child
48
+ matching_node.children.map { |child_node| @rest.query_nodes(child_node, descendant_match: false) }
49
+ .flatten
50
+ when :next_sibling
51
+ @rest.query_nodes(matching_node.siblings.first, descendant_match: false)
52
+ when :subsequent_sibling
53
+ matching_node.siblings.map { |sibling_node| @rest.query_nodes(sibling_node, descendant_match: false) }
54
+ .flatten
55
+ end
56
+ end.flatten
57
+ end
58
+
59
+ def to_s
60
+ return @selector.to_s unless @rest
61
+
62
+ result = []
63
+ result << @selector if @selector
64
+ case @relationship
65
+ when :child then result << '>'
66
+ when :subsequent_sibling then result << '~'
67
+ when :next_sibling then result << '+'
68
+ end
69
+ result << @rest
70
+ result.map(&:to_s).join(' ')
71
+ end
72
+
73
+ private
74
+
75
+ def find_nodes_without_relationship(node, descendant_match: true)
76
+ return [node] unless @selector
77
+
78
+ nodes = []
79
+ nodes << node if @selector.match?(node)
80
+ if descendant_match
81
+ node.recursive_children do |child_node|
82
+ nodes << child_node if @selector.match?(child_node)
83
+ end
84
+ end
85
+ @selector.filter(nodes)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,41 @@
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
+ SIMPLE_VALID_OPERATORS
35
+ end
36
+
37
+ def to_s
38
+ @value
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core::NodeQuery::Compiler
4
+ # Operator is invalid error.
5
+ class InvalidOperatorError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core::NodeQuery::Compiler
4
+ # The parser error.
5
+ class ParseError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,51 @@
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 node_type [String] the node type
8
+ # @param attribute_list [Synvert::Core::NodeQuery::Compiler::AttributeList] the attribute list
9
+ # @param index [Integer] the index
10
+ # @param has_expression [Synvert::Core::NodeQuery::Compiler::Expression] the has expression
11
+ def initialize(node_type: nil, attribute_list: nil, index: nil, has_expression: nil)
12
+ @node_type = node_type
13
+ @attribute_list = attribute_list
14
+ @index = index
15
+ @has_expression = has_expression
16
+ end
17
+
18
+ # Filter nodes by index.
19
+ def filter(nodes)
20
+ return nodes if @index.nil?
21
+
22
+ nodes[@index] ? [nodes[@index]] : []
23
+ end
24
+
25
+ # Check if node matches the selector.
26
+ # @param node [Parser::AST::Node] the node
27
+ def match?(node, _operator = :==)
28
+ (!@node_type || (node.is_a?(::Parser::AST::Node) && @node_type.to_sym == node.type)) &&
29
+ (!@attribute_list || @attribute_list.match?(node)) &&
30
+ (!@has_expression || @has_expression.match?(node))
31
+ end
32
+
33
+ def to_s
34
+ str = ".#{@node_type}#{@attribute_list}"
35
+ return str if !@index && !@has_expression
36
+
37
+ return "#{str}:has(#{@has_expression})" if @has_expression
38
+
39
+ case @index
40
+ when 0
41
+ str + ':first-child'
42
+ when -1
43
+ str + ':last-child'
44
+ when (1..)
45
+ str + ":nth-child(#{@index + 1})"
46
+ else # ...-1
47
+ str + ":nth-last-child(#{-@index})"
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,34 @@
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
+ SIMPLE_VALID_OPERATORS
17
+ end
18
+
19
+ # Get the actual value of a node.
20
+ # @param node [Parser::AST::Node] the node
21
+ # @return [String] if node is a Parser::AST::Node, return the node source code, otherwise, return the string value.
22
+ def actual_value(node)
23
+ if node.is_a?(::Parser::AST::Node)
24
+ node.to_source
25
+ else
26
+ node.to_s
27
+ end
28
+ end
29
+
30
+ def to_s
31
+ "\"#{@value}\""
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core::NodeQuery::Compiler
4
+ autoload :InvalidOperatorError, 'synvert/core/node_query/compiler/invalid_operator_error'
5
+ autoload :ParseError, 'synvert/core/node_query/compiler/parse_error'
6
+
7
+ autoload :Comparable, 'synvert/core/node_query/compiler/comparable'
8
+
9
+ autoload :Expression, 'synvert/core/node_query/compiler/expression'
10
+ autoload :Selector, 'synvert/core/node_query/compiler/selector'
11
+ autoload :AttributeList, 'synvert/core/node_query/compiler/attribute_list'
12
+ autoload :Attribute, 'synvert/core/node_query/compiler/attribute'
13
+
14
+ autoload :Array, 'synvert/core/node_query/compiler/array'
15
+ autoload :Boolean, 'synvert/core/node_query/compiler/boolean'
16
+ autoload :DynamicAttribute, 'synvert/core/node_query/compiler/dynamic_attribute'
17
+ autoload :Float, 'synvert/core/node_query/compiler/float'
18
+ autoload :Identifier, 'synvert/core/node_query/compiler/identifier'
19
+ autoload :Integer, 'synvert/core/node_query/compiler/integer'
20
+ autoload :Nil, 'synvert/core/node_query/compiler/nil'
21
+ autoload :Regexp, 'synvert/core/node_query/compiler/regexp'
22
+ autoload :String, 'synvert/core/node_query/compiler/string'
23
+ autoload :Symbol, 'synvert/core/node_query/compiler/symbol'
24
+ end