mutant 0.10.33 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
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
  - - ">="