mutant 0.11.3 → 0.11.6
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/ast/regexp/transformer.rb +2 -2
- data/lib/mutant/cli/command/environment/run.rb +5 -22
- data/lib/mutant/cli/command.rb +2 -2
- data/lib/mutant/env.rb +6 -7
- data/lib/mutant/license/subscription/opensource.rb +1 -1
- data/lib/mutant/loader.rb +4 -13
- data/lib/mutant/matcher/config.rb +2 -3
- data/lib/mutant/matcher/method/instance.rb +10 -0
- data/lib/mutant/matcher/method.rb +27 -3
- data/lib/mutant/matcher/methods.rb +3 -1
- data/lib/mutant/mutation.rb +5 -2
- data/lib/mutant/mutator/node/arguments.rb +26 -5
- data/lib/mutant/mutator/node/block_pass.rb +1 -0
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +3 -1
- data/lib/mutant/mutator/node/when.rb +1 -1
- data/lib/mutant/repository/diff.rb +1 -1
- data/lib/mutant/subject/method/instance.rb +5 -0
- data/lib/mutant/subject/method/singleton.rb +5 -0
- data/lib/mutant/subject/method.rb +1 -0
- data/lib/mutant/subject.rb +7 -0
- data/lib/mutant/transform.rb +1 -2
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +0 -3
- metadata +5 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 945d6584e161b704f52d2f1efc3b6a78df03cc0f6b48d52f157bf47720623725
         | 
| 4 | 
            +
              data.tar.gz: 7a507de1188d5d8a89740730d827c89f818dee72b844f3bccfa97264d1c1e266
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f37bb36a48e29385936390ebd92790051871b6ee9b5fe053c1249815ab4432db1dbe7633e236d5bf40c04a488c1f0288bca9e29b8282f7c8a4bd2bfe0da5ee15
         | 
| 7 | 
            +
              data.tar.gz: 281fc2061663198b9676c1000793104c7bb52fed3f4892b02419bd7a7aaf2a7168f23fb1c7ba0653710900cd7bf2637de99998da37b87cac1ca021a2dd10b0d8
         | 
| @@ -110,9 +110,9 @@ module Mutant | |
| 110 110 | 
             
                        #
         | 
| 111 111 | 
             
                        # @return [Table]
         | 
| 112 112 | 
             
                        def self.create(*rows)
         | 
| 113 | 
            -
                          table = rows. | 
| 113 | 
            +
                          table = rows.to_h do |ast_type, token, klass|
         | 
| 114 114 | 
             
                            [ast_type, Mapping.new(::Regexp::Token.new(*token), klass)]
         | 
| 115 | 
            -
                          end | 
| 115 | 
            +
                          end
         | 
| 116 116 |  | 
| 117 117 | 
             
                          new(table)
         | 
| 118 118 | 
             
                        end
         | 
| @@ -7,13 +7,13 @@ module Mutant | |
| 7 7 | 
             
                    class Run < self
         | 
| 8 8 | 
             
                      NAME              = 'run'
         | 
| 9 9 | 
             
                      SHORT_DESCRIPTION = 'Run code analysis'
         | 
| 10 | 
            -
                      SLEEP             = 60
         | 
| 11 10 | 
             
                      SUBCOMMANDS       = EMPTY_ARRAY
         | 
| 12 11 |  | 
| 13 12 | 
             
                      UNLICENSED = <<~MESSAGE.lines.freeze
         | 
| 14 | 
            -
                         | 
| 15 | 
            -
             | 
| 16 | 
            -
                        See https://github.com/mbj/mutant#licensing
         | 
| 13 | 
            +
                        You are using mutant unlicensed.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        See https://github.com/mbj/mutant#licensing to aquire a license.
         | 
| 16 | 
            +
                        Note: Its free for opensource use, which is recommended for trials.
         | 
| 17 17 | 
             
                      MESSAGE
         | 
| 18 18 |  | 
| 19 19 | 
             
                      NO_TESTS_MESSAGE = <<~'MESSAGE'
         | 
| @@ -40,7 +40,7 @@ module Mutant | |
| 40 40 | 
             
                    private
         | 
| 41 41 |  | 
| 42 42 | 
             
                      def action
         | 
| 43 | 
            -
                         | 
| 43 | 
            +
                        License.call(world)
         | 
| 44 44 | 
             
                          .bind { bootstrap }
         | 
| 45 45 | 
             
                          .bind(&method(:validate_tests))
         | 
