mutant 0.10.33 → 0.11.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c20fb3fdc41f7d6e0f8164916206353716c037ec596fccccd06db10c05e810c
4
- data.tar.gz: 276612decdc11bf06de38e704fed0d6dc3b9b0b590d9e2f333be7ae383396ca0
3
+ metadata.gz: 3615060fe7453d95369d3a331f37af2ccaf30227b60ed88fe10cbbd647c1aef1
4
+ data.tar.gz: 26883c9dd809504502b21f95f93853144fd0c80bf4ce09b4709c9c3eb75742fe
5
5
  SHA512:
6
- metadata.gz: 652ac4959565f27514568c25c43a0ab64d3af74f9f9de50712bf6e6e825dcf44d27e55e40ff76f0e7c91e27c4199c4f67a0d2205f2268eefae5acc338e2aecb5
7
- data.tar.gz: a7e9b023ffefb0d3da5a13d7ec83fbb6696a10efe0f8840b867e8f6e788a55e7d2eabd077173957a697e9f0689ce109fec5d8668078946e317f7c9c4b7216614
6
+ metadata.gz: e99c8649c373b2f001c9e03440947ab456c1b776c0d8841316a9edcc4105ce22229b5227e72f6b1273f11879ca013b7df909286c42b3f9b8fc186827cda47938
7
+ data.tar.gz: 3a699d84bacfc16d70912534b2e68a8645d4f737bc977e0495c98b84390328f7912379bf623c0ca6a68df8884faf766e256fb3a983c0b4ea944e23c09ba5ae98
@@ -71,6 +71,10 @@ module Mutant
71
71
 
72
72
  hooks.run(:env_infection_pre, env)
73
73
 
74
+ config.environment_variables.each do |key, value|
75
+ world.environment_variables[key] = value
76
+ end
77
+
74
78
  config.includes.each(&world.load_path.public_method(:<<))
75
79
  config.requires.each(&world.kernel.public_method(:require))
76
80
 
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ module CLI
5
+ class Command
6
+ class Environment
7
+ class IRB < self
8
+ NAME = 'irb'
9
+ SHORT_DESCRIPTION = 'Run irb with mutant environment loaded'
10
+ SUBCOMMANDS = EMPTY_ARRAY
11
+
12
+ private
13
+
14
+ def action
15
+ bootstrap.fmap { TOPLEVEL_BINDING.irb }
16
+ end
17
+ end # IRB
18
+ end # Environment
19
+ end # Command
20
+ end # CLI
21
+ end # Mutant
@@ -7,7 +7,7 @@ module Mutant
7
7
  class Run < self
8
8
  NAME = 'run'
9
9
  SHORT_DESCRIPTION = 'Run code analysis'
10
- SLEEP = 40
10
+ SLEEP = 60
11
11
  SUBCOMMANDS = EMPTY_ARRAY
12
12
 
13
13
  UNLICENSED = <<~MESSAGE.lines.freeze
@@ -16,6 +16,20 @@ module Mutant
16
16
  See https://github.com/mbj/mutant#licensing
17
17
  MESSAGE
18
18
 
19
+ NO_TESTS_MESSAGE = <<~'MESSAGE'
20
+ ===============
21
+ Mutant found no tests. Mutation testing cannot be started.
22
+
23
+ This can have various reasons:
24
+
25
+ * You did not setup an integration, see:
26
+ https://github.com/mbj/mutant/blob/main/docs/configuration.md#integration
27
+ * You set environment variables like RSPEC_OPTS that filter out all tests.
28
+ * You set configuration optiosn like `config.filter_run :focus` which do
29
+ make rspec to not report any test.
30
+ ===============
31
+ MESSAGE
32
+
19
33
  # Test if command needs to be executed in zombie environment
20
34
  #
21
35
  # @return [Bool]
@@ -28,10 +42,19 @@ module Mutant
28
42
  def action
29
43
  soft_fail(License.call(world))
30
44
  .bind { bootstrap }
45
+ .bind(&method(:validate_tests))
31
46
  .bind(&Runner.public_method(:call))
32
47
  .bind(&method(:from_result))
33
48
  end
