mutant 0.10.20 → 0.10.25
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 +4 -4
- data/lib/mutant.rb +23 -4
- data/lib/mutant/ast/meta/send.rb +0 -1
- data/lib/mutant/ast/regexp.rb +37 -0
- data/lib/mutant/ast/regexp/transformer.rb +150 -0
- data/lib/mutant/ast/regexp/transformer/direct.rb +121 -0
- data/lib/mutant/ast/regexp/transformer/named_group.rb +50 -0
- data/lib/mutant/ast/regexp/transformer/options_group.rb +68 -0
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +90 -0
- data/lib/mutant/ast/regexp/transformer/recursive.rb +56 -0
- data/lib/mutant/ast/regexp/transformer/root.rb +28 -0
- data/lib/mutant/ast/regexp/transformer/text.rb +58 -0
- data/lib/mutant/ast/types.rb +115 -11
- data/lib/mutant/cli/command/environment.rb +9 -3
- data/lib/mutant/config.rb +8 -54
- data/lib/mutant/config/coverage_criteria.rb +61 -0
- data/lib/mutant/env.rb +8 -6
- data/lib/mutant/expression.rb +0 -12
- data/lib/mutant/expression/namespace.rb +1 -1
- data/lib/mutant/isolation/fork.rb +1 -1
- data/lib/mutant/loader.rb +1 -1
- data/lib/mutant/matcher.rb +2 -2
- data/lib/mutant/matcher/config.rb +27 -6
- data/lib/mutant/matcher/method.rb +2 -3
- data/lib/mutant/matcher/method/metaclass.rb +1 -1
- data/lib/mutant/meta/example/dsl.rb +6 -1
- data/lib/mutant/mutator/node/arguments.rb +0 -2
- data/lib/mutant/mutator/node/block.rb +5 -1
- data/lib/mutant/mutator/node/dynamic_literal.rb +1 -1
- data/lib/mutant/mutator/node/kwargs.rb +44 -0
- data/lib/mutant/mutator/node/literal/regex.rb +26 -0
- data/lib/mutant/mutator/node/literal/symbol.rb +0 -2
- data/lib/mutant/mutator/node/regexp.rb +20 -0
- data/lib/mutant/mutator/node/regexp/alternation_meta.rb +20 -0
- data/lib/mutant/mutator/node/regexp/beginning_of_line_anchor.rb +20 -0
- data/lib/mutant/mutator/node/regexp/capture_group.rb +25 -0
- data/lib/mutant/mutator/node/regexp/character_type.rb +31 -0
- data/lib/mutant/mutator/node/regexp/end_of_line_anchor.rb +20 -0
- data/lib/mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb +20 -0
- data/lib/mutant/mutator/node/regexp/zero_or_more.rb +34 -0
- data/lib/mutant/mutator/node/sclass.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +36 -19
- data/lib/mutant/parallel.rb +43 -28
- data/lib/mutant/parallel/driver.rb +9 -3
- data/lib/mutant/parallel/worker.rb +60 -2
- data/lib/mutant/pipe.rb +94 -0
- data/lib/mutant/reporter/cli/printer/env.rb +1 -1
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +1 -6
- data/lib/mutant/result.rb +8 -0
- data/lib/mutant/runner.rb +7 -10
- data/lib/mutant/runner/sink.rb +12 -2
- data/lib/mutant/subject.rb +1 -3
- data/lib/mutant/subject/method/instance.rb +2 -4
- data/lib/mutant/timer.rb +2 -4
- data/lib/mutant/transform.rb +25 -2
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/world.rb +1 -2
- metadata +48 -9
- data/lib/mutant/warnings.rb +0 -106
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f02dec057593b8e61c2b207918ed6f1b9c4aa1d41bc0b2f2390c2a1da9172b5d
         | 
| 4 | 
            +
              data.tar.gz: 99a318ed1f02d9976037694b2dbc1de463863f747cc4b8b5e95809b307680f03
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 5312bd87fc41b3442b886b40b200357c254c2d7d65081cdfaca2e2e213311539eb23b00eb5b792c9f7978c8eeed5a6cbd72b3a513598b9abc9f72a3beaa9989d
         | 
| 7 | 
            +
              data.tar.gz: 922e0ea1878e05f014a3c832d7bfa23e0d8410cc8c8d5b9bd1bc8b81124a18ecd11403be643cd144772863950076b17ab06ce3cd809cda01a9563ec815c95e79
         | 
    
        data/lib/mutant.rb
    CHANGED
    
    | @@ -17,6 +17,7 @@ require 'optparse' | |