| 46 46 | 
             
                          .bind(&Runner.public_method(:call))
         | 
| @@ -62,23 +62,6 @@ module Mutant | |
| 62 62 | 
             
                          Either::Left.new('Uncovered mutations detected, exiting nonzero!')
         | 
| 63 63 | 
             
                        end
         | 
| 64 64 | 
             
                      end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                      def soft_fail(result)
         | 
| 67 | 
            -
                        result.either(
         | 
| 68 | 
            -
                          lambda do |message|
         | 
| 69 | 
            -
                            stderr = world.stderr
         | 
| 70 | 
            -
                            stderr.puts(message)
         | 
| 71 | 
            -
                            UNLICENSED.each { |line| stderr.puts(unlicensed(line)) }
         | 
| 72 | 
            -
                            world.kernel.sleep(SLEEP)
         | 
| 73 | 
            -
                            Either::Right.new(nil)
         | 
| 74 | 
            -
                          end,
         | 
| 75 | 
            -
                          ->(_subscription) { Either::Right.new(nil) }
         | 
| 76 | 
            -
                        )
         | 
| 77 | 
            -
                      end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                      def unlicensed(message)
         | 
| 80 | 
            -
                        "[Mutant-License-Error]: #{message}"
         | 
| 81 | 
            -
                      end
         | 
| 82 65 | 
             
                    end # Run
         | 
| 83 66 | 
             
                  end # Environment
         | 
| 84 67 | 
             
                end # Command
         | 
    
        data/lib/mutant/cli/command.rb
    CHANGED
    
    | @@ -184,9 +184,9 @@ module Mutant | |
| 184 184 | 
             
                  end
         | 
| 185 185 |  | 
| 186 186 | 
             
                  def format_subcommands
         | 
| 187 | 
            -
                    commands = subcommands. | 
| 187 | 
            +
                    commands = subcommands.to_h do |subcommand|
         | 
| 188 188 | 
             
                      [subcommand.command_name, subcommand.short_description]
         | 
| 189 | 
            -
                    end | 
| 189 | 
            +
                    end
         | 
| 190 190 |  | 
| 191 191 | 
             
                    width = commands.each_key.map(&:length).max
         | 
| 192 192 |  | 
    
        data/lib/mutant/env.rb
    CHANGED
    
    | @@ -68,9 +68,9 @@ module Mutant | |
| 68 68 | 
             
                #
         | 
| 69 69 | 
             
                # @return Hash{Mutation => Enumerable<Test>}
         | 
| 70 70 | 
             
                def selections
         | 
| 71 | 
            -
                  subjects. | 
| 71 | 
            +
                  subjects.to_h do |subject|
         | 
| 72 72 | 
             
                    [subject, selector.call(subject)]
         | 
| 73 | 
            -
                  end | 
| 73 | 
            +
                  end
         | 
| 74 74 | 
             
                end
         | 
| 75 75 | 
             
                memoize :selections
         | 
| 76 76 |  | 
| @@ -142,11 +142,10 @@ module Mutant | |
| 142 142 | 
             
                    result = mutation.insert(world.kernel)
         | 
| 143 143 | 
             
                    hooks.run(:mutation_insert_post, mutation)
         | 
| 144 144 |  | 
| 145 | 
            -
                     | 
| 146 | 
            -
                      Result::Test::VoidValue.instance
         | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
                    end
         | 
| 145 | 
            +
                    result.either(
         | 
| 146 | 
            +
                      ->(_) { Result::Test::VoidValue.instance },
         | 
| 147 | 
            +
                      ->(_) { integration.call(tests) }
         | 
| 148 | 
            +
                    )
         | 
| 150 149 | 
             
                  end
         | 
| 151 150 | 
             
                end
         | 
| 152 151 |  | 
    
        data/lib/mutant/loader.rb
    CHANGED
    
    | @@ -9,17 +9,8 @@ module Mutant | |
| 9 9 |  | 
| 10 10 | 
             
                private_constant(*constants(false))
         | 
| 11 11 |  | 
| 12 | 
            -
                 | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
                  # Vale returned on successful load
         | 
| 16 | 
            -
                  class Success < self
         | 
| 17 | 
            -
                  end # Success
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  # Vale returned on MRI detecting void value expressions
         | 
| 20 | 
            -
                  class VoidValue < self
         | 
| 21 | 
            -
                  end # VoidValue
         | 
| 22 | 
            -
                end # Result
         | 