34
49
 
50
+ def validate_tests(environment)
51
+ if environment.integration.all_tests.length.zero?
52
+ Either::Left.new(NO_TESTS_MESSAGE)
53
+ else
54
+ Either::Right.new(environment)
55
+ end
56
+ end
57
+
35
58
  def from_result(result)
36
59
  if result.success?
37
60
  Either::Right.new(nil)
@@ -62,6 +62,7 @@ module Mutant
62
62
  set(matcher: @config.matcher.add(attribute, value))
63
63
  end
64
64
 
65
+ # rubocop:disable Metrics/MethodLength
65
66
  def add_environment_options(parser)
66
67
  parser.separator('Environment:')
67
68
  parser.on('--zombie', 'Run mutant zombified') do
@@ -73,7 +74,14 @@ module Mutant
73
74
  parser.on('-r', '--require NAME', 'Require file with NAME') do |name|
74
75
  add(:requires, name)
75
76
  end
77
+ parser.on('--env KEY=VALUE', 'Set environment variable') do |value|
78
+ match = ENV_VARIABLE_KEY_VALUE_REGEXP.match(value) || fail("Invalid env variable: #{value.inspect}")
79
+ set(
80
+ environment_variables: @config.environment_variables.merge(match[:key] => match[:value])
81
+ )
82
+ end
76
83
  end
84
+ # rubocop:enable Metrics/MethodLength
77
85
 
78
86
  def add_integration_options(parser)
79
87
  parser.separator('Integration:')
@@ -4,7 +4,7 @@ module Mutant
4
4
  module CLI
5
5
  class Command
6
6
  class Environment < self
7
- SUBCOMMANDS = [Environment::Subject, Environment::Show, Environment::Test].freeze
7
+ SUBCOMMANDS = [Environment::Subject, Environment::Show, Environment::IRB, Environment::Test].freeze
8
8
  end # Environment
9
9
 
10
10
  class Root < self
@@ -130,6 +130,8 @@ module Mutant
130
130
  end
131
131
 
132
132
  def add_global_options(parser)
133
+ parser.separator("mutant version: #{VERSION}")
134
+ parser.separator(nil)
133
135
  parser.separator('Global Options:')
134
136
  parser.separator(nil)
135
137
 
data/lib/mutant/config.rb CHANGED
@@ -5,9 +5,12 @@ module Mutant
5
5
  #
6
6
  # Does not reference any "external" volatile state. The configuration applied
7
7
  # to current environment is being represented by the Mutant::Env object.
8
+ #
9
+ # rubocop:disable Metrics/ClassLength
8
10
  class Config
9
11
  include Adamantium, Anima.new(
10
12
  :coverage_criteria,
13
+ :environment_variables,
11
14
  :expression_parser,
12
15
  :fail_fast,
13
16
  :hooks,
@@ -48,16 +51,17 @@ module Mutant
48
51
  # rubocop:disable Metrics/MethodLength
49
52
  def merge(other)
50
53
  other.with(
51
- coverage_criteria: coverage_criteria.merge(other.coverage_criteria),
52
- fail_fast: fail_fast || other.fail_fast,
53
- hooks: hooks + other.hooks,
54
- includes: includes + other.includes,
55
- integration: other.integration || integration,
56
- jobs: other.jobs || jobs,
57
- matcher: matcher.merge(other.matcher),
58
- mutation_timeout: other.mutation_timeout || mutation_timeout,
59
- requires: requires + other.requires,
60
- zombie: zombie || other.zombie
54
+ coverage_criteria: coverage_criteria.merge(other.coverage_criteria),
55
+ environment_variables: environment_variables.merge(other.environment_variables),
56
+ fail_fast: fail_fast || other.fail_fast,
57
+ hooks: hooks + other.hooks,
58
+ includes: includes + other.includes,
59
+ integration: other.integration || integration,
60
+ jobs: other.jobs || jobs,
61
+ matcher: matcher.merge(other.matcher),
62
+ mutation_timeout: other.mutation_timeout || mutation_timeout,
63
+ requires: requires + other.requires,
64
+ zombie: zombie || other.zombie
61
65
  )
62
66
  end
63
67
  # rubocop:enable Metrics/AbcSize
@@ -117,6 +121,24 @@ module Mutant
117
121
  )