| 17 17 | 
             
            require 'parser'
         | 
| 18 18 | 
             
            require 'parser/current'
         | 
| 19 19 | 
             
            require 'pathname'
         | 
| 20 | 
            +
            require 'regexp_parser'
         | 
| 20 21 | 
             
            require 'set'
         | 
| 21 22 | 
             
            require 'singleton'
         | 
| 22 23 | 
             
            require 'stringio'
         | 
| @@ -40,9 +41,11 @@ module Mutant | |
| 40 41 | 
             
              SCOPE_OPERATOR = '::'
         | 
| 41 42 | 
             
            end # Mutant
         | 
| 42 43 |  | 
| 44 | 
            +
            require 'mutant/transform'
         | 
| 43 45 | 
             
            require 'mutant/bootstrap'
         | 
| 44 46 | 
             
            require 'mutant/version'
         | 
| 45 47 | 
             
            require 'mutant/env'
         | 
| 48 | 
            +
            require 'mutant/pipe'
         | 
| 46 49 | 
             
            require 'mutant/util'
         | 
| 47 50 | 
             
            require 'mutant/registry'
         | 
| 48 51 | 
             
            require 'mutant/ast'
         | 
| @@ -52,6 +55,15 @@ require 'mutant/ast/nodes' | |
| 52 55 | 
             
            require 'mutant/ast/named_children'
         | 
| 53 56 | 
             
            require 'mutant/ast/node_predicates'
         | 
| 54 57 | 
             
            require 'mutant/ast/find_metaclass_containing'
         | 
| 58 | 
            +
            require 'mutant/ast/regexp'
         | 
| 59 | 
            +
            require 'mutant/ast/regexp/transformer'
         | 
| 60 | 
            +
            require 'mutant/ast/regexp/transformer/direct'
         | 
| 61 | 
            +
            require 'mutant/ast/regexp/transformer/named_group'
         | 
| 62 | 
            +
            require 'mutant/ast/regexp/transformer/options_group'
         | 
| 63 | 
            +
            require 'mutant/ast/regexp/transformer/quantifier'
         | 
| 64 | 
            +
            require 'mutant/ast/regexp/transformer/recursive'
         | 
| 65 | 
            +
            require 'mutant/ast/regexp/transformer/root'
         | 
| 66 | 
            +
            require 'mutant/ast/regexp/transformer/text'
         | 
| 55 67 | 
             
            require 'mutant/ast/meta'
         | 
| 56 68 | 
             
            require 'mutant/ast/meta/send'
         | 
| 57 69 | 
             
            require 'mutant/ast/meta/const'
         | 
| @@ -74,6 +86,14 @@ require 'mutant/mutator/util/array' | |
| 74 86 | 
             
            require 'mutant/mutator/util/symbol'
         | 
| 75 87 | 
             
            require 'mutant/mutator/node'
         | 
| 76 88 | 
             
            require 'mutant/mutator/node/generic'
         | 
| 89 | 
            +
            require 'mutant/mutator/node/regexp'
         | 
| 90 | 
            +
            require 'mutant/mutator/node/regexp/alternation_meta'
         | 
| 91 | 
            +
            require 'mutant/mutator/node/regexp/beginning_of_line_anchor'
         | 
| 92 | 
            +
            require 'mutant/mutator/node/regexp/capture_group'
         | 
| 93 | 
            +
            require 'mutant/mutator/node/regexp/character_type'
         | 
| 94 | 
            +
            require 'mutant/mutator/node/regexp/end_of_line_anchor'
         | 
| 95 | 
            +
            require 'mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor'
         | 
| 96 | 
            +
            require 'mutant/mutator/node/regexp/zero_or_more'
         | 
| 77 97 | 
             
            require 'mutant/mutator/node/literal'
         | 
| 78 98 | 
             
            require 'mutant/mutator/node/literal/boolean'
         | 
| 79 99 | 
             
            require 'mutant/mutator/node/literal/range'
         | 
| @@ -129,6 +149,7 @@ require 'mutant/mutator/node/rescue' | |
| 129 149 | 
             
            require 'mutant/mutator/node/match_current_line'
         | 
| 130 150 | 
             
            require 'mutant/mutator/node/index'
         | 
| 131 151 | 
             
            require 'mutant/mutator/node/procarg_zero'
         | 
| 152 | 
            +
            require 'mutant/mutator/node/kwargs'
         | 
| 132 153 | 
             
            require 'mutant/loader'
         | 