| 12 | 
            +
                VOID_VALUE = Either::Left.new(nil)
         | 
| 13 | 
            +
                SUCCESS    = Either::Right.new(nil)
         | 
| 23 14 |  | 
| 24 15 | 
             
                # Call loader
         | 
| 25 16 | 
             
                #
         | 
| @@ -45,12 +36,12 @@ module Mutant | |
| 45 36 | 
             
                rescue SyntaxError => exception
         | 
| 46 37 | 
             
                  # rubocop:disable Style/GuardClause
         | 
| 47 38 | 
             
                  if VOID_VALUE_REGEXP.match?(exception.message)
         | 
| 48 | 
            -
                     | 
| 39 | 
            +
                    VOID_VALUE
         | 
| 49 40 | 
             
                  else
         | 
| 50 41 | 
             
                    raise
         | 
| 51 42 | 
             
                  end
         | 
| 52 43 | 
             
                else
         | 
| 53 | 
            -
                   | 
| 44 | 
            +
                  SUCCESS
         | 
| 54 45 | 
             
                end
         | 
| 55 46 | 
             
              end # Loader
         | 
| 56 47 | 
             
            end # Mutant
         | 
| @@ -25,7 +25,7 @@ module Mutant | |
| 25 25 |  | 
| 26 26 | 
             
                  private_constant(*constants(false))
         | 
| 27 27 |  | 
| 28 | 
            -
                  DEFAULT = new(anima.attribute_names. | 
| 28 | 
            +
                  DEFAULT = new(anima.attribute_names.to_h { |name| [name, []] })
         | 
| 29 29 |  | 
| 30 30 | 
             
                  expression = Transform::Block.capture(:expression) do |input|
         | 
| 31 31 | 
             
                    Mutant::Config::DEFAULT.expression_parser.call(input)
         | 
| @@ -74,8 +74,7 @@ module Mutant | |
| 74 74 | 
             
                  def merge(other)
         | 
| 75 75 | 
             
                    self.class.new(
         | 
| 76 76 | 
             
                      to_h
         | 
| 77 | 
            -
                        . | 
| 78 | 
            -
                        .to_h
         | 
| 77 | 
            +
                        .to_h { |name, value| [name, value + other.public_send(name)] }
         | 
| 79 78 | 
             
                    )
         | 
| 80 79 | 
             
                  end
         | 
| 81 80 |  | 
| @@ -41,6 +41,16 @@ module Mutant | |
| 41 41 | 
             
                        node.children.fetch(NAME_INDEX).equal?(method_name)
         | 
| 42 42 | 
             
                      end
         | 
| 43 43 |  | 
| 44 | 
            +
                      def visibility
         | 
| 45 | 
            +
                        if scope.private_instance_methods.include?(method_name)
         | 
| 46 | 
            +
                          :private
         | 
| 47 | 
            +
                        elsif scope.protected_instance_methods.include?(method_name)
         | 
| 48 | 
            +
                          :protected
         | 
| 49 | 
            +
                        else
         | 
| 50 | 
            +
                          :public
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
             | 
| 44 54 | 
             
                      # Evaluator specialized for memoized instance methods
         | 
| 45 55 | 
             
                      class Memoized < self
         | 
| 46 56 | 
             
                        SUBJECT_CLASS = Subject::Method::Instance::Memoized
         | 
| @@ -99,16 +99,40 @@ module Mutant | |
| 99 99 | 
             
                      node = matched_node_path.last || return
         | 
| 100 100 |  | 
| 101 101 | 
             
                      self.class::SUBJECT_CLASS.new(
         | 
| 102 | 
            -
                        context: | 
| 103 | 
            -
                        node: | 
| 102 | 
            +
                        context:    context,
         | 
| 103 | 
            +
                        node:       node,
         | 
| 104 | 
            +
                        visibility: visibility
         | 
| 104 105 | 
             
                      )
         | 
| 105 106 | 
             
                    end
         | 
| 106 | 
            -
                    memoize :subject
         | 
| 107 107 |  | 
| 108 108 | 
             
                    def matched_node_path
         | 
| 109 109 | 
             
                      AST.find_last_path(ast, &method(:match?))
         | 
| 110 110 | 
             
                    end
         | 
| 111 111 | 
             
                    memoize :matched_node_path
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    def visibility
         | 
| 114 | 
            +
                      # This can be cleaned up once we are on >ruby-3.0
         | 
| 115 | 
            +
                      # Method#{public,private,protected}? exists there.
         | 
| 116 | 
            +
                      #
         | 
| 117 | 
            +
                      # On Ruby 3.1 this can just be:
         | 
| 118 | 
            +
                      #
         | 
| 119 | 
            +
                      # if target_method.private?
         | 
| 120 | 
            +
                      #   :private
         | 
| 121 | 
            +
                      # elsif target_method.protected?
         | 
| 122 | 
            +
                      #   :protected
         | 
| 123 | 
            +
                      # else
         | 
| 124 | 
            +
                      #   :public
         | 
| 125 | 
            +
                      # end
         | 
| 126 | 
            +
                      #
         | 
| 127 | 
            +
                      # Change to this once 3.0 is EOL.
         | 
| 128 | 
            +
                      if scope.private_methods.include?(method_name)
         | 
| 129 | 
            +
                        :private
         | 
| 130 | 
            +
                      elsif scope.protected_methods.include?(method_name)
         | 
| 131 | 
            +
                        :protected
         | 
| 132 | 
            +
                      else
         | 
| 133 | 
            +
                        :public
         | 
| 134 | 
            +
                      end
         | 
| 135 | 
            +
                    end
         | 
| 112 136 | 
             
                  end # Evaluator
         | 
| 113 137 |  | 
| 114 138 | 
             
                  private_constant(*constants(false))
         | 
    
        data/lib/mutant/mutation.rb
    CHANGED
    
    | @@ -7,7 +7,7 @@ module Mutant | |
| 7 7 | 
             
                include Concord::Public.new(:subject, :node)
         | 
| 8 8 |  | 
| 9 9 | 
             
                CODE_DELIMITER = "\0"
         | 
| 10 | 
            -
                CODE_RANGE     = ( | 
| 10 | 
            +
                CODE_RANGE     = (..4).freeze
         | 
| 11 11 |  | 
| 12 12 | 
             
                # Mutation identification code
         | 
| 13 13 | 
             
                #
         | 
| @@ -69,7 +69,10 @@ module Mutant | |
| 69 69 | 
             
                    kernel:  kernel,
         | 
| 70 70 | 
             
                    source:  monkeypatch,
         | 
| 71 71 | 
             
                    subject: subject
         | 
| 72 | 
            -
                  )
         | 
| 72 | 
            +
                  ).fmap do
         | 