118
122
  )
119
123
 
124
+ # Parse a hash of environment variables
125
+ #
126
+ # @param [Hash<Object,Object>]
127
+ #
128
+ # @return [Either<String,Hash<String,String>]
129
+ #
130
+ def self.parse_environment_variables(hash)
131
+ invalid = hash.keys.reject { |key| key.instance_of?(String) }
132
+ return Either::Left.new("Non string keys: #{invalid}") if invalid.any?
133
+
134
+ invalid = hash.keys.grep_v(ENV_VARIABLE_KEY_REGEXP)
135
+ return Either::Left.new("Invalid keys: #{invalid}") if invalid.any?
136
+
137
+ invalid = hash.values.reject { |value| value.instance_of?(String) }
138
+ return Either::Left.new("Non string values: #{invalid}") if invalid.any?
139
+
140
+ Either::Right.new(hash)
141
+ end
120
142
  TRANSFORM = Transform::Sequence.new(
121
143
  [
122
144
  Transform::Exception.new(SystemCallError, :read.to_proc),
@@ -124,14 +146,23 @@ module Mutant
124
146
  Transform::Hash.new(
125
147
  optional: [
126
148
  Transform::Hash::Key.new('coverage_criteria', ->(value) { CoverageCriteria::TRANSFORM.call(value) }),
127
- Transform::Hash::Key.new('fail_fast', Transform::BOOLEAN),
128
- Transform::Hash::Key.new('hooks', PATHNAME_ARRAY),
129
- Transform::Hash::Key.new('includes', Transform::STRING_ARRAY),
130
- Transform::Hash::Key.new('integration', Transform::STRING),
131
- Transform::Hash::Key.new('jobs', Transform::INTEGER),
132
- Transform::Hash::Key.new('matcher', Matcher::Config::LOADER),
133
- Transform::Hash::Key.new('mutation_timeout', Transform::FLOAT),
134
- Transform::Hash::Key.new('requires', Transform::STRING_ARRAY)
149
+ Transform::Hash::Key.new(
150
+ 'environment_variables',
151
+ Transform::Sequence.new(
152
+ [
153
+ Transform::Primitive.new(Hash),
154
+ Transform::Block.capture(:environment_variables, &method(:parse_environment_variables))
155
+ ]
156
+ )
157
+ ),
158
+ Transform::Hash::Key.new('fail_fast', Transform::BOOLEAN),
159
+ Transform::Hash::Key.new('hooks', PATHNAME_ARRAY),
160
+ Transform::Hash::Key.new('includes', Transform::STRING_ARRAY),
161
+ Transform::Hash::Key.new('integration', Transform::STRING),
162
+ Transform::Hash::Key.new('jobs', Transform::INTEGER),
163
+ Transform::Hash::Key.new('matcher', Matcher::Config::LOADER),
164
+ Transform::Hash::Key.new('mutation_timeout', Transform::FLOAT),
165
+ Transform::Hash::Key.new('requires', Transform::STRING_ARRAY)
135
166
  ],
136
167
  required: []
137
168
  ),
@@ -141,4 +172,5 @@ module Mutant
141
172
 
142
173
  private_constant(:TRANSFORM)
143
174
  end # Config
175
+ # rubocop:enable Metrics/ClassLength
144
176
  end # Mutant
@@ -82,7 +82,17 @@ module Mutant
82
82
  end
83
83
 
84
84
  def source_location
85
- target_method.source_location
85
+ signature = sorbet_signature
86
+
87
+ if signature
88
+ signature.method.source_location
89
+ else
90
+ target_method.source_location
91
+ end
92
+ end
93
+
94
+ def sorbet_signature
95
+ T::Private::Methods.signature_for_method(target_method)
86
96
  end
87
97
 
88
98
  def subject
@@ -21,7 +21,7 @@ module Mutant
21
21
  # @return [Enumerable<Subject>]
22
22
  def call(env)
23
23
  Chain.new(
24
- methods.map { |method| matcher.new(scope, method) }
24
+ methods(env).map { |method| matcher.new(scope, method) }
25
25
  ).call(env)
26
26
  end
27
27
 
@@ -31,17 +31,16 @@ module Mutant
31
31
  self.class::MATCHER
32
32
  end
33
33
 
34
- def methods
34
+ def methods(env)
35
35
  candidate_names.each_with_object([]) do |name, methods|
36
- method = access(name)
37
- methods << method if method.owner.equal?(candidate_scope)
36
+ method = access(env, name)
37
+ methods << method if method&.owner.equal?(candidate_scope)
38
38
  end
39
39
  end
40
- memoize :methods
41
40
 
42
41
  def candidate_names
43
42
  CANDIDATE_NAMES
44
- .map(&candidate_scope.public_method(:public_send))
43
+ .map { |name| candidate_scope.public_send(name, false) }
45
44
  .reduce(:+)
46
45
  .sort
47
46
  end
@@ -55,7 +54,7 @@ module Mutant
55
54
 
56
55
  private
57
56
 
58
- def access(method_name)
57
+ def access(_env, method_name)
59
58
  scope.method(method_name)
60
59
  end
61
60
 
@@ -71,7 +70,7 @@ module Mutant
71
70
 
72
71
  private
73
72
 
74
- def access(method_name)
73
+ def access(_env, method_name)
75
74
  scope.method(method_name)
76
75
  end
77
76
 
@@ -84,11 +83,33 @@ module Mutant
84
83
  class Instance < self
85
84
  MATCHER = Matcher::Method::Instance
86
85
 
86
+ MESSAGE = <<~'MESSAGE'
87
+ Caught an exception while accessing a method with
88
+ #instance_method that is part of #{public,privat,protected}_instance_methods.
89
+
90
+ This is a bug in your ruby implementation its stdlib, libaries our your code.
91
+
92
+ Mutant will ignore this method:
93
+
94
+ Object: %<scope>s
95
+ Method: %<method_name>s
96
+ Exception: %<exception>s
97
+
98
+ See: https://github.com/mbj/mutant/issues/1273
99
+ MESSAGE
100
+
87
101
  private
88
102
 
89
- def access(method_name)
103
+ # rubocop:disable Lint/RescueException
104
+ def access(env, method_name)
90
105
  scope.instance_method(method_name)
106
+ rescue Exception => exception
107
+ env.warn(
108
+ MESSAGE % { scope: scope, method_name: method_name, exception: exception }
109
+ )
110
+ nil
91
111
  end
112
+ # rubocop:enable Lint/RescueException
92
113
 
93
114
  def candidate_scope
94
115
  scope
@@ -21,8 +21,11 @@ module Mutant
21
21
  emit_singletons
22
22
  emit_promotions
23
23
  emit_operator_mutations
24
- emit_left_negation
25
- emit_left_mutations
24
+
25
+ emit_left_mutations do |mutation|
26
+ !(n_irange?(mutation) || n_erange?(mutation)) || !mutation.children.fetch(1).nil?
27
+ end
28
+
26
29
  emit_right_mutations
27
30
  end
28
31
 
@@ -35,10 +38,6 @@ module Mutant
35
38
  emit(right)
36
39
  end
37
40
 
38
- def emit_left_negation
39
- emit(s(node.type, n_not(left), right))
40
- end
41
-
42
41
  end # Binary
43
42
  end # Node
44
43
  end # Mutator
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ class Mutator
5
+ class Node
6
+ class Numblock < self
7
+
8
+ handle(:numblock)
9
+
10
+ children :receiver, :count, :block
11
+
12
+ private
13
+
14
+ def dispatch
15
+ emit_nil
16
+ emit_receiver_mutations(&method(:n_send?))
17
+ end
18
+ end # Numblock
19
+ end # Node
20
+ end # Mutator
21
+ end # Mutant
@@ -8,7 +8,7 @@ module Mutant
8
8
  class Mutation < self
9
9
  NO_DIFF_MESSAGE = <<~'MESSAGE'
10
10
  --- Internal failure ---
11
- BUG: A generted mutation did not result in exactly one diff hunk!
11
+ BUG: A generated mutation did not result in exactly one diff hunk!
12
12
  This is an invariant violation by the mutation generation engine.
13
13
  Please report a reproduction to https://github.com/mbj/mutant
14
14
  Original unparsed source:
@@ -27,7 +27,7 @@ module Mutant
27
27
 
28
28
  NO_DIFF_MESSAGE = <<~'MESSAGE'
29
29
  --- Internal failure ---
30
- BUG: A generted mutation did not result in exactly one diff hunk!
30
+ BUG: A generated mutation did not result in exactly one diff hunk!
31
31
  This is an invariant violation by the mutation generation engine.
32
32
  Please report a reproduction to https://github.com/mbj/mutant
33
33
  Original unparsed source:
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.10.33'
5
+ VERSION = '0.11.1'
6
6
  end # Mutant
data/lib/mutant/world.rb CHANGED
@@ -5,6 +5,7 @@ module Mutant
5
5
  class World
6
6
  include Adamantium, Anima.new(
7
7
  :condition_variable,
8
+ :environment_variables,
8
9
  :gem,
9
10
  :gem_method,
10
11
  :io,
data/lib/mutant.rb CHANGED
@@ -4,6 +4,7 @@ require 'diff/lcs'
4
4
  require 'diff/lcs/hunk'
5
5
  require 'digest/sha1'
6
6
  require 'etc'
7
+ require 'irb'
7
8
  require 'json'
8
9
  require 'open3'
9
10
  require 'optparse'
@@ -13,6 +14,7 @@ require 'pathname'
13
14
  require 'regexp_parser'
14
15
  require 'set'
15
16
  require 'singleton'
17
+ require 'sorbet-runtime'
16
18
  require 'stringio'
17
19
  require 'unparser'
18
20
  require 'yaml'
@@ -36,6 +38,11 @@ module Mutant
36
38
  EMPTY_ARRAY = [].freeze
37
39
  EMPTY_HASH = {}.freeze
38
40
  SCOPE_OPERATOR = '::'
41
+
42
+ env_key = /[a-zA-Z_\d]+/
43
+
44
+ ENV_VARIABLE_KEY_VALUE_REGEXP = /\A(?<key>#{env_key}+)=(?<value>.*)\z/.freeze
45
+ ENV_VARIABLE_KEY_REGEXP = /\A#{env_key}\z/.freeze
39
46
  end # Mutant
40
47
 
41
48
  require 'mutant/procto'
@@ -152,6 +159,7 @@ require 'mutant/mutator/node/match_current_line'
152
159
  require 'mutant/mutator/node/index'
153
160
  require 'mutant/mutator/node/procarg_zero'
154
161
  require 'mutant/mutator/node/kwargs'
162
+ require 'mutant/mutator/node/numblock'
155
163
  require 'mutant/loader'
156
164
  require 'mutant/context'
157
165
  require 'mutant/scope'
@@ -193,6 +201,7 @@ require 'mutant/cli'
193
201
  require 'mutant/cli/command'
194
202
  require 'mutant/cli/command/subscription'
195
203
  require 'mutant/cli/command/environment'
204
+ require 'mutant/cli/command/environment/irb'
196
205
  require 'mutant/cli/command/environment/run'
197
206
  require 'mutant/cli/command/environment/show'
198
207
  require 'mutant/cli/command/environment/subject'
@@ -230,46 +239,48 @@ require 'mutant/license/subscription/commercial'
230
239
 
231
240
  module Mutant
232
241
  WORLD = World.new(
233
- condition_variable: ConditionVariable,
234
- gem: Gem,
235
- gem_method: method(:gem),
236
- io: IO,
237
- json: JSON,
238
- kernel: Kernel,
239
- load_path: $LOAD_PATH,
240
- marshal: Marshal,
241
- mutex: Mutex,
242
- object_space: ObjectSpace,
243
- open3: Open3,
244
- pathname: Pathname,
245
- process: Process,
246
- stderr: $stderr,
247
- stdout: $stdout,
248
- thread: Thread,
249
- timer: Timer.new(Process)
242
+ condition_variable: ConditionVariable,
243
+ environment_variables: ENV,
244
+ gem: Gem,
245
+ gem_method: method(:gem),
246
+ io: IO,
247
+ json: JSON,
248
+ kernel: Kernel,
249
+ load_path: $LOAD_PATH,
250
+ marshal: Marshal,
251
+ mutex: Mutex,
252
+ object_space: ObjectSpace,
253
+ open3: Open3,
254
+ pathname: Pathname,
255
+ process: Process,
256
+ stderr: $stderr,
257
+ stdout: $stdout,
258
+ thread: Thread,
259
+ timer: Timer.new(Process)
250
260
  )
251
261
 
252
262
  # Reopen class to initialize constant to avoid dep circle
253
263
  class Config
254
264
  DEFAULT = new(
255
- coverage_criteria: Config::CoverageCriteria::EMPTY,
256
- expression_parser: Expression::Parser.new([
265
+ coverage_criteria: Config::CoverageCriteria::EMPTY,
266
+ expression_parser: Expression::Parser.new([
257
267
  Expression::Method,
258
268
  Expression::Methods,
259
269
  Expression::Namespace::Exact,
260
270
  Expression::Namespace::Recursive
261
271
  ]),
262
- fail_fast: false,
263
- hooks: EMPTY_ARRAY,
264
- includes: EMPTY_ARRAY,
265
- integration: nil,
266
- isolation: Mutant::Isolation::Fork.new(WORLD),
267
- jobs: nil,
268
- matcher: Matcher::Config::DEFAULT,
269
- mutation_timeout: nil,
270
- reporter: Reporter::CLI.build(WORLD.stdout),
271
- requires: EMPTY_ARRAY,
272
- zombie: false
272
+ fail_fast: false,
273
+ environment_variables: EMPTY_HASH,
274
+ hooks: EMPTY_ARRAY,
275
+ includes: EMPTY_ARRAY,
276
+ integration: nil,
277
+ isolation: Mutant::Isolation::Fork.new(WORLD),
278
+ jobs: nil,
279
+ matcher: Matcher::Config::DEFAULT,
280
+ mutation_timeout: nil,
281
+ reporter: Reporter::CLI.build(WORLD.stdout),
282
+ requires: EMPTY_ARRAY,
283
+ zombie: false
273
284
  )
274
285
  end # Config
275
286
 
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.10.33
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-25 00:00:00.000000000 Z
11
+ date: 2021-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs
@@ -58,6 +58,20 @@ dependencies:
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
60
  version: 2.0.3
61
+ - !ruby/object:Gem::Dependency
62
+ name: sorbet-runtime
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.5.0
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: 0.5.0
61
75
  - !ruby/object:Gem::Dependency
62
76
  name: unparser
63
77
  requirement: !ruby/object:Gem::Requirement
@@ -180,6 +194,7 @@ files:
180
194
  - lib/mutant/cli.rb
181
195
  - lib/mutant/cli/command.rb
182
196
  - lib/mutant/cli/command/environment.rb
197
+ - lib/mutant/cli/command/environment/irb.rb
183
198
  - lib/mutant/cli/command/environment/run.rb
184
199
  - lib/mutant/cli/command/environment/show.rb
185
200
  - lib/mutant/cli/command/environment/subject.rb
@@ -269,6 +284,7 @@ files:
269
284
  - lib/mutant/mutator/node/next.rb
270
285
  - lib/mutant/mutator/node/noop.rb
271
286
  - lib/mutant/mutator/node/nthref.rb
287
+ - lib/mutant/mutator/node/numblock.rb
272
288
  - lib/mutant/mutator/node/op_asgn.rb
273
289
  - lib/mutant/mutator/node/or_asgn.rb
274
290
  - lib/mutant/mutator/node/procarg_zero.rb
@@ -359,7 +375,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
359
375
  requirements:
360
376
  - - ">="
361
377
  - !ruby/object:Gem::Version
362
- version: '2.5'
378
+ version: '2.6'
363
379
  required_rubygems_version: !ruby/object:Gem::Requirement
364
380
  requirements:
365
381
  - - ">="