| 133 154 | 
             
            require 'mutant/context'
         | 
| 134 155 | 
             
            require 'mutant/scope'
         | 
| @@ -157,7 +178,6 @@ require 'mutant/expression/methods' | |
| 157 178 | 
             
            require 'mutant/expression/namespace'
         | 
| 158 179 | 
             
            require 'mutant/test'
         | 
| 159 180 | 
             
            require 'mutant/timer'
         | 
| 160 | 
            -
            require 'mutant/transform'
         | 
| 161 181 | 
             
            require 'mutant/integration'
         | 
| 162 182 | 
             
            require 'mutant/integration/null'
         | 
| 163 183 | 
             
            require 'mutant/selector'
         | 
| @@ -165,6 +185,7 @@ require 'mutant/selector/expression' | |
| 165 185 | 
             
            require 'mutant/selector/null'
         | 
| 166 186 | 
             
            require 'mutant/world'
         | 
| 167 187 | 
             
            require 'mutant/config'
         | 
| 188 | 
            +
            require 'mutant/config/coverage_criteria'
         | 
| 168 189 | 
             
            require 'mutant/cli'
         | 
| 169 190 | 
             
            require 'mutant/cli/command'
         | 
| 170 191 | 
             
            require 'mutant/cli/command/subscription'
         | 
| @@ -194,7 +215,6 @@ require 'mutant/reporter/cli/format' | |
| 194 215 | 
             
            require 'mutant/repository'
         | 
| 195 216 | 
             
            require 'mutant/repository/diff'
         | 
| 196 217 | 
             
            require 'mutant/repository/diff/ranges'
         | 
| 197 | 
            -
            require 'mutant/warnings'
         | 
| 198 218 | 
             
            require 'mutant/zombifier'
         | 
| 199 219 | 
             
            require 'mutant/range'
         | 
| 200 220 | 
             
            require 'mutant/license'
         | 
| @@ -220,8 +240,7 @@ module Mutant | |
| 220 240 | 
             
                stderr:             $stderr,
         | 
| 221 241 | 
             
                stdout:             $stdout,
         | 
| 222 242 | 
             
                thread:             Thread,
         | 
| 223 | 
            -
                timer:              Timer.new(Process) | 
| 224 | 
            -
                warnings:           Warnings.new(Warning)
         | 
| 243 | 
            +
                timer:              Timer.new(Process)
         | 
| 225 244 | 
             
              )
         | 
| 226 245 |  | 
| 227 246 | 
             
              # Reopen class to initialize constant to avoid dep circle
         | 
    
        data/lib/mutant/ast/meta/send.rb
    CHANGED
    
    
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Mutant
         | 
| 4 | 
            +
              module AST
         | 
| 5 | 
            +
                # Regexp source mapper
         | 
| 6 | 
            +
                module Regexp
         | 
| 7 | 
            +
                  # Parse regex string into expression
         | 
| 8 | 
            +
                  #
         | 
| 9 | 
            +
                  # @param regexp [String]
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  # @return [Regexp::Expression, nil]
         | 
| 12 | 
            +
                  def self.parse(regexp)
         | 
| 13 | 
            +
                    ::Regexp::Parser.parse(regexp)
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  # Convert expression into ast node
         | 
| 17 | 
            +
                  #
         | 
| 18 | 
            +
                  # @param expression [Regexp::Expression]
         | 
| 19 | 
            +
                  #
         | 
| 20 | 
            +
                  # @return [Parser::AST::Node]
         | 
| 21 | 
            +
                  def self.to_ast(expression)
         | 
| 22 | 
            +
                    ast_type = :"regexp_#{expression.token}_#{expression.type}"
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    Transformer.lookup(ast_type).to_ast(expression)
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  # Convert node into expression
         | 
| 28 | 
            +
                  #
         | 
| 29 | 
            +
                  # @param node [Parser::AST::Node]
         | 
| 30 | 
            +
                  #
         | 
| 31 | 
            +
                  # @return [Regexp::Expression]
         | 
| 32 | 
            +
                  def self.to_expression(node)
         | 
| 33 | 
            +
                    Transformer.lookup(node.type).to_expression(node)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end # Regexp
         | 
| 36 | 
            +
              end # AST
         | 
| 37 | 
            +
            end # Mutant
         | 
| @@ -0,0 +1,150 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Mutant
         | 
| 4 | 
            +
              module AST
         | 
| 5 | 
            +
                module Regexp
         | 