| 73 | 
            +
                    subject.post_insert
         | 
| 74 | 
            +
                    nil
         | 
| 75 | 
            +
                  end
         | 
| 73 76 | 
             
                end
         | 
| 74 77 |  | 
| 75 78 | 
             
                # Rendered mutation diff
         | 
| @@ -6,6 +6,8 @@ module Mutant | |
| 6 6 | 
             
                  # Mutator for arguments node
         | 
| 7 7 | 
             
                  class Arguments < self
         | 
| 8 8 |  | 
| 9 | 
            +
                    ANONYMOUS_BLOCKARG_PRED = ::Parser::AST::Node.new(:blockarg, [nil]).method(:eql?)
         | 
| 10 | 
            +
             | 
| 9 11 | 
             
                    handle(:args)
         | 
| 10 12 |  | 
| 11 13 | 
             
                  private
         | 
| @@ -17,15 +19,34 @@ module Mutant | |
| 17 19 | 
             
                    end
         | 
| 18 20 |  | 
| 19 21 | 
             
                    def emit_argument_presence
         | 
| 20 | 
            -
                      emit_type
         | 
| 22 | 
            +
                      emit_type unless removed_block_arg?(EMPTY_ARRAY) || forward_arg?
         | 
| 21 23 |  | 
| 22 | 
            -
                       | 
| 23 | 
            -
                         | 
| 24 | 
            -
             | 
| 24 | 
            +
                      children.each_with_index do |removed, index|
         | 
| 25 | 
            +
                        new_arguments = children.dup
         | 
| 26 | 
            +
                        new_arguments.delete_at(index)
         | 
| 27 | 
            +
                        unless n_forward_arg?(removed) || removed_block_arg?(new_arguments) || only_mlhs?(new_arguments)
         | 
| 28 | 
            +
                          emit_type(*new_arguments)
         | 
| 25 29 | 
             
                        end
         | 
| 26 30 | 
             
                      end
         | 
| 27 31 | 
             
                    end
         | 
| 28 32 |  | 
| 33 | 
            +
                    def only_mlhs?(new_arguments)
         | 
