mutant 0.9.8 → 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +2 -2
- data/Changelog.md +6 -0
- data/README.md +63 -23
- data/config/reek.yml +1 -0
- data/lib/mutant.rb +4 -0
- data/lib/mutant/ast.rb +0 -9
- data/lib/mutant/ast/find_metaclass_containing.rb +48 -0
- data/lib/mutant/ast/meta/send.rb +0 -6
- data/lib/mutant/bootstrap.rb +0 -36
- data/lib/mutant/cli.rb +5 -49
- data/lib/mutant/color.rb +0 -3
- data/lib/mutant/config.rb +0 -8
- data/lib/mutant/context.rb +0 -3
- data/lib/mutant/diff.rb +0 -17
- data/lib/mutant/env.rb +0 -6
- data/lib/mutant/expression/method.rb +6 -6
- data/lib/mutant/expression/methods.rb +6 -6
- data/lib/mutant/expression/parser.rb +0 -6
- data/lib/mutant/integration.rb +0 -18
- data/lib/mutant/isolation/fork.rb +0 -22
- data/lib/mutant/license.rb +11 -0
- data/lib/mutant/matcher.rb +0 -14
- data/lib/mutant/matcher/config.rb +0 -11
- data/lib/mutant/matcher/method.rb +0 -31
- data/lib/mutant/matcher/method/instance.rb +0 -8
- data/lib/mutant/matcher/method/metaclass.rb +86 -0
- data/lib/mutant/matcher/method/singleton.rb +0 -25
- data/lib/mutant/matcher/methods.rb +17 -28
- data/lib/mutant/matcher/namespace.rb +0 -10
- data/lib/mutant/matcher/scope.rb +2 -4
- data/lib/mutant/meta/example/dsl.rb +0 -21
- data/lib/mutant/meta/example/verification.rb +0 -20
- data/lib/mutant/mutation.rb +0 -3
- data/lib/mutant/mutator.rb +1 -29
- data/lib/mutant/mutator/node.rb +1 -66
- data/lib/mutant/mutator/node/and_asgn.rb +0 -3
- data/lib/mutant/mutator/node/argument.rb +0 -15
- data/lib/mutant/mutator/node/arguments.rb +0 -20
- data/lib/mutant/mutator/node/begin.rb +0 -3
- data/lib/mutant/mutator/node/binary.rb +0 -23
- data/lib/mutant/mutator/node/block.rb +0 -15
- data/lib/mutant/mutator/node/break.rb +0 -3
- data/lib/mutant/mutator/node/case.rb +0 -9
- data/lib/mutant/mutator/node/class.rb +0 -3
- data/lib/mutant/mutator/node/conditional_loop.rb +0 -3
- data/lib/mutant/mutator/node/const.rb +0 -3
- data/lib/mutant/mutator/node/define.rb +0 -11
- data/lib/mutant/mutator/node/defined.rb +0 -3
- data/lib/mutant/mutator/node/dstr.rb +0 -3
- data/lib/mutant/mutator/node/dsym.rb +0 -3
- data/lib/mutant/mutator/node/generic.rb +0 -3
- data/lib/mutant/mutator/node/if.rb +0 -12
- data/lib/mutant/mutator/node/index.rb +0 -27
- data/lib/mutant/mutator/node/kwbegin.rb +0 -3
- data/lib/mutant/mutator/node/literal.rb +0 -3
- data/lib/mutant/mutator/node/literal/array.rb +0 -6
- data/lib/mutant/mutator/node/literal/boolean.rb +0 -4
- data/lib/mutant/mutator/node/literal/float.rb +0 -9
- data/lib/mutant/mutator/node/literal/hash.rb +0 -9
- data/lib/mutant/mutator/node/literal/integer.rb +0 -9
- data/lib/mutant/mutator/node/literal/nil.rb +0 -3
- data/lib/mutant/mutator/node/literal/range.rb +0 -6
- data/lib/mutant/mutator/node/literal/regex.rb +0 -6
- data/lib/mutant/mutator/node/literal/string.rb +0 -3
- data/lib/mutant/mutator/node/literal/symbol.rb +0 -3
- data/lib/mutant/mutator/node/masgn.rb +0 -3
- data/lib/mutant/mutator/node/match_current_line.rb +0 -3
- data/lib/mutant/mutator/node/mlhs.rb +0 -3
- data/lib/mutant/mutator/node/named_value/access.rb +2 -14
- data/lib/mutant/mutator/node/named_value/constant_assignment.rb +0 -9
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -6
- data/lib/mutant/mutator/node/next.rb +0 -3
- data/lib/mutant/mutator/node/noop.rb +0 -3
- data/lib/mutant/mutator/node/nthref.rb +0 -3
- data/lib/mutant/mutator/node/op_asgn.rb +0 -3
- data/lib/mutant/mutator/node/or_asgn.rb +0 -3
- data/lib/mutant/mutator/node/procarg_zero.rb +0 -3
- data/lib/mutant/mutator/node/regopt.rb +0 -6
- data/lib/mutant/mutator/node/resbody.rb +0 -6
- data/lib/mutant/mutator/node/rescue.rb +2 -19
- data/lib/mutant/mutator/node/return.rb +0 -3
- data/lib/mutant/mutator/node/sclass.rb +20 -0
- data/lib/mutant/mutator/node/send.rb +2 -61
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +0 -9
- data/lib/mutant/mutator/node/send/binary.rb +0 -11
- data/lib/mutant/mutator/node/send/conditional.rb +0 -3
- data/lib/mutant/mutator/node/splat.rb +0 -3
- data/lib/mutant/mutator/node/super.rb +0 -3
- data/lib/mutant/mutator/node/when.rb +0 -19
- data/lib/mutant/mutator/node/yield.rb +0 -3
- data/lib/mutant/mutator/node/zsuper.rb +0 -3
- data/lib/mutant/mutator/util/array.rb +0 -6
- data/lib/mutant/mutator/util/symbol.rb +0 -3
- data/lib/mutant/parallel.rb +0 -13
- data/lib/mutant/parallel/driver.rb +0 -10
- data/lib/mutant/parallel/worker.rb +0 -22
- data/lib/mutant/reporter/cli.rb +0 -5
- data/lib/mutant/reporter/cli/format.rb +0 -9
- data/lib/mutant/reporter/cli/printer.rb +0 -40
- data/lib/mutant/reporter/cli/printer/env_progress.rb +0 -15
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +0 -18
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -5
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +0 -21
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +0 -8
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -9
- data/lib/mutant/repository/diff.rb +1 -13
- data/lib/mutant/repository/diff/ranges.rb +0 -11
- data/lib/mutant/result.rb +0 -3
- data/lib/mutant/runner.rb +0 -18
- data/lib/mutant/runner/sink.rb +0 -5
- data/lib/mutant/subject.rb +0 -8
- data/lib/mutant/subject/method.rb +0 -3
- data/lib/mutant/subject/method/instance.rb +0 -5
- data/lib/mutant/subject/method/metaclass.rb +30 -0
- data/lib/mutant/transform.rb +0 -92
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warnings.rb +0 -6
- data/lib/mutant/zombifier.rb +2 -34
- data/meta/and.rb +0 -2
- data/meta/array.rb +0 -3
- data/meta/begin.rb +0 -3
- data/meta/block.rb +0 -3
- data/meta/break.rb +0 -1
- data/meta/case.rb +0 -6
- data/meta/casgn.rb +0 -3
- data/meta/cvasgn.rb +0 -1
- data/meta/def.rb +0 -7
- data/meta/ensure.rb +0 -1
- data/meta/false.rb +0 -1
- data/meta/gvasgn.rb +0 -1
- data/meta/hash.rb +0 -4
- data/meta/if.rb +0 -5
- data/meta/ivasgn.rb +0 -1
- data/meta/kwbegin.rb +0 -1
- data/meta/lvasgn.rb +0 -1
- data/meta/match_current_line.rb +0 -1
- data/meta/next.rb +0 -1
- data/meta/or.rb +0 -2
- data/meta/regexp.rb +0 -1
- data/meta/rescue.rb +0 -6
- data/meta/sclass.rb +12 -0
- data/meta/send.rb +0 -4
- data/meta/true.rb +0 -1
- data/meta/until.rb +0 -1
- data/meta/while.rb +0 -2
- data/meta/yield.rb +0 -1
- data/mutant.sh +12 -0
- data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +64 -0
- data/spec/unit/mutant/expression/methods_spec.rb +7 -2
- data/spec/unit/mutant/license_spec.rb +15 -3
- data/spec/unit/mutant/matcher/method/metaclass_spec.rb +108 -0
- data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +62 -0
- data/spec/unit/mutant/matcher/namespace_spec.rb +3 -1
- data/spec/unit/mutant/matcher/scope_spec.rb +11 -1
- data/spec/unit/mutant/meta/example_spec.rb +3 -3
- data/spec/unit/mutant/mutator/node_spec.rb +1 -6
- data/spec/unit/mutant/subject/method/metaclass_spec.rb +63 -0
- data/test_app/lib/test_app.rb +1 -0
- data/test_app/lib/test_app/metaclasses.rb +108 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6e6e125d0e2736934ed481945e35eada9a1b8fffaf05641a5410a2ed25b9b20
|
4
|
+
data.tar.gz: 13e2b48cbc500aab1ef792ccbaff86de593337f7213bdcf7d0d81afa21e7a641
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a3bfbaffad39ee2bc7cf41a07c19031704c26c7d05ba9b3f07d59d3b82965311c0822aec10ab359570fc8c3d3235f36d461fbe39cddb6349997b2b8bd0fa5d3
|
7
|
+
data.tar.gz: a1caa7e5f3318001137239c613ddd50bdeabe981fa132f4e9e5a383019a24a53075da121b290e98dcb61c93a1900f79f8e1207ce7ac282d049b2af0351b26e64
|
data/.github/workflows/ci.yml
CHANGED
@@ -31,7 +31,7 @@ jobs:
|
|
31
31
|
ruby-mutant:
|
32
32
|
name: Mutation coverage
|
33
33
|
runs-on: ${{ matrix.os }}
|
34
|
-
timeout-minutes:
|
34
|
+
timeout-minutes: 30
|
35
35
|
strategy:
|
36
36
|
fail-fast: false
|
37
37
|
matrix:
|
@@ -47,7 +47,7 @@ jobs:
|
|
47
47
|
- run: |
|
48
48
|
gem install bundler
|
49
49
|
bundle install
|
50
|
-
- run:
|
50
|
+
- run: ./mutant.sh
|
51
51
|
ruby-integration-minitest:
|
52
52
|
name: Integration Minitest
|
53
53
|
runs-on: ${{ matrix.os }}
|
data/Changelog.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# v0.9.9 2020-09-25
|
2
|
+
|
3
|
+
+ Add support for mutating methods inside eigenclasses `class <<`. [#1009](https://github.com/mbj/mutant/pull/1009)
|
4
|
+
- Remove `<` -> `<=` and `>` -> `>=` mutations as non canonical. [#1020](https://github.com/mbj/mutant/pull/1020)
|
5
|
+
- Remove `true` -> `nil` and `false` -> `nil` mutations as non canonical. [#1018](https://github.com/mbj/mutant/pull/1018)
|
6
|
+
|
1
7
|
# v0.9.8 2020-08-02
|
2
8
|
|
3
9
|
* Change to generic catch all node mutator. This allows better cross parser version compatibility.
|
data/README.md
CHANGED
@@ -7,31 +7,41 @@ mutant
|
|
7
7
|
|
8
8
|
## What is Mutant?
|
9
9
|
|
10
|
-
|
10
|
+
An automated code review tool, with a side effect of producing semantic code coverage
|
11
|
+
metrics.
|
11
12
|
|
12
|
-
|
13
|
+
Think of mutant as an expert developer that simplifies your code while making sure that all tests pass.
|
13
14
|
|
14
|
-
|
15
|
-
Coverage becomes a meaningful metric!
|
15
|
+
That developer never has a bad day and is always ready to jump on your PR.
|
16
16
|
|
17
|
-
|
17
|
+
Each reported simplification signifies either:
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
* Learn something new about the semantics of Ruby and your direct and indirect dependencies.
|
19
|
+
A) A piece of code that does more than the tests ask for.
|
20
|
+
You can probably use the simplified version of the code. OR:
|
22
21
|
|
23
|
-
|
22
|
+
B) If you have a reason to not take the simplified version as it violates a requirement:
|
23
|
+
There was no test that proves the extra requirement. Likely you are missing an
|
24
|
+
important test for that requirement.
|
24
25
|
|
25
|
-
|
26
|
+
On extensive mutant use A) happens more often than B), which leads to overall less code enter
|
27
|
+
your repository at higher confidence for both the author and the reviewer.
|
28
|
+
|
29
|
+
BTW: Mutant is a mutation testing tool, which is a form of code coverage.
|
30
|
+
But each reported uncovered mutation is actually a call to action, just like a flag in a code review
|
31
|
+
would be.
|
32
|
+
|
33
|
+
## Getting started:
|
34
|
+
|
35
|
+
* Start with reading the [nomenclature](/docs/nomenclature.md). No way around that one, sorry.
|
26
36
|
* Then select and setup your [integration](/docs/nomenclature.md#integration), also make sure
|
27
37
|
you can reproduce the examples in the integration specific documentation.
|
28
|
-
*
|
29
|
-
|
30
|
-
|
38
|
+
* Use mutant during code reviews and on CI in [incremental](/docs/incremental.md) mode.
|
39
|
+
* Do not merge code with new alive mutations. If you really must bypass:
|
40
|
+
Add the subjects with open problems to the ignored subjects.
|
31
41
|
|
32
42
|
## Ruby Versions
|
33
43
|
|
34
|
-
Mutant currently only works on cRuby/MRI. Starting with version 2.5.x. It supports all syntax features
|
44
|
+
Mutant currently only works on cRuby/MRI. Starting with version 2.5.x. It supports all syntax features up to and
|
35
45
|
including Ruby 2.6.
|
36
46
|
|
37
47
|
Support for 2.7 syntax features is pending, see unparser issue: https://github.com/mbj/unparser/issues/129.
|
@@ -43,7 +53,7 @@ Mutant will work under Ruby 2.7 just fine, unless a 2.7 syntax feature is used.
|
|
43
53
|
Mutant was recently transitioned commercial software, with a free usage plan for opensource projects.
|
44
54
|
|
45
55
|
Commercial projects have to acquire a license per developer, with unlimited repositories
|
46
|
-
per developer.
|
56
|
+
per developer. CI usage for licensed developers is included.
|
47
57
|
|
48
58
|
Opensource projects have to acquire their free license per repository.
|
49
59
|
|
@@ -65,22 +75,52 @@ The mutant license gem contains metadata that allows mutant to verify licensed u
|
|
65
75
|
For commercial licenses mutant checks the git commit author or the configured git email
|
66
76
|
to be in the set of licensed developers.
|
67
77
|
|
68
|
-
For opensource licenses mutant checks the git remotes against the
|
78
|
+
For opensource licenses mutant checks the git remotes against the licensed git repositories.
|
69
79
|
This allows the project maintainer to sign up and not bother collaborators with the details.
|
70
80
|
|
71
|
-
There are, apart from initial license gem installation, no remote
|
81
|
+
There are, apart from initial license gem installation, no remote interaction for
|
72
82
|
license validation.
|
73
83
|
|
74
|
-
|
84
|
+
### Getting an Opensource license
|
85
|
+
|
86
|
+
As stated above: Opensource projects of any kind are free to use mutant.
|
87
|
+
|
88
|
+
Just mail [me](mailto:mbj@schirp-dso.com?subject=Mutant%20Opensource%20License): Please
|
89
|
+
include:
|
90
|
+
|
91
|
+
* Just the git remote URL of your repository. Repository can be anywhere, must not be on Github, just has to be public.
|
92
|
+
|
93
|
+
I do not need any more details.
|
94
|
+
|
95
|
+
### Getting a commercial license
|
96
|
+
|
97
|
+
Mutant offers a per developer subscription a monthly plan for 30$, or an annual plan for 300$.
|
98
|
+
|
99
|
+
Above 10 developer licensees per customer I'm open to negotiate more discounts.
|
100
|
+
|
101
|
+
Should you want to procure a commercial mutant license please [mail me](mailto:mbj@schirp-dso.com?subject=Mutant%20Commercial%20License).
|
102
|
+
|
103
|
+
Please include the following information:
|
104
|
+
|
105
|
+
* Your invoice address, including your Tax ID (For EU customers VAT-ID is mandatory)
|
106
|
+
* Per licensed user the git author email address as returned by `git config user.email`
|
107
|
+
|
108
|
+
Also feel free to ask any other question I forgot to proactively answer here.
|
109
|
+
|
110
|
+
#### Payment methods
|
111
|
+
|
112
|
+
* For monthly subscriptions: Exclusively CC.
|
113
|
+
* For annual subscriptions: CC (worldwide) or ACH (US) / SEPA (EU) wire transfer.
|
75
114
|
|
76
|
-
|
115
|
+
#### Pricing Why?
|
77
116
|
|
78
|
-
|
117
|
+
The idea is to charge 1$ per developer per day. Mutant reduces the time spend on code reviews.
|
79
118
|
|
80
|
-
|
81
|
-
Yearly prepayments with discounts are available.
|
119
|
+
This time saved should be worth way more than the 1$ per day.
|
82
120
|
|
83
|
-
|
121
|
+
If you think this is not true for your code base, either my claims are wrong our your use of mutant is wrong.
|
122
|
+
I'd be happy to hear about your case as I'm certainly willing to help you in using mutant right, and in case
|
123
|
+
I'm wrong I'd be happy to improve mutant to the point I'm right again.
|
84
124
|
|
85
125
|
## Topics
|
86
126
|
|
data/config/reek.yml
CHANGED
@@ -136,3 +136,4 @@ detectors:
|
|
136
136
|
- Mutant::Reporter::CLI::Printer::StatusProgressive#object # False positive calls super
|
137
137
|
- Mutant::Repository::Diff#tracks? # intentional, private
|
138
138
|
- Mutant::Repository::Diff#within_working_directory? # intentional, private
|
139
|
+
- Mutant::AST::FindMetaclassContaining#include_exact? # intentional, private
|
data/lib/mutant.rb
CHANGED
@@ -51,6 +51,7 @@ require 'mutant/ast/types'
|
|
51
51
|
require 'mutant/ast/nodes'
|
52
52
|
require 'mutant/ast/named_children'
|
53
53
|
require 'mutant/ast/node_predicates'
|
54
|
+
require 'mutant/ast/find_metaclass_containing'
|
54
55
|
require 'mutant/ast/meta'
|
55
56
|
require 'mutant/ast/meta/send'
|
56
57
|
require 'mutant/ast/meta/const'
|
@@ -112,6 +113,7 @@ require 'mutant/mutator/node/send/conditional'
|
|
112
113
|
require 'mutant/mutator/node/send/attribute_assignment'
|
113
114
|
require 'mutant/mutator/node/when'
|
114
115
|
require 'mutant/mutator/node/class'
|
116
|
+
require 'mutant/mutator/node/sclass'
|
115
117
|
require 'mutant/mutator/node/define'
|
116
118
|
require 'mutant/mutator/node/mlhs'
|
117
119
|
require 'mutant/mutator/node/nthref'
|
@@ -134,11 +136,13 @@ require 'mutant/subject'
|
|
134
136
|
require 'mutant/subject/method'
|
135
137
|
require 'mutant/subject/method/instance'
|
136
138
|
require 'mutant/subject/method/singleton'
|
139
|
+
require 'mutant/subject/method/metaclass'
|
137
140
|
require 'mutant/matcher'
|
138
141
|
require 'mutant/matcher/config'
|
139
142
|
require 'mutant/matcher/chain'
|
140
143
|
require 'mutant/matcher/method'
|
141
144
|
require 'mutant/matcher/method/singleton'
|
145
|
+
require 'mutant/matcher/method/metaclass'
|
142
146
|
require 'mutant/matcher/method/instance'
|
143
147
|
require 'mutant/matcher/methods'
|
144
148
|
require 'mutant/matcher/namespace'
|
data/lib/mutant/ast.rb
CHANGED
@@ -27,15 +27,6 @@ module Mutant
|
|
27
27
|
path
|
28
28
|
end
|
29
29
|
|
30
|
-
# Walk all ast nodes keeping track of path
|
31
|
-
#
|
32
|
-
# @param [Parser::AST::Node] root
|
33
|
-
# @param [Array<Parser::AST::Node>] stack
|
34
|
-
#
|
35
|
-
# @yield [Parser::AST::Node]
|
36
|
-
# all nodes visited recursively including root
|
37
|
-
#
|
38
|
-
# @return [undefined]
|
39
30
|
def self.walk(node, stack, &block)
|
40
31
|
block.call(node, stack)
|
41
32
|
node.children.grep(::Parser::AST::Node) do |child|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
module AST
|
5
|
+
# Given an AST, finds the sclass that directly(-ish) contains the provided
|
6
|
+
# node.
|
7
|
+
# This won't match arbitrarily complex structures - it only searches the
|
8
|
+
# first level deep (no begins-in-begins, for example). This is in
|
9
|
+
# keeping with mutant generally not supporting 'weird' syntax.
|
10
|
+
# Descending into 'begin' nodes is supported because these are generated for
|
11
|
+
# the one-line syntax class << self; def foo; end
|
12
|
+
class FindMetaclassContaining
|
13
|
+
include NodePredicates, Concord.new(:root, :target), Procto.call
|
14
|
+
|
15
|
+
SCLASS_BODY_INDEX = 1
|
16
|
+
|
17
|
+
private_constant(*constants(false))
|
18
|
+
|
19
|
+
# Find metaclass node containing target node
|
20
|
+
#
|
21
|
+
# @return [Parser::AST::Node, nil]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
def call
|
25
|
+
AST.find_last_path(root) do |current|
|
26
|
+
next unless n_sclass?(current)
|
27
|
+
|
28
|
+
metaclass_of?(current)
|
29
|
+
end.last
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def metaclass_of?(sclass)
|
35
|
+
body = sclass.children.fetch(SCLASS_BODY_INDEX)
|
36
|
+
body.equal?(target) || transparently_contains?(body)
|
37
|
+
end
|
38
|
+
|
39
|
+
def transparently_contains?(body)
|
40
|
+
n_begin?(body) && include_exact?(body.children, target)
|
41
|
+
end
|
42
|
+
|
43
|
+
def include_exact?(haystack, needle)
|
44
|
+
haystack.any? { |elem| elem.equal?(needle) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/mutant/ast/meta/send.rb
CHANGED
@@ -56,16 +56,10 @@ module Mutant
|
|
56
56
|
|
57
57
|
private
|
58
58
|
|
59
|
-
# Test if node is `proc { ... }`
|
60
|
-
#
|
61
|
-
# @return [Boolean]
|
62
59
|
def naked_proc?
|
63
60
|
!receiver && selector.equal?(:proc)
|
64
61
|
end
|
65
62
|
|
66
|
-
# Test if node is `Proc.new { ... }`
|
67
|
-
#
|
68
|
-
# @return [Boolean]
|
69
63
|
def proc_new?
|
70
64
|
receiver &&
|
71
65
|
selector.equal?(:new) &&
|
data/lib/mutant/bootstrap.rb
CHANGED
@@ -49,9 +49,6 @@ module Mutant
|
|
49
49
|
end
|
50
50
|
# rubocop:enable Metrics/MethodLength
|
51
51
|
|
52
|
-
# Infect environment
|
53
|
-
#
|
54
|
-
# @return [undefined]
|
55
52
|
def self.infect(env)
|
56
53
|
config, world = env.config, env.world
|
57
54
|
|
@@ -60,12 +57,6 @@ module Mutant
|
|
60
57
|
end
|
61
58
|
private_class_method :infect
|
62
59
|
|
63
|
-
# Matchable scopes
|
64
|
-
#
|
65
|
-
# @param [World] world
|
66
|
-
# @param [Config] config
|
67
|
-
#
|
68
|
-
# @return [Array<Scope>]
|
69
60
|
def self.matchable_scopes(world, config)
|
70
61
|
scopes = world.object_space.each_object(Module).each_with_object([]) do |scope, aggregate|
|
71
62
|
expression = expression(config.reporter, config.expression_parser, scope) || next
|
@@ -76,15 +67,6 @@ module Mutant
|
|
76
67
|
end
|
77
68
|
private_class_method :matchable_scopes
|
78
69
|
|
79
|
-
# Scope name from scoping object
|
80
|
-
#
|
81
|
-
# @param [Class, Module] scope
|
82
|
-
#
|
83
|
-
# @return [String]
|
84
|
-
# if scope has a name and does not raise exceptions obtaining it
|
85
|
-
#
|
86
|
-
# @return [nil]
|
87
|
-
# otherwise
|
88
70
|
def self.scope_name(reporter, scope)
|
89
71
|
scope.name
|
90
72
|
rescue => exception
|
@@ -99,20 +81,7 @@ module Mutant
|
|
99
81
|
end
|
100
82
|
private_class_method :scope_name
|
101
83
|
|
102
|
-
# Try to turn scope into expression
|
103
|
-
#
|
104
|
-
# @param [Expression::Parser] expression_parser
|
105
|
-
# @param [Class, Module] scope
|
106
|
-
#
|
107
|
-
# @return [Expression]
|
108
|
-
# if scope can be represented in an expression
|
109
|
-
#
|
110
|
-
# @return [nil]
|
111
|
-
# otherwise
|
112
|
-
#
|
113
84
|
# rubocop:disable Metrics/MethodLength
|
114
|
-
#
|
115
|
-
# ignore :reek:LongParameterList
|
116
85
|
def self.expression(reporter, expression_parser, scope)
|
117
86
|
name = scope_name(reporter, scope) or return
|
118
87
|
|
@@ -132,11 +101,6 @@ module Mutant
|
|
132
101
|
private_class_method :expression
|
133
102
|
# rubocop:enable Metrics/MethodLength
|
134
103
|
|
135
|
-
# Write a semantics warning
|
136
|
-
#
|
137
|
-
# @return [undefined]
|
138
|
-
#
|
139
|
-
# ignore :reek:LongParameterList
|
140
104
|
def self.semantics_warning(reporter, format, options)
|
141
105
|
reporter.warn(SEMANTICS_MESSAGE_FORMAT % { message: format % options })
|
142
106
|
end
|
data/lib/mutant/cli.rb
CHANGED
@@ -88,23 +88,12 @@ module Mutant
|
|
88
88
|
|
89
89
|
private
|
90
90
|
|
91
|
-
# Parse matchers
|
92
|
-
#
|
93
|
-
# @param [Array<String>] expressions
|
94
|
-
#
|
95
|
-
# @return [undefined]
|
96
91
|
def parse_match_expressions(expressions)
|
97
92
|
expressions.each do |expression|
|
98
93
|
add_matcher(:match_expressions, config.expression_parser.apply(expression).from_right)
|
99
94
|
end
|
100
95
|
end
|
101
96
|
|
102
|
-
# Add environmental options
|
103
|
-
#
|
104
|
-
# @param [Object] opts
|
105
|
-
#
|
106
|
-
# @return [undefined]
|
107
|
-
#
|
108
97
|
# rubocop:disable Metrics/MethodLength
|
109
98
|
def add_environment_options(opts)
|
110
99
|
opts.separator('Environment:')
|
@@ -121,12 +110,8 @@ module Mutant
|
|
121
110
|
with(jobs: Integer(number))
|
122
111
|
end
|
123
112
|
end
|
113
|
+
# rubocop:enable Metrics/MethodLength
|
124
114
|
|
125
|
-
# Add mutation options
|
126
|
-
#
|
127
|
-
# @param [OptionParser] opts
|
128
|
-
#
|
129
|
-
# @return [undefined]
|
130
115
|
def add_mutation_options(opts)
|
131
116
|
opts.separator(nil)
|
132
117
|
opts.separator('Options:')
|
@@ -136,11 +121,7 @@ module Mutant
|
|
136
121
|
end
|
137
122
|
end
|
138
123
|
|
139
|
-
#
|
140
|
-
#
|
141
|
-
# @param [OptionParser] opts
|
142
|
-
#
|
143
|
-
# @return [undefined]
|
124
|
+
# rubocop:disable Metrics/MethodLength
|
144
125
|
def add_filter_options(opts)
|
145
126
|
opts.on('--ignore-subject EXPRESSION', 'Ignore subjects that match EXPRESSION as prefix') do |pattern|
|
146
127
|
add_matcher(:ignore_expressions, config.expression_parser.apply(pattern).from_right)
|
@@ -154,12 +135,9 @@ module Mutant
|
|
154
135
|
)
|
155
136
|
end
|
156
137
|
end
|
138
|
+
# rubocop:enable Metrics/MethodLength
|
157
139
|
|
158
|
-
#
|
159
|
-
#
|
160
|
-
# @param [OptionParser] opts
|
161
|
-
#
|
162
|
-
# @return [undefined]
|
140
|
+
# rubocop:disable Metrics/MethodLength
|
163
141
|
def add_debug_options(opts)
|
164
142
|
opts.on('--fail-fast', 'Fail fast') do
|
165
143
|
with(fail_fast: true)
|
@@ -173,38 +151,16 @@ module Mutant
|
|
173
151
|
world.kernel.exit
|
174
152
|
end
|
175
153
|
end
|
154
|
+
# rubocop:enable Metrics/MethodLength
|
176
155
|
|
177
|
-
# With configuration
|
178
|
-
#
|
179
|
-
# @param [Hash<Symbol, Object>] attributes
|
180
|
-
#
|
181
|
-
# @return [undefined]
|
182
156
|
def with(attributes)
|
183
157
|
@config = config.with(attributes)
|
184
158
|
end
|
185
159
|
|
186
|
-
# Add configuration
|
187
|
-
#
|
188
|
-
# @param [Symbol] attribute
|
189
|
-
# the attribute to add to
|
190
|
-
#
|
191
|
-
# @param [Object] value
|
192
|
-
# the value to add
|
193
|
-
#
|
194
|
-
# @return [undefined]
|
195
160
|
def add(attribute, value)
|
196
161
|
with(attribute => config.public_send(attribute) + [value])
|
197
162
|
end
|
198
163
|
|
199
|
-
# Add matcher configuration
|
200
|
-
#
|
201
|
-
# @param [Symbol] attribute
|
202
|
-
# the attribute to add to
|
203
|
-
#
|
204
|
-
# @param [Object] value
|
205
|
-
# the value to add
|
206
|
-
#
|
207
|
-
# @return [undefined]
|
208
164
|
def add_matcher(attribute, value)
|
209
165
|
with(matcher: config.matcher.add(attribute, value))
|
210
166
|
end
|