| 6 | 
            +
                  # Regexp bijective mapper
         | 
| 7 | 
            +
                  #
         | 
| 8 | 
            +
                  # Transforms parsed regular expression representation from
         | 
| 9 | 
            +
                  # `Regexp::Expression` instances (provided by `regexp_parser`) into
         | 
| 10 | 
            +
                  # equivalent representations using `Parser::AST::Node`
         | 
| 11 | 
            +
                  class Transformer
         | 
| 12 | 
            +
                    include AbstractType
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    REGISTRY = Registry.new
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    # Lookup transformer class for regular expression node type
         | 
| 17 | 
            +
                    #
         | 
| 18 | 
            +
                    # @param type [Symbol]
         | 
| 19 | 
            +
                    #
         | 
| 20 | 
            +
                    # @return [Class<Transformer>]
         | 
| 21 | 
            +
                    def self.lookup(type)
         | 
| 22 | 
            +
                      REGISTRY.lookup(type)
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                    def self.register(type)
         | 
| 26 | 
            +
                      REGISTRY.register(type, self)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                    private_class_method :register
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    # Transform expression
         | 
| 31 | 
            +
                    #
         | 
| 32 | 
            +
                    # @param expression [Regexp::Expression]
         | 
| 33 | 
            +
                    #
         | 
| 34 | 
            +
                    # @return [Parser::AST::Node]
         | 
| 35 | 
            +
                    def self.to_ast(expression)
         | 
| 36 | 
            +
                      self::ExpressionToAST.call(expression)
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    # Transform node
         | 
| 40 | 
            +
                    #
         | 
| 41 | 
            +
                    # @param node [Parser::AST::Node]
         | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    # @return [Regexp::Expression]
         | 
| 44 | 
            +
                    def self.to_expression(node)
         | 
| 45 | 
            +
                      self::ASTToExpression.call(node)
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    # Abstract expression transformer
         | 
| 49 | 
            +
                    class ExpressionToAST
         | 
| 50 | 
            +
                      PREFIX = :regexp
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                      include Concord.new(:expression), Procto.call, AST::Sexp, AbstractType, Adamantium
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                    private
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                      def ast(*children)
         | 
| 57 | 
            +
                        s(type, *children)
         | 
| 58 | 
            +
                      end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                      def quantify(node)
         | 
| 61 | 
            +
                        return node unless expression.quantified?
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                        Quantifier.to_ast(expression.quantifier).append(node)
         | 
| 64 | 
            +
                      end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                      def children
         | 
| 67 | 
            +
                        expression.map(&Regexp.public_method(:to_ast))
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                      def type
         | 
| 71 | 
            +
                        :"#{PREFIX}_#{expression.token}_#{expression.type}"
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end # ExpressionToAST
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    # Abstract node transformer
         | 
| 76 | 
            +
                    class ASTToExpression
         | 
| 77 | 
            +
                      include Concord.new(:node), Procto.call, AbstractType, Adamantium
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      # Call generic transform method and freeze result
         | 
| 80 | 
            +
                      #
         | 
| 81 | 
            +
                      # @return [Regexp::Expression]
         | 
| 82 | 
            +
                      def call
         | 
| 83 | 
            +
                        transform.freeze
         | 
| 84 | 
            +
                      end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    private
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      abstract_method :transform
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                      def subexpressions
         | 
| 91 | 
            +
                        node.children.map(&Regexp.public_method(:to_expression))
         | 
| 92 | 
            +
                      end
         | 
| 93 | 
            +
                    end # ASTToExpression
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                    # Mixin for node transformers
         | 
| 96 | 
            +
                    #
         | 
| 97 | 
            +
                    # Helps construct a mapping from Parser::AST::Node domain to
         | 
| 98 | 
            +
                    # Regexp::Expression domain
         | 
| 99 | 
            +
                    module LookupTable
         | 
| 100 | 
            +
                      Mapping = Class.new.include(Concord::Public.new(:token, :regexp_class))
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                      # Table mapping ast types to object information for regexp domain
         | 
| 103 | 
            +
                      class Table
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                        # Coerce array of mapping information into structured table
         | 
| 106 | 
            +
                        #
         | 
| 107 | 
            +
                        # @param [Array(Symbol, Array, Class<Regexp::Expression>)]
         | 
| 108 | 
            +
                        #
         | 
| 109 | 
            +
                        # @return [Table]
         | 
| 110 | 
            +
                        def self.create(*rows)
         | 
| 111 | 
            +
                          table = rows.map do |ast_type, token, klass|
         | 
