mutant 0.8.24 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -3
- data/Changelog.md +14 -654
- data/Gemfile +13 -0
- data/Gemfile.lock +59 -64
- data/LICENSE +271 -20
- data/README.md +73 -140
- data/Rakefile +0 -21
- data/bin/mutant +7 -2
- data/config/reek.yml +2 -1
- data/config/rubocop.yml +5 -9
- data/docs/incremental.md +76 -0
- data/docs/known-problems.md +0 -14
- data/docs/mutant-minitest.md +1 -1
- data/docs/mutant-rspec.md +2 -24
- data/lib/mutant.rb +45 -53
- data/lib/mutant/ast/nodes.rb +0 -2
- data/lib/mutant/ast/types.rb +1 -117
- data/lib/mutant/base.rb +192 -0
- data/lib/mutant/bootstrap.rb +145 -0
- data/lib/mutant/cli.rb +68 -54
- data/lib/mutant/config.rb +119 -6
- data/lib/mutant/env.rb +94 -8
- data/lib/mutant/expression.rb +6 -1
- data/lib/mutant/expression/parser.rb +9 -31
- data/lib/mutant/integration.rb +64 -36
- data/lib/mutant/isolation.rb +16 -1
- data/lib/mutant/isolation/fork.rb +105 -40
- data/lib/mutant/license.rb +34 -0
- data/lib/mutant/license/subscription.rb +47 -0
- data/lib/mutant/license/subscription/commercial.rb +57 -0
- data/lib/mutant/license/subscription/opensource.rb +77 -0
- data/lib/mutant/loader.rb +27 -4
- data/lib/mutant/matcher.rb +48 -1
- data/lib/mutant/matcher/chain.rb +1 -1
- data/lib/mutant/matcher/config.rb +0 -2
- data/lib/mutant/matcher/filter.rb +1 -1
- data/lib/mutant/matcher/method.rb +11 -7
- data/lib/mutant/matcher/methods.rb +1 -1
- data/lib/mutant/matcher/namespace.rb +1 -1
- data/lib/mutant/matcher/null.rb +1 -1
- data/lib/mutant/matcher/scope.rb +1 -1
- data/lib/mutant/meta/example/dsl.rb +0 -8
- data/lib/mutant/mutation.rb +1 -2
- data/lib/mutant/mutator/node.rb +2 -9
- data/lib/mutant/mutator/node/arguments.rb +1 -1
- data/lib/mutant/mutator/node/class.rb +0 -8
- data/lib/mutant/mutator/node/define.rb +0 -12
- data/lib/mutant/mutator/node/generic.rb +30 -44
- data/lib/mutant/mutator/node/index.rb +4 -4
- data/lib/mutant/mutator/node/literal/regex.rb +0 -39
- data/lib/mutant/mutator/node/send.rb +13 -12
- data/lib/mutant/parallel.rb +61 -40
- data/lib/mutant/parallel/driver.rb +59 -0
- data/lib/mutant/parallel/source.rb +6 -2
- data/lib/mutant/parallel/worker.rb +63 -45
- data/lib/mutant/range.rb +15 -0
- data/lib/mutant/reporter/cli.rb +5 -11
- data/lib/mutant/reporter/cli/format.rb +3 -46
- data/lib/mutant/reporter/cli/printer/config.rb +5 -6
- data/lib/mutant/reporter/cli/printer/env.rb +40 -0
- data/lib/mutant/reporter/cli/printer/env_progress.rb +13 -17
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +17 -3
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +2 -3
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +19 -10
- data/lib/mutant/repository.rb +0 -65
- data/lib/mutant/repository/diff.rb +104 -0
- data/lib/mutant/repository/diff/ranges.rb +52 -0
- data/lib/mutant/result.rb +16 -7
- data/lib/mutant/runner.rb +38 -47
- data/lib/mutant/runner/sink.rb +1 -1
- data/lib/mutant/selector/null.rb +19 -0
- data/lib/mutant/subject.rb +3 -1
- data/lib/mutant/subject/method/instance.rb +3 -1
- data/lib/mutant/transform.rb +511 -0
- data/lib/mutant/variable.rb +282 -0
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warnings.rb +113 -0
- data/meta/case.rb +1 -0
- data/meta/class.rb +0 -9
- data/meta/def.rb +1 -26
- data/meta/regexp.rb +10 -20
- data/meta/send.rb +14 -46
- data/mutant-minitest.gemspec +1 -1
- data/mutant-rspec.gemspec +2 -2
- data/mutant.gemspec +15 -16
- data/mutant.yml +6 -0
- data/spec/integration/mutant/isolation/fork_spec.rb +22 -5
- data/spec/integration/mutant/minitest_spec.rb +3 -2
- data/spec/integration/mutant/rspec_spec.rb +4 -3
- data/spec/integrations.yml +16 -13
- data/spec/shared/base_behavior.rb +45 -0
- data/spec/shared/framework_integration_behavior.rb +43 -14
- data/spec/spec_helper.rb +21 -17
- data/spec/support/corpus.rb +56 -95
- data/spec/support/shared_context.rb +37 -14
- data/spec/support/xspec.rb +7 -3
- data/spec/unit/mutant/bootstrap_spec.rb +216 -0
- data/spec/unit/mutant/cli_spec.rb +173 -117
- data/spec/unit/mutant/config_spec.rb +126 -0
- data/spec/unit/mutant/either_spec.rb +247 -0
- data/spec/unit/mutant/env_spec.rb +162 -40
- data/spec/unit/mutant/expression/method_spec.rb +16 -0
- data/spec/unit/mutant/expression/parser_spec.rb +29 -33
- data/spec/unit/mutant/expression_spec.rb +5 -7
- data/spec/unit/mutant/integration_spec.rb +100 -9
- data/spec/unit/mutant/isolation/fork_spec.rb +125 -67
- data/spec/unit/mutant/isolation/result_spec.rb +33 -1
- data/spec/unit/mutant/license_spec.rb +257 -0
- data/spec/unit/mutant/loader_spec.rb +50 -11
- data/spec/unit/mutant/matcher/compiler_spec.rb +0 -78
- data/spec/unit/mutant/matcher/method/instance_spec.rb +55 -11
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +12 -2
- data/spec/unit/mutant/matcher_spec.rb +102 -0
- data/spec/unit/mutant/maybe_spec.rb +60 -0
- data/spec/unit/mutant/meta/example/dsl_spec.rb +1 -17
- data/spec/unit/mutant/mutation_spec.rb +13 -6
- data/spec/unit/mutant/parallel/driver_spec.rb +112 -14
- data/spec/unit/mutant/parallel/source/array_spec.rb +25 -17
- data/spec/unit/mutant/parallel/worker_spec.rb +182 -44
- data/spec/unit/mutant/parallel_spec.rb +105 -8
- data/spec/unit/mutant/range_spec.rb +141 -0
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +7 -21
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +15 -6
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +10 -2
- data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +12 -4
- data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +31 -2
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +4 -4
- data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +5 -0
- data/spec/unit/mutant/reporter/cli_spec.rb +46 -123
- data/spec/unit/mutant/repository/diff/ranges_spec.rb +180 -0
- data/spec/unit/mutant/repository/diff_spec.rb +84 -71
- data/spec/unit/mutant/require_highjack_spec.rb +1 -1
- data/spec/unit/mutant/result/env_spec.rb +39 -9
- data/spec/unit/mutant/result/test_spec.rb +14 -0
- data/spec/unit/mutant/runner_spec.rb +88 -41
- data/spec/unit/mutant/selector/expression_spec.rb +11 -10
- data/spec/unit/mutant/selector/null_spec.rb +17 -0
- data/spec/unit/mutant/subject/method/instance_spec.rb +44 -5
- data/spec/unit/mutant/subject/method/singleton_spec.rb +9 -2
- data/spec/unit/mutant/subject_spec.rb +9 -1
- data/spec/unit/mutant/transform/array_spec.rb +92 -0
- data/spec/unit/mutant/transform/bool_spec.rb +63 -0
- data/spec/unit/mutant/transform/error_spec.rb +132 -0
- data/spec/unit/mutant/transform/exception_spec.rb +44 -0
- data/spec/unit/mutant/transform/hash_spec.rb +236 -0
- data/spec/unit/mutant/transform/index_spec.rb +92 -0
- data/spec/unit/mutant/transform/named_spec.rb +49 -0
- data/spec/unit/mutant/transform/primitive_spec.rb +56 -0
- data/spec/unit/mutant/transform/sequence_spec.rb +98 -0
- data/spec/unit/mutant/variable_spec.rb +618 -0
- data/spec/unit/mutant/warnings_spec.rb +89 -0
- data/spec/unit/mutant/world_spec.rb +63 -0
- data/test_app/Gemfile.minitest +0 -2
- metadata +79 -113
- data/.gitattributes +0 -1
- data/.ruby-gemset +0 -1
- data/config/triage.yml +0 -2
- data/lib/mutant/actor.rb +0 -57
- data/lib/mutant/actor/env.rb +0 -31
- data/lib/mutant/actor/mailbox.rb +0 -34
- data/lib/mutant/actor/receiver.rb +0 -42
- data/lib/mutant/actor/sender.rb +0 -26
- data/lib/mutant/ast/meta/restarg.rb +0 -19
- data/lib/mutant/ast/regexp.rb +0 -42
- data/lib/mutant/ast/regexp/transformer.rb +0 -187
- data/lib/mutant/ast/regexp/transformer/direct.rb +0 -123
- data/lib/mutant/ast/regexp/transformer/named_group.rb +0 -59
- data/lib/mutant/ast/regexp/transformer/options_group.rb +0 -83
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +0 -114
- data/lib/mutant/ast/regexp/transformer/recursive.rb +0 -58
- data/lib/mutant/ast/regexp/transformer/root.rb +0 -31
- data/lib/mutant/ast/regexp/transformer/text.rb +0 -60
- data/lib/mutant/env/bootstrap.rb +0 -160
- data/lib/mutant/matcher/compiler.rb +0 -60
- data/lib/mutant/mutator/node/regexp.rb +0 -35
- data/lib/mutant/mutator/node/regexp/alternation_meta.rb +0 -23
- data/lib/mutant/mutator/node/regexp/capture_group.rb +0 -28
- data/lib/mutant/mutator/node/regexp/character_type.rb +0 -32
- data/lib/mutant/mutator/node/regexp/end_of_line_anchor.rb +0 -23
- data/lib/mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb +0 -23
- data/lib/mutant/mutator/node/regexp/greedy_zero_or_more.rb +0 -27
- data/lib/mutant/parallel/master.rb +0 -181
- data/lib/mutant/reporter/cli/printer/status.rb +0 -53
- data/lib/mutant/reporter/cli/tput.rb +0 -46
- data/lib/mutant/warning_filter.rb +0 -61
- data/meta/regexp/character_types.rb +0 -23
- data/meta/regexp/regexp_alternation_meta.rb +0 -13
- data/meta/regexp/regexp_bol_anchor.rb +0 -10
- data/meta/regexp/regexp_bos_anchor.rb +0 -18
- data/meta/regexp/regexp_capture_group.rb +0 -19
- data/meta/regexp/regexp_eol_anchor.rb +0 -10
- data/meta/regexp/regexp_eos_anchor.rb +0 -8
- data/meta/regexp/regexp_eos_ob_eol_anchor.rb +0 -10
- data/meta/regexp/regexp_greedy_zero_or_more.rb +0 -12
- data/meta/regexp/regexp_root_expression.rb +0 -10
- data/meta/restarg.rb +0 -10
- data/spec/support/fake_actor.rb +0 -111
- data/spec/support/warning.rb +0 -66
- data/spec/unit/mutant/actor/binding_spec.rb +0 -34
- data/spec/unit/mutant/actor/env_spec.rb +0 -31
- data/spec/unit/mutant/actor/mailbox_spec.rb +0 -28
- data/spec/unit/mutant/actor/message_spec.rb +0 -25
- data/spec/unit/mutant/actor/receiver_spec.rb +0 -58
- data/spec/unit/mutant/actor/sender_spec.rb +0 -24
- data/spec/unit/mutant/ast/regexp/parse_spec.rb +0 -19
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table/table_spec.rb +0 -21
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table_spec.rb +0 -35
- data/spec/unit/mutant/ast/regexp/transformer_spec.rb +0 -21
- data/spec/unit/mutant/ast/regexp_spec.rb +0 -704
- data/spec/unit/mutant/env/bootstrap_spec.rb +0 -188
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +0 -26
- data/spec/unit/mutant/parallel/master_spec.rb +0 -338
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +0 -121
- data/spec/unit/mutant/reporter/cli/tput_spec.rb +0 -50
- data/spec/unit/mutant/warning_filter_spec.rb +0 -106
- data/spec/unit/mutant_spec.rb +0 -17
- data/test_app/Gemfile.rspec3.7 +0 -7
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module License
|
5
|
+
def self.apply(world)
|
6
|
+
soft_fail(world, license_result(world))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.license_result(world)
|
10
|
+
Subscription.from_json(world.json.load(license_path(world))).apply(world)
|
11
|
+
end
|
12
|
+
private_class_method :license_result
|
13
|
+
|
14
|
+
def self.soft_fail(world, license_result)
|
15
|
+
license_result.lmap do |message|
|
16
|
+
stderr = world.stderr
|
17
|
+
stderr.puts(message)
|
18
|
+
stderr.puts('Soft fail, continuing in 10 seconds')
|
19
|
+
world.kernel.sleep(10)
|
20
|
+
end
|
21
|
+
|
22
|
+
Either::Right.new(true)
|
23
|
+
end
|
24
|
+
private_class_method :soft_fail
|
25
|
+
|
26
|
+
def self.license_path(world)
|
27
|
+
world
|
28
|
+
.pathname
|
29
|
+
.new(world.gem.loaded_specs.fetch('mutant-license').full_gem_path)
|
30
|
+
.join('license.json')
|
31
|
+
end
|
32
|
+
private_class_method :license_path
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module License
|
5
|
+
class Subscription
|
6
|
+
|
7
|
+
MESSAGE_FORMAT = <<~'MESSAGE'
|
8
|
+
Can not validate %<subscription_name>s license.
|
9
|
+
Licensed:
|
10
|
+
%<expected>s
|
11
|
+
Present:
|
12
|
+
%<actual>s
|
13
|
+
MESSAGE
|
14
|
+
|
15
|
+
def self.from_json(value)
|
16
|
+
{
|
17
|
+
'com' => Commercial,
|
18
|
+
'oss' => Opensource
|
19
|
+
}.fetch(value.fetch('type')).from_json(value.fetch('contents'))
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def failure(expected, actual)
|
25
|
+
Either::Left.new(message(expected, actual))
|
26
|
+
end
|
27
|
+
|
28
|
+
# ignore :reek:UtilityFunction
|
29
|
+
def success
|
30
|
+
# masked by soft fail
|
31
|
+
Either::Right.new(nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
def subscription_name
|
35
|
+
self.class.name.split('::').last.downcase
|
36
|
+
end
|
37
|
+
|
38
|
+
def message(expected, actual)
|
39
|
+
MESSAGE_FORMAT % {
|
40
|
+
actual: actual.any? ? actual.map(&:to_s).join("\n") : '[none]',
|
41
|
+
expected: expected.map(&:to_s).join("\n"),
|
42
|
+
subscription_name: subscription_name
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end # Subscription
|
46
|
+
end # License
|
47
|
+
end # Mutant
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module License
|
5
|
+
class Subscription
|
6
|
+
class Commercial < self
|
7
|
+
include Concord.new(:authors)
|
8
|
+
|
9
|
+
class Author
|
10
|
+
include Concord.new(:email)
|
11
|
+
|
12
|
+
alias_method :to_s, :email
|
13
|
+
public :to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_json(value)
|
17
|
+
new(value.fetch('authors').map(&Author.method(:new)).to_set)
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply(world)
|
21
|
+
candidates = candidates(world)
|
22
|
+
|
23
|
+
if (authors & candidates).any?
|
24
|
+
success
|
25
|
+
else
|
26
|
+
failure(authors, candidates)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def candidates(world)
|
33
|
+
git_author(world).merge(commit_author(world))
|
34
|
+
end
|
35
|
+
|
36
|
+
def git_author(world)
|
37
|
+
capture(world, %w[git config --get user.email])
|
38
|
+
end
|
39
|
+
|
40
|
+
def commit_author(world)
|
41
|
+
capture(world, %w[git show --quiet --pretty=format:%ae])
|
42
|
+
end
|
43
|
+
|
44
|
+
# ignore :reek:UtilityFunction
|
45
|
+
def capture(world, command)
|
46
|
+
world
|
47
|
+
.capture_stdout(command)
|
48
|
+
.fmap(&:chomp)
|
49
|
+
.fmap(&Author.method(:new))
|
50
|
+
.fmap { |value| Set.new([value]) }
|
51
|
+
.from_right { Set.new }
|
52
|
+
end
|
53
|
+
|
54
|
+
end # Commercial
|
55
|
+
end # Subscription
|
56
|
+
end # License
|
57
|
+
end # Mutant
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module License
|
5
|
+
class Subscription
|
6
|
+
class Opensource < self
|
7
|
+
include Concord.new(:repositories)
|
8
|
+
|
9
|
+
class Repository
|
10
|
+
include Concord.new(:host, :path)
|
11
|
+
|
12
|
+
REMOTE_REGEXP = /\A[^\t]+\t(?<url>[^ ]+) \((?:fetch|push)\)\n\z/.freeze
|
13
|
+
GIT_SSH_REGEXP = %r{\A[^@]+@(?<host>[^:/]+)[:/](?<path>.+?)(?:\.git)?\z}.freeze
|
14
|
+
GIT_HTTPS_REGEXP = %r{\Ahttps://(?<host>[^/]+)/(?<path>.+?)(?:\.git)?\z}.freeze
|
15
|
+
|
16
|
+
private_constant(*constants(false))
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
[host, path].join('/')
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse(input)
|
23
|
+
new(*input.split('/', 2))
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.parse_remote(input)
|
27
|
+
match = REMOTE_REGEXP.match(input) or
|
28
|
+
fail "Unmatched remote line: #{input.inspect}"
|
29
|
+
|
30
|
+
parse_url(match[:url])
|
31
|
+
end
|
32
|
+
private_class_method :parse_remote
|
33
|
+
|
34
|
+
def self.parse_url(input)
|
35
|
+
match = GIT_SSH_REGEXP.match(input) || GIT_HTTPS_REGEXP.match(input)
|
36
|
+
|
37
|
+
unless match
|
38
|
+
fail "Unmatched git remote URL: #{input.inspect}"
|
39
|
+
end
|
40
|
+
|
41
|
+
new(match[:host], match[:path])
|
42
|
+
end
|
43
|
+
private_class_method :parse_url
|
44
|
+
end
|
45
|
+
|
46
|
+
private_constant(*constants(false))
|
47
|
+
|
48
|
+
def self.from_json(value)
|
49
|
+
new(value.fetch('repositories').map(&Repository.method(:parse)))
|
50
|
+
end
|
51
|
+
|
52
|
+
def apply(world)
|
53
|
+
world
|
54
|
+
.capture_stdout(%w[git remote --verbose])
|
55
|
+
.fmap(&method(:parse_remotes))
|
56
|
+
.apply(&method(:check_subscription))
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def check_subscription(actual)
|
62
|
+
if (repositories.to_set & actual).any?
|
63
|
+
success
|
64
|
+
else
|
65
|
+
failure(repositories, actual)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# ignore :reek:UtilityFunction
|
70
|
+
def parse_remotes(input)
|
71
|
+
input.lines.map(&Repository.method(:parse_remote)).to_set
|
72
|
+
end
|
73
|
+
|
74
|
+
end # Opensource
|
75
|
+
end # Subscription
|
76
|
+
end # License
|
77
|
+
end # Mutant
|
data/lib/mutant/loader.rb
CHANGED
@@ -1,26 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mutant
|
4
|
-
# Base class for code loaders
|
5
4
|
class Loader
|
6
5
|
include Anima.new(:binding, :kernel, :source, :subject)
|
7
6
|
|
8
7
|
FROZEN_STRING_FORMAT = "# frozen_string_literal: true\n%s"
|
8
|
+
VOID_VALUE_REGEXP = /\A[^:]+:\d+: void value expression/.freeze
|
9
9
|
|
10
10
|
private_constant(*constants(false))
|
11
11
|
|
12
|
+
class Result
|
13
|
+
include Singleton
|
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
|
23
|
+
|
12
24
|
# Call loader
|
13
25
|
#
|
14
|
-
# @return [
|
26
|
+
# @return [Result]
|
15
27
|
def self.call(*arguments)
|
16
28
|
new(*arguments).call
|
17
29
|
end
|
18
30
|
|
19
31
|
# Call loader
|
20
32
|
#
|
21
|
-
# One off the very few valid uses of eval
|
33
|
+
# One off the very few valid uses of eval ever.
|
34
|
+
#
|
35
|
+
# @return [Result]
|
22
36
|
#
|
23
|
-
#
|
37
|
+
# rubocop:disable Metrics/MethodLength
|
24
38
|
def call
|
25
39
|
kernel.eval(
|
26
40
|
FROZEN_STRING_FORMAT % source,
|
@@ -28,6 +42,15 @@ module Mutant
|
|
28
42
|
subject.source_path.to_s,
|
29
43
|
subject.source_line
|
30
44
|
)
|
45
|
+
rescue SyntaxError => exception
|
46
|
+
# rubocop:disable Style/GuardClause
|
47
|
+
if VOID_VALUE_REGEXP.match?(exception.message)
|
48
|
+
Result::VoidValue.instance
|
49
|
+
else
|
50
|
+
raise
|
51
|
+
end
|
52
|
+
else
|
53
|
+
Result::Success.instance
|
31
54
|
end
|
32
55
|
end # Loader
|
33
56
|
end # Mutant
|
data/lib/mutant/matcher.rb
CHANGED
@@ -7,11 +7,58 @@ module Mutant
|
|
7
7
|
|
8
8
|
# Call matcher
|
9
9
|
#
|
10
|
-
# @param [Env
|
10
|
+
# @param [Env] env
|
11
11
|
#
|
12
12
|
# @return [Enumerable<Subject>]
|
13
13
|
#
|
14
14
|
abstract_method :call
|
15
15
|
|
16
|
+
# Turn config into matcher
|
17
|
+
#
|
18
|
+
# @param [Config] config
|
19
|
+
#
|
20
|
+
# @return [Matcher]
|
21
|
+
def self.from_config(config)
|
22
|
+
Filter.new(
|
23
|
+
Chain.new(config.match_expressions.map(&:matcher)),
|
24
|
+
method(:allowed_subject?).curry.call(config)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Test if subject is allowed do
|
29
|
+
#
|
30
|
+
# @param [Config] config
|
31
|
+
# @param [Subject] subject
|
32
|
+
#
|
33
|
+
# @return [Boolean]
|
34
|
+
def self.allowed_subject?(config, subject)
|
35
|
+
select_subject?(config, subject) && !ignore_subject?(config, subject)
|
36
|
+
end
|
37
|
+
private_class_method :allowed_subject?
|
38
|
+
|
39
|
+
# Predicate that tests for selected subject
|
40
|
+
#
|
41
|
+
# @param [Config] config
|
42
|
+
# @param [Subject] subject
|
43
|
+
#
|
44
|
+
# @return [Boolean]
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
def self.select_subject?(config, subject)
|
48
|
+
config.subject_filters.all? { |filter| filter.call(subject) }
|
49
|
+
end
|
50
|
+
private_class_method :select_subject?
|
51
|
+
|
52
|
+
# Predicate that tests for ignored subject
|
53
|
+
#
|
54
|
+
# @param [Config] config
|
55
|
+
# @param [Subject] subject
|
56
|
+
#
|
57
|
+
# @return [Boolean]
|
58
|
+
def self.ignore_subject?(config, subject)
|
59
|
+
config.ignore_expressions.any? do |expression|
|
60
|
+
expression.prefix?(subject.expression)
|
61
|
+
end
|
62
|
+
end
|
16
63
|
end # Matcher
|
17
64
|
end # Mutant
|
data/lib/mutant/matcher/chain.rb
CHANGED
@@ -8,9 +8,8 @@ module Mutant
|
|
8
8
|
Adamantium::Flat,
|
9
9
|
Concord::Public.new(:scope, :target_method, :evaluator)
|
10
10
|
|
11
|
-
#
|
12
|
-
|
13
|
-
BLACKLIST = %r{\A(kernel/|\(eval\)\z)}.freeze
|
11
|
+
# Source locations we cannot acces
|
12
|
+
BLACKLIST = %w[(eval) <internal:prelude>].to_set.freeze
|
14
13
|
|
15
14
|
SOURCE_LOCATION_WARNING_FORMAT =
|
16
15
|
'%s does not have a valid source location, unable to emit subject'
|
@@ -20,7 +19,7 @@ module Mutant
|
|
20
19
|
|
21
20
|
# Matched subjects
|
22
21
|
#
|
23
|
-
# @param [Env
|
22
|
+
# @param [Env] env
|
24
23
|
#
|
25
24
|
# @return [Enumerable<Subject>]
|
26
25
|
def call(env)
|
@@ -55,7 +54,7 @@ module Mutant
|
|
55
54
|
# @return [Truthy]
|
56
55
|
def skip?
|
57
56
|
location = source_location
|
58
|
-
if location.nil? || BLACKLIST.
|
57
|
+
if location.nil? || BLACKLIST.include?(location.first)
|
59
58
|
env.warn(SOURCE_LOCATION_WARNING_FORMAT % target_method)
|
60
59
|
elsif matched_node_path.any?(&method(:n_block?))
|
61
60
|
env.warn(CLOSURE_WARNING_FORMAT % target_method)
|
@@ -87,7 +86,7 @@ module Mutant
|
|
87
86
|
#
|
88
87
|
# @return [Pathname]
|
89
88
|
def source_path
|
90
|
-
env.
|
89
|
+
env.world.pathname.new(source_location.first)
|
91
90
|
end
|
92
91
|
memoize :source_path
|
93
92
|
|
@@ -114,7 +113,12 @@ module Mutant
|
|
114
113
|
# otherwise
|
115
114
|
def subject
|
116
115
|
node = matched_node_path.last || return
|
117
|
-
|
116
|
+
|
117
|
+
self.class::SUBJECT_CLASS.new(
|
118
|
+
context: context,
|
119
|
+
node: node,
|
120
|
+
warnings: env.world.warnings
|
121
|
+
)
|
118
122
|
end
|
119
123
|
memoize :subject
|
120
124
|
|