| 34 | 
            +
                      new_arguments.one? && n_mlhs?(new_arguments.first)
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                    def forward_arg?
         | 
| 38 | 
            +
                      children.last && n_forward_arg?(children.last)
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def removed_block_arg?(new_arguments)
         | 
| 42 | 
            +
                      anonymous_block_arg? && new_arguments.none?(&ANONYMOUS_BLOCKARG_PRED)
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    def anonymous_block_arg?
         | 
| 46 | 
            +
                      children.any?(&ANONYMOUS_BLOCKARG_PRED)
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                    memoize :anonymous_block_arg?
         | 
| 49 | 
            +
             | 
| 29 50 | 
             
                    def emit_argument_mutations
         | 
| 30 51 | 
             
                      children.each_with_index do |child, index|
         | 
| 31 52 | 
             
                        Mutator.mutate(child).each do |mutant|
         | 
| @@ -36,7 +57,7 @@ module Mutant | |
| 36 57 | 
             
                    end
         | 
| 37 58 |  | 
| 38 59 | 
             
                    def invalid_argument_replacement?(mutant, index)
         | 
| 39 | 
            -
                      n_arg?(mutant) && children[ | 
| 60 | 
            +
                      n_arg?(mutant) && children[...index].any?(&method(:n_optarg?))
         | 
| 40 61 | 
             
                    end
         | 
| 41 62 |  | 
| 42 63 | 
             
                    def emit_mlhs_expansion
         | 
| @@ -241,7 +241,9 @@ module Mutant | |
| 241 241 |  | 
| 242 242 | 
             
                      argument = Mutant::Util.one(arguments)
         | 
| 243 243 |  | 
| 244 | 
            -
                       | 
| 244 | 
            +
                      return if n_kwargs?(argument) || n_forwarded_args?(argument)
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                      emit_propagation(argument)
         | 
| 245 247 | 
             
                    end
         | 
| 246 248 |  | 
| 247 249 | 
             
                    def mutate_receiver
         | 
    
        data/lib/mutant/subject.rb
    CHANGED
    
    
    
        data/lib/mutant/transform.rb
    CHANGED
    
    | @@ -351,7 +351,7 @@ module Mutant | |
| 351 351 | 
             
                  def transform_keys(keys, input)
         | 
| 352 352 | 
             
                    success(
         | 
| 353 353 | 
             
                      keys
         | 
| 354 | 
            -
                        . | 
| 354 | 
            +
                        .to_h do |key|
         | 
| 355 355 | 
             
                          [
         | 
| 356 356 | 
             
                            key.value,
         | 
| 357 357 | 
             
                            coerce_key(key, input).from_right do |error|
         | 
| @@ -359,7 +359,6 @@ module Mutant | |
| 359 359 | 
             
                            end
         | 
| 360 360 | 
             
                          ]
         | 
| 361 361 | 
             
                        end
         | 
| 362 | 
            -
                        .to_h
         | 
| 363 362 | 
             
                    )
         | 
| 364 363 | 
             
                  end
         | 
| 365 364 | 
             
                  # rubocop:enable Metrics/MethodLength
         | 
    
        data/lib/mutant/version.rb
    CHANGED
    
    
    
        data/lib/mutant/zombifier.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: mutant
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.11. | 
| 4 | 
            +
              version: 0.11.6
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Markus Schirp
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022- | 
| 11 | 
            +
            date: 2022-04-10 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: diff-lcs
         | 
| @@ -368,7 +368,8 @@ files: | |
| 368 368 | 
             
            homepage: https://github.com/mbj/mutant
         | 
| 369 369 | 
             
            licenses:
         | 
| 370 370 | 
             
            - Nonstandard
         | 
| 371 | 
            -
            metadata: | 
| 371 | 
            +
            metadata:
         | 
| 372 | 
            +
              rubygems_mfa_required: 'true'
         | 
| 372 373 | 
             
            post_install_message:
         | 
| 373 374 | 
             
            rdoc_options: []
         | 
| 374 375 | 
             
            require_paths:
         | 
| @@ -377,7 +378,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 377 378 | 
             
              requirements:
         | 
| 378 379 | 
             
              - - ">="
         | 
| 379 380 | 
             
                - !ruby/object:Gem::Version
         | 
| 380 | 
            -
                  version: '2. | 
| 381 | 
            +
                  version: '2.7'
         | 
| 381 382 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 382 383 | 
             
              requirements:
         | 
| 383 384 | 
             
              - - ">="
         |