| 112 | 
            +
                            [ast_type, Mapping.new(::Regexp::Token.new(*token), klass)]
         | 
| 113 | 
            +
                          end.to_h
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                          new(table)
         | 
| 116 | 
            +
                        end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                        include Concord.new(:table), Adamantium
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                        # Types defined by the table
         | 
| 121 | 
            +
                        #
         | 
| 122 | 
            +
                        # @return [Array<Symbol>]
         | 
| 123 | 
            +
                        def types
         | 
| 124 | 
            +
                          table.keys
         | 
| 125 | 
            +
                        end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                        # Lookup mapping information given an ast node type
         | 
| 128 | 
            +
                        #
         | 
| 129 | 
            +
                        # @param type [Symbol]
         | 
| 130 | 
            +
                        #
         | 
| 131 | 
            +
                        # @return [Mapping]
         | 
| 132 | 
            +
                        def lookup(type)
         | 
| 133 | 
            +
                          table.fetch(type)
         | 
| 134 | 
            +
                        end
         | 
| 135 | 
            +
                      end # Table
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    private
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                      def expression_token
         | 
| 140 | 
            +
                        self.class::TABLE.lookup(node.type).token
         | 
| 141 | 
            +
                      end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                      def expression_class
         | 
| 144 | 
            +
                        self.class::TABLE.lookup(node.type).regexp_class
         | 
| 145 | 
            +
                      end
         | 
| 146 | 
            +
                    end # LookupTable
         | 
| 147 | 
            +
                  end # Transformer
         | 
| 148 | 
            +
                end # Regexp
         | 
| 149 | 
            +
              end # AST
         | 
| 150 | 
            +
            end # Mutant
         | 
| @@ -0,0 +1,121 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Mutant
         | 
| 4 | 
            +
              module AST
         | 
| 5 | 
            +
                module Regexp
         | 
| 6 | 
            +
                  class Transformer
         | 
| 7 | 
            +
                    # Transformer for nodes which map directly to other domain
         | 
| 8 | 
            +
                    #
         | 
| 9 | 
            +
                    # A node maps "directly" to another domain if the node never
         | 
| 10 | 
            +
                    # has children or text which needs to be preserved for a mapping
         | 
| 11 | 
            +
                    #
         | 
| 12 | 
            +
                    # @example direct mapping
         | 
| 13 | 
            +
                    #
         | 
| 14 | 
            +
                    #     input      = /\d/
         | 
| 15 | 
            +
                    #     expression = Regexp::Parser.parse(input).first
         | 
| 16 | 
            +
                    #     node       = Transformer::Direct.to_ast(expression)
         | 
| 17 | 
            +
                    #
         | 
| 18 | 
            +
                    #     # the digit type always has the same text and no children
         | 
| 19 | 
            +
                    #     expression.text      # => "\\d"
         | 
| 20 | 
            +
                    #     expression.terminal? # => true
         | 
| 21 | 
            +
                    #
         | 
| 22 | 
            +
                    #     # therefore the `Parser::AST::Node` is always the same
         | 
| 23 | 
            +
                    #     node # => s(:regexp_digit_type)
         | 
| 24 | 
            +
                    class Direct < self
         | 
| 25 | 
            +
                      # Mapper from `Regexp::Expression` to `Parser::AST::Node`
         | 
| 26 | 
            +
                      class ExpressionToAST < Transformer::ExpressionToAST
         | 
| 27 | 
            +
                        # Transform expression into node
         | 
| 28 | 
            +
                        #
         | 
| 29 | 
            +
                        # @return [Parser::AST::Node]
         | 
| 30 | 
            +
                        def call
         | 
| 31 | 
            +
                          quantify(ast)
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                      end # ExpressionToAST
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                      # Mapper from `Parser::AST::Node` to `Regexp::Expression`
         | 
| 36 | 
            +
                      class ASTToExpression < Transformer::ASTToExpression
         | 
| 37 | 
            +
                        include LookupTable
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                        # rubocop:disable Layout/LineLength
         | 
| 40 | 
            +
                        TABLE = Table.create(
         | 
| 41 | 
            +
                          [:regexp_alnum_posixclass,         [:posixclass,    :alnum,            '[:alnum:]'],    ::Regexp::Expression::PosixClass],
         | 
| 42 | 
            +
                          [:regexp_alpha_posixclass,         [:posixclass,    :alpha,            '[:alpha:]'],    ::Regexp::Expression::PosixClass],
         | 
| 43 | 
            +
                          [:regexp_alpha_property,           [:property,      :alpha,            '\p{Alpha}'],    ::Regexp::Expression::UnicodeProperty::Alpha],
         | 
| 44 | 
            +
                          [:regexp_alternation_escape,       [:escape,        :alternation,      '\|'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 45 | 
            +
                          [:regexp_arabic_property,          [:property,      :arabic,           '\p{Arabic}'],   ::Regexp::Expression::UnicodeProperty::Script],
         | 
| 46 | 
            +
                          [:regexp_ascii_posixclass,         [:posixclass,    :ascii,            '[:ascii:]'],    ::Regexp::Expression::PosixClass],
         | 
| 47 | 
            +
                          [:regexp_backspace_escape,         [:escape,        :backspace,        '\b'],           ::Regexp::Expression::EscapeSequence::Backspace],
         | 
| 48 | 
            +
                          [:regexp_bell_escape,              [:escape,        :bell,             '\a'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 49 | 
            +
                          [:regexp_blank_posixclass,         [:posixclass,    :blank,            '[:blank:]'],    ::Regexp::Expression::PosixClass],
         | 
| 50 | 
            +
                          [:regexp_bol_anchor,               [:anchor,        :bol,              '^'],            ::Regexp::Expression::Anchor::BeginningOfLine],
         | 
| 51 | 
            +
                          [:regexp_bol_escape,               [:escape,        :bol,              '\^'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 52 | 
            +
                          [:regexp_bos_anchor,               [:anchor,        :bos,              '\\A'],          ::Regexp::Expression::Anchor::BeginningOfString],
         | 
| 53 | 
            +
                          [:regexp_carriage_escape,          [:escape,        :carriage,         '\r'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 54 | 
            +
                          [:regexp_cntrl_posixclass,         [:posixclass,    :cntrl,            '[:cntrl:]'],    ::Regexp::Expression::PosixClass],
         | 
| 55 | 
            +
                          [:regexp_digit_posixclass,         [:posixclass,    :digit,            '[:digit:]'],    ::Regexp::Expression::PosixClass],
         | 
| 56 | 
            +
                          [:regexp_digit_type,               [:type,          :digit,            '\d'],           ::Regexp::Expression::CharacterType::Digit],
         | 
| 57 | 
            +
                          [:regexp_dot_escape,               [:escape,        :dot,              '\.'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 58 | 
            +
                          [:regexp_dot_meta,                 [:meta,          :dot,              '.'],            ::Regexp::Expression::CharacterType::Any],
         | 
| 59 | 
            +
                          [:regexp_eol_anchor,               [:anchor,        :eol,              '$'],            ::Regexp::Expression::Anchor::EndOfLine],
         | 
| 60 | 
            +
                          [:regexp_eol_escape,               [:escape,        :eol,              '\$'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 61 | 
            +
                          [:regexp_eos_anchor,               [:anchor,        :eos,              '\\z'],          ::Regexp::Expression::Anchor::EndOfString],
         | 
| 62 | 
            +
                          [:regexp_eos_ob_eol_anchor,        [:anchor,        :eos_ob_eol,       '\\Z'],          ::Regexp::Expression::Anchor::EndOfStringOrBeforeEndOfLine],
         | 
| 63 | 
            +
                          [:regexp_escape_escape,            [:escape,        :escape,           '\e'],           ::Regexp::Expression::EscapeSequence::AsciiEscape],
         | 
| 64 | 
            +
                          [:regexp_form_feed_escape,         [:escape,        :form_feed,        '\f'],           ::Regexp::Expression::EscapeSequence::FormFeed],
         | 
| 65 | 
            +
                          [:regexp_graph_posixclass,         [:posixclass,    :graph,            '[:graph:]'],    ::Regexp::Expression::PosixClass],
         | 
| 66 | 
            +
                          [:regexp_group_close_escape,       [:escape,        :group_close,      '\)'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 67 | 
            +
                          [:regexp_group_open_escape,        [:escape,        :group_open,       '\('],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 68 | 
            +
                          [:regexp_han_property,             [:property,      :han,              '\p{Han}'],      ::Regexp::Expression::UnicodeProperty::Script],
         | 
| 69 | 
            +
                          [:regexp_hangul_property,          [:property,      :hangul,           '\p{Hangul}'],   ::Regexp::Expression::UnicodeProperty::Script],
         | 
| 70 | 
            +
                          [:regexp_hex_type,                 [:type,          :hex,              '\h'],           ::Regexp::Expression::CharacterType::Hex],
         | 
| 71 | 
            +
                          [:regexp_hiragana_property,        [:property,      :hiragana,         '\p{Hiragana}'], ::Regexp::Expression::UnicodeProperty::Script],
         | 
| 72 | 
            +
                          [:regexp_interval_close_escape,    [:escape,        :interval_close,   '\}'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 73 | 
            +
                          [:regexp_interval_open_escape,     [:escape,        :interval_open,    '\{'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 74 | 
            +
                          [:regexp_katakana_property,        [:property,      :katakana,         '\p{Katakana}'], ::Regexp::Expression::UnicodeProperty::Script],
         | 
| 75 | 
            +
                          [:regexp_letter_property,          [:property,      :letter,           '\p{L}'],        ::Regexp::Expression::UnicodeProperty::Letter::Any],
         | 
| 76 | 
            +
                          [:regexp_linebreak_type,           [:type,          :linebreak,        '\R'],           ::Regexp::Expression::CharacterType::Linebreak],
         | 
| 77 | 
            +
                          [:regexp_lower_posixclass,         [:posixclass,    :lower,            '[:lower:]'],    ::Regexp::Expression::PosixClass],
         | 
| 78 | 
            +
                          [:regexp_mark_keep,                [:keep,          :mark,             '\K'],           ::Regexp::Expression::Keep::Mark],
         | 
| 79 | 
            +
                          [:regexp_match_start_anchor,       [:anchor,        :match_start,      '\\G'],          ::Regexp::Expression::Anchor::MatchStart],
         | 
| 80 | 
            +
                          [:regexp_newline_escape,           [:escape,        :newline,          '\n'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 81 | 
            +
                          [:regexp_nondigit_type,            [:type,          :nondigit,         '\D'],           ::Regexp::Expression::CharacterType::NonDigit],
         | 
| 82 | 
            +
                          [:regexp_nonhex_type,              [:type,          :nonhex,           '\H'],           ::Regexp::Expression::CharacterType::NonHex],
         | 
| 83 | 
            +
                          [:regexp_nonspace_type,            [:type,          :nonspace,         '\S'],           ::Regexp::Expression::CharacterType::NonSpace],
         | 
| 84 | 
            +
                          [:regexp_nonword_boundary_anchor,  [:anchor,        :nonword_boundary, '\\B'],          ::Regexp::Expression::Anchor::NonWordBoundary],
         | 
| 85 | 
            +
                          [:regexp_nonword_type,             [:type,          :nonword,          '\W'],           ::Regexp::Expression::CharacterType::NonWord],
         | 
| 86 | 
            +
                          [:regexp_one_or_more_escape,       [:escape,        :one_or_more,      '\+'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 87 | 
            +
                          [:regexp_print_nonposixclass,      [:nonposixclass, :print,            '[:^print:]'],   ::Regexp::Expression::PosixClass],
         | 
| 88 | 
            +
                          [:regexp_print_nonproperty,        [:nonproperty,   :print,            '\P{Print}'],    ::Regexp::Expression::UnicodeProperty::Print],
         | 
| 89 | 
            +
                          [:regexp_print_posixclass,         [:posixclass,    :print,            '[:print:]'],    ::Regexp::Expression::PosixClass],
         | 
| 90 | 
            +
                          [:regexp_print_posixclass,         [:posixclass,    :print,            '[:print:]'],    ::Regexp::Expression::PosixClass],
         | 
| 91 | 
            +
                          [:regexp_print_property,           [:property,      :print,            '\p{Print}'],    ::Regexp::Expression::UnicodeProperty::Print],
         | 
| 92 | 
            +
                          [:regexp_punct_posixclass,         [:posixclass,    :punct,            '[:punct:]'],    ::Regexp::Expression::PosixClass],
         | 
| 93 | 
            +
                          [:regexp_set_close_escape,         [:escape,        :set_close,        '\]'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 94 | 
            +
                          [:regexp_set_open_escape,          [:escape,        :set_open,         '\['],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 95 | 
            +
                          [:regexp_space_posixclass,         [:posixclass,    :space,            '[:space:]'],    ::Regexp::Expression::PosixClass],
         | 
| 96 | 
            +
                          [:regexp_space_type,               [:type,          :space,            '\s'],           ::Regexp::Expression::CharacterType::Space],
         | 
| 97 | 
            +
                          [:regexp_upper_posixclass,         [:posixclass,    :upper,            '[:upper:]'],    ::Regexp::Expression::PosixClass],
         | 
| 98 | 
            +
                          [:regexp_vertical_tab_escape,      [:escape,        :vertical_tab,     '\v'],           ::Regexp::Expression::EscapeSequence::VerticalTab],
         | 
| 99 | 
            +
                          [:regexp_word_boundary_anchor,     [:anchor,        :word_boundary,    '\b'],           ::Regexp::Expression::Anchor::WordBoundary],
         | 
| 100 | 
            +
                          [:regexp_word_posixclass,          [:posixclass,    :word,             '[:word:]'],     ::Regexp::Expression::PosixClass],
         | 
| 101 | 
            +
                          [:regexp_word_type,                [:type,          :word,             '\w'],           ::Regexp::Expression::CharacterType::Word],
         | 
| 102 | 
            +
                          [:regexp_xdigit_posixclass,        [:posixclass,    :xdigit,           '[:xdigit:]'],   ::Regexp::Expression::PosixClass],
         | 
| 103 | 
            +
                          [:regexp_xgrapheme_type,           [:type,          :xgrapheme,        '\X'],           ::Regexp::Expression::CharacterType::ExtendedGrapheme],
         | 
| 104 | 
            +
                          [:regexp_zero_or_more_escape,      [:escape,        :zero_or_more,     '\*'],           ::Regexp::Expression::EscapeSequence::Literal],
         | 
| 105 | 
            +
                          [:regexp_zero_or_one_escape,       [:escape,        :zero_or_one,      '\?'],           ::Regexp::Expression::EscapeSequence::Literal]
         | 
| 106 | 
            +
                        )
         | 
| 107 | 
            +
                      # rubocop:enable Layout/LineLength
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                      private
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                        def transform
         | 
| 112 | 
            +
                          expression_class.new(expression_token)
         | 
| 113 | 
            +
                        end
         | 
| 114 | 
            +
                      end # ASTToExpression
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                      ASTToExpression::TABLE.types.each(&method(:register))
         | 
| 117 | 
            +
                    end # Direct
         | 
| 118 | 
            +
                  end # Transformer
         | 
| 119 | 
            +
                end # Regexp
         | 
| 120 | 
            +
              end # AST
         | 
| 121 | 
            +
            end # Mutant
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Mutant
         | 
| 4 | 
            +
              module AST
         | 
| 5 | 
            +
                module Regexp
         | 
| 6 | 
            +
                  class Transformer
         | 
| 7 | 
            +
                    # Transformer for named groups
         | 
| 8 | 
            +
                    class NamedGroup < self
         | 
| 9 | 
            +
                      register :regexp_named_group
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                      # Mapper from `Regexp::Expression` to `Parser::AST::Node`
         | 
| 12 | 
            +
                      class ExpressionToAST < Transformer::ExpressionToAST
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                        # Transform named group into node
         | 
| 15 | 
            +
                        #
         | 
| 16 | 
            +
                        # @return [Parser::AST::Node]
         | 
| 17 | 
            +
                        def call
         | 
| 18 | 
            +
                          quantify(ast(expression.name, *children))
         | 
| 19 | 
            +
                        end
         | 
| 20 | 
            +
                      end # ExpressionToAST
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      # Mapper from `Parser::AST::Node` to `Regexp::Expression`
         | 
| 23 | 
            +
                      class ASTToExpression < Transformer::ASTToExpression
         | 
| 24 | 
            +
                        include NamedChildren
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                        children :name
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                      private
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                        def transform
         | 
| 31 | 
            +
                          named_group.tap do |expression|
         | 
| 32 | 
            +
                            expression.expressions = subexpressions
         | 
| 33 | 
            +
                          end
         | 
| 34 | 
            +
                        end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                        def subexpressions
         | 
| 37 | 
            +
                          remaining_children.map(&Regexp.public_method(:to_expression))
         | 
| 38 | 
            +
                        end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                        def named_group
         | 
| 41 | 
            +
                          ::Regexp::Expression::Group::Named.new(
         | 
| 42 | 
            +
                            ::Regexp::Token.new(:group, :named, "(?<#{name}>")
         | 
| 43 | 
            +
                          )
         | 
| 44 | 
            +
                        end
         | 
| 45 | 
            +
                      end # ASTToExpression
         | 
| 46 | 
            +
                    end # NamedGroup
         | 
| 47 | 
            +
                  end # Transformer
         | 
| 48 | 
            +
                end # Regexp
         | 
| 49 | 
            +
              end # AST
         | 
| 50 | 
            +
            end # Mutant
         |