mutant 0.11.13 → 0.11.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/mutant +40 -35
- data/lib/mutant/ast/find_metaclass_containing.rb +6 -6
- data/lib/mutant/ast/meta/const.rb +1 -1
- data/lib/mutant/ast/meta/optarg.rb +1 -1
- data/lib/mutant/ast/meta/resbody.rb +1 -1
- data/lib/mutant/ast/meta/send.rb +1 -1
- data/lib/mutant/ast/meta/symbol.rb +1 -1
- data/lib/mutant/ast/meta.rb +1 -1
- data/lib/mutant/ast/named_children.rb +1 -1
- data/lib/mutant/ast/node_predicates.rb +1 -1
- data/lib/mutant/ast/nodes.rb +1 -1
- data/lib/mutant/ast/pattern/lexer.rb +1 -1
- data/lib/mutant/ast/pattern/parser.rb +1 -1
- data/lib/mutant/ast/pattern/source.rb +1 -1
- data/lib/mutant/ast/pattern/token.rb +1 -1
- data/lib/mutant/ast/pattern.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/direct.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/named_group.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/options_group.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/recursive.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/root.rb +1 -1
- data/lib/mutant/ast/regexp/transformer/text.rb +1 -1
- data/lib/mutant/ast/regexp/transformer.rb +1 -1
- data/lib/mutant/ast/regexp.rb +1 -1
- data/lib/mutant/ast/sexp.rb +1 -1
- data/lib/mutant/ast/structure.rb +8 -3
- data/lib/mutant/ast/types.rb +1 -1
- data/lib/mutant/ast.rb +31 -29
- data/lib/mutant/cli/command/environment/run.rb +0 -7
- data/lib/mutant/cli/command/environment.rb +4 -5
- data/lib/mutant/cli/command.rb +24 -22
- data/lib/mutant/cli.rb +2 -4
- data/lib/mutant/config.rb +4 -16
- data/lib/mutant/matcher/method/instance.rb +3 -2
- data/lib/mutant/matcher/method/metaclass.rb +4 -3
- data/lib/mutant/matcher/method/singleton.rb +3 -2
- data/lib/mutant/matcher/method.rb +32 -23
- data/lib/mutant/mutation/config.rb +2 -1
- data/lib/mutant/mutator/node/block.rb +5 -3
- data/lib/mutant/mutator/node/define.rb +3 -2
- data/lib/mutant/parser.rb +0 -7
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant.rb +2 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebfdb4dba80abb7c2b06b6b057cebf6db686b598219979ed3d0730b6e5a9ed82
|
4
|
+
data.tar.gz: ee03173b094cf29a9d21ad30b383a0b01b8cac7b7ba1132f24f36c25e9e4fee3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90d9c06d5a2900441b49b3bc0fa039b11bb296e389af41927f711431855a28369a8e31faf0b1cc5ba74ab09c6300c21002ac30c0d6eae6b3d63eac3129a692e8
|
7
|
+
data.tar.gz: 725ecfb369b3c28133d898f3405bb5cec8f780027c8e7c05de59c225719924fde51e192186d2f7a2199a57352b056401fa562a67d75409a637d182bbb50d9390
|
data/bin/mutant
CHANGED
@@ -8,43 +8,48 @@ end
|
|
8
8
|
|
9
9
|
require 'mutant'
|
10
10
|
|
11
|
-
|
11
|
+
Mutant::CLI.parse(
|
12
12
|
arguments: ARGV,
|
13
13
|
world: Mutant::WORLD
|
14
|
-
)
|
14
|
+
).either(
|
15
|
+
->(message) { Mutant::WORLD.stderr.puts(message); Kernel.exit(false) },
|
16
|
+
# rubocop:disable Metrics/BlockLength
|
17
|
+
lambda do |command|
|
18
|
+
status =
|
19
|
+
if command.zombie?
|
20
|
+
$stderr.puts('Running mutant zombified!')
|
21
|
+
Mutant::Zombifier.call(
|
22
|
+
namespace: :Zombie,
|
23
|
+
load_path: $LOAD_PATH,
|
24
|
+
kernel: Kernel,
|
25
|
+
pathname: Pathname,
|
26
|
+
require_highjack: Mutant::RequireHighjack
|
27
|
+
.public_method(:call)
|
28
|
+
.to_proc
|
29
|
+
.curry
|
30
|
+
.call(Kernel),
|
31
|
+
root_require: 'mutant',
|
32
|
+
includes: %w[
|
33
|
+
adamantium
|
34
|
+
anima
|
35
|
+
concord
|
36
|
+
equalizer
|
37
|
+
mprelude
|
38
|
+
mutant
|
39
|
+
unparser
|
40
|
+
variable
|
41
|
+
]
|
42
|
+
)
|
15
43
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
pathname: Pathname,
|
24
|
-
require_highjack: Mutant::RequireHighjack
|
25
|
-
.public_method(:call)
|
26
|
-
.to_proc
|
27
|
-
.curry
|
28
|
-
.call(Kernel),
|
29
|
-
root_require: 'mutant',
|
30
|
-
includes: %w[
|
31
|
-
adamantium
|
32
|
-
anima
|
33
|
-
concord
|
34
|
-
equalizer
|
35
|
-
mprelude
|
36
|
-
mutant
|
37
|
-
unparser
|
38
|
-
variable
|
39
|
-
]
|
40
|
-
)
|
44
|
+
Zombie::Mutant::CLI.parse(
|
45
|
+
arguments: ARGV,
|
46
|
+
world: Zombie::Mutant::WORLD
|
47
|
+
).from_right.call
|
48
|
+
else
|
49
|
+
command.call
|
50
|
+
end
|
41
51
|
|
42
|
-
|
43
|
-
arguments: ARGV,
|
44
|
-
world: Zombie::Mutant::WORLD
|
45
|
-
).call
|
46
|
-
else
|
47
|
-
command.call
|
52
|
+
Kernel.exit(status)
|
48
53
|
end
|
49
|
-
|
50
|
-
|
54
|
+
# rubocop:enable Metrics/BlockLength
|
55
|
+
)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mutant
|
4
|
-
|
4
|
+
class AST
|
5
5
|
# Given an AST, finds the sclass that directly(-ish) contains the provided
|
6
6
|
# node.
|
7
7
|
# This won't match arbitrarily complex structures - it only searches the
|
@@ -10,7 +10,7 @@ module Mutant
|
|
10
10
|
# Descending into 'begin' nodes is supported because these are generated for
|
11
11
|
# the one-line syntax class << self; def foo; end
|
12
12
|
class FindMetaclassContaining
|
13
|
-
include NodePredicates, Concord.new(:
|
13
|
+
include NodePredicates, Concord.new(:ast, :target), Procto
|
14
14
|
|
15
15
|
SCLASS_BODY_INDEX = 1
|
16
16
|
|
@@ -22,11 +22,11 @@ module Mutant
|
|
22
22
|
#
|
23
23
|
# @api private
|
24
24
|
def call
|
25
|
-
|
26
|
-
|
25
|
+
Structure.for(ast.node.type).each_node(ast.node) do |current|
|
26
|
+
return current if n_sclass?(current) && metaclass_of?(current)
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
end.last
|
29
|
+
nil
|
30
30
|
end
|
31
31
|
|
32
32
|
private
|
data/lib/mutant/ast/meta/send.rb
CHANGED
data/lib/mutant/ast/meta.rb
CHANGED
data/lib/mutant/ast/nodes.rb
CHANGED
data/lib/mutant/ast/pattern.rb
CHANGED
data/lib/mutant/ast/regexp.rb
CHANGED
data/lib/mutant/ast/sexp.rb
CHANGED
data/lib/mutant/ast/structure.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mutant
|
4
|
-
|
4
|
+
class AST
|
5
5
|
# AST Structure metadata
|
6
6
|
# rubocop:disable Metrics/ModuleLength
|
7
7
|
module Structure
|
@@ -26,7 +26,7 @@ module Mutant
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def value(node)
|
29
|
-
node.children.
|
29
|
+
node.children.at(index)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -246,7 +246,7 @@ module Mutant
|
|
246
246
|
type: :class,
|
247
247
|
fixed: Node.fixed(
|
248
248
|
[
|
249
|
-
[Node::Fixed::
|
249
|
+
[Node::Fixed::Attribute, :name],
|
250
250
|
[Node::Fixed::Descendant, :superclass],
|
251
251
|
[Node::Fixed::Descendant, :body]
|
252
252
|
]
|
@@ -386,6 +386,11 @@ module Mutant
|
|
386
386
|
fixed: Node.fixed([[Node::Fixed::Attribute, :value]]),
|
387
387
|
variable: nil
|
388
388
|
),
|
389
|
+
Node.new(
|
390
|
+
type: :forwarded_args,
|
391
|
+
fixed: EMPTY_ARRAY,
|
392
|
+
variable: nil
|
393
|
+
),
|
389
394
|
Node.new(
|
390
395
|
type: :for,
|
391
396
|
fixed: Node.fixed(
|
data/lib/mutant/ast/types.rb
CHANGED
data/lib/mutant/ast.rb
CHANGED
@@ -1,41 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mutant
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
4
|
+
class AST
|
5
|
+
include Adamantium, Anima.new(
|
6
|
+
:node,
|
7
|
+
:comment_associations
|
8
|
+
)
|
9
|
+
|
10
|
+
class View
|
11
|
+
include Adamantium, Anima.new(:node, :path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_line(line)
|
15
|
+
line_map.fetch(line, EMPTY_HASH).map do |node, path|
|
16
|
+
View.new(node: node, path: path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def line_map
|
23
|
+
line_map = {}
|
24
|
+
|
25
|
+
walk_path(node) do |node, path|
|
26
|
+
expression = node.location.expression || next
|
27
|
+
(line_map[expression.line] ||= []) << [node, path]
|
26
28
|
end
|
27
|
-
|
29
|
+
|
30
|
+
line_map
|
28
31
|
end
|
32
|
+
memoize :line_map
|
29
33
|
|
30
|
-
def
|
31
|
-
block.call(node, stack)
|
34
|
+
def walk_path(node, stack = [node.type], &block)
|
35
|
+
block.call(node, stack.dup)
|
32
36
|
node.children.grep(::Parser::AST::Node) do |child|
|
33
|
-
stack.push(child)
|
34
|
-
|
37
|
+
stack.push(child.type)
|
38
|
+
walk_path(child, stack, &block)
|
35
39
|
stack.pop
|
36
40
|
end
|
37
41
|
end
|
38
|
-
private_class_method :walk
|
39
|
-
|
40
42
|
end # AST
|
41
43
|
end # Mutant
|
@@ -19,7 +19,9 @@ module Mutant
|
|
19
19
|
|
20
20
|
def initialize(attributes)
|
21
21
|
super(attributes)
|
22
|
-
@config = Config::DEFAULT
|
22
|
+
@config = Config::DEFAULT.with(
|
23
|
+
coverage_criteria: Config::CoverageCriteria::EMPTY
|
24
|
+
)
|
23
25
|
end
|
24
26
|
|
25
27
|
def bootstrap
|
@@ -37,7 +39,7 @@ module Mutant
|
|
37
39
|
)
|
38
40
|
end
|
39
41
|
|
40
|
-
@config = Config.env.merge(file_config).merge(@config)
|
42
|
+
@config = Config.env.merge(file_config).merge(@config)
|
41
43
|
end
|
42
44
|
|
43
45
|
def parse_remaining_arguments(arguments)
|
@@ -67,9 +69,6 @@ module Mutant
|
|
67
69
|
# rubocop:disable Metrics/MethodLength
|
68
70
|
def add_environment_options(parser)
|
69
71
|
parser.separator('Environment:')
|
70
|
-
parser.on('--zombie', 'Run mutant zombified') do
|
71
|
-
set(zombie: true)
|
72
|
-
end
|
73
72
|
parser.on('-I', '--include DIRECTORY', 'Add DIRECTORY to $LOAD_PATH') do |directory|
|
74
73
|
add(:includes, directory)
|
75
74
|
end
|
data/lib/mutant/cli/command.rb
CHANGED
@@ -4,9 +4,7 @@ module Mutant
|
|
4
4
|
module CLI
|
5
5
|
# rubocop:disable Metrics/ClassLength
|
6
6
|
class Command
|
7
|
-
include AbstractType, Anima.new(:world, :main, :parent, :
|
8
|
-
|
9
|
-
include Equalizer.new(:parent, :arguments)
|
7
|
+
include AbstractType, Anima.new(:world, :main, :parent, :zombie)
|
10
8
|
|
11
9
|
OPTIONS = [].freeze
|
12
10
|
SUBCOMMANDS = [].freeze
|
@@ -18,21 +16,20 @@ module Mutant
|
|
18
16
|
define_method(:add_officious) {}
|
19
17
|
end # OptionParser
|
20
18
|
|
21
|
-
class FailParse < self
|
22
|
-
include Concord.new(:world, :message)
|
23
|
-
|
24
|
-
def call
|
25
|
-
world.stderr.puts(message)
|
26
|
-
false
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
19
|
# Parse command
|
31
20
|
#
|
32
21
|
# @return [Command]
|
33
|
-
|
34
|
-
|
22
|
+
#
|
23
|
+
# rubocop:disable Metrics/ParameterLists
|
24
|
+
def self.parse(arguments:, parent: nil, world:, zombie: false)
|
25
|
+
new(
|
26
|
+
main: nil,
|
27
|
+
parent: parent,
|
28
|
+
world: world,
|
29
|
+
zombie: zombie
|
30
|
+
).__send__(:parse, arguments)
|
35
31
|
end
|
32
|
+
# rubocop:enable Metrics/ParameterLists
|
36
33
|
|
37
34
|
# Command name
|
38
35
|
#
|
@@ -62,12 +59,7 @@ module Mutant
|
|
62
59
|
[*parent&.full_name, self.class.command_name].join(' ')
|
63
60
|
end
|
64
61
|
|
65
|
-
|
66
|
-
#
|
67
|
-
# @return [Bool]
|
68
|
-
def zombie?
|
69
|
-
false
|
70
|
-
end
|
62
|
+
alias_method :zombie?, :zombie
|
71
63
|
|
72
64
|
abstract_method :action
|
73
65
|
|
@@ -116,7 +108,7 @@ module Mutant
|
|
116
108
|
end
|
117
109
|
end
|
118
110
|
|
119
|
-
def parse
|
111
|
+
def parse(arguments)
|
120
112
|
Either
|
121
113
|
.wrap_error(OptionParser::InvalidOption) { parser.order(arguments) }
|
122
114
|
.lmap(&method(:with_help))
|
@@ -129,6 +121,7 @@ module Mutant
|
|
129
121
|
parser.separator(nil)
|
130
122
|
end
|
131
123
|
|
124
|
+
# rubocop:disable Metrics/MethodLength
|
132
125
|
def add_global_options(parser)
|
133
126
|
parser.separator("mutant version: #{VERSION}")
|
134
127
|
parser.separator(nil)
|
@@ -142,6 +135,10 @@ module Mutant
|
|
142
135
|
parser.on('--version', 'Print mutants version') do
|
143
136
|
capture_main { world.stdout.puts("mutant-#{VERSION}"); true }
|
144
137
|
end
|
138
|
+
|
139
|
+
parser.on('--zombie', 'Run mutant zombified') do
|
140
|
+
@zombie = true
|
141
|
+
end
|
145
142
|
end
|
146
143
|
|
147
144
|
def add_subcommands(parser)
|
@@ -178,7 +175,12 @@ module Mutant
|
|
178
175
|
Either::Left.new(with_help('Missing required subcommand!'))
|
179
176
|
else
|
180
177
|
find_command(command_name).bind do |command|
|
181
|
-
command.parse(
|
178
|
+
command.parse(
|
179
|
+
arguments: arguments,
|
180
|
+
parent: self,
|
181
|
+
world: world,
|
182
|
+
zombie: zombie
|
183
|
+
)
|
182
184
|
end
|
183
185
|
end
|
184
186
|
end
|
data/lib/mutant/cli.rb
CHANGED
@@ -6,10 +6,8 @@ module Mutant
|
|
6
6
|
# Parse command
|
7
7
|
#
|
8
8
|
# @return [Command]
|
9
|
-
def self.parse(
|
10
|
-
Command::Root
|
11
|
-
.parse(world: world, **attributes)
|
12
|
-
.from_right { |message| Command::FailParse.new(world, message) }
|
9
|
+
def self.parse(arguments:, world:)
|
10
|
+
Command::Root.parse(arguments: arguments, world: world)
|
13
11
|
end
|
14
12
|
end # CLI
|
15
13
|
end # Mutant
|
data/lib/mutant/config.rb
CHANGED
@@ -21,11 +21,10 @@ module Mutant
|
|
21
21
|
:matcher,
|
22
22
|
:mutation,
|
23
23
|
:reporter,
|
24
|
-
:requires
|
25
|
-
:zombie
|
24
|
+
:requires
|
26
25
|
)
|
27
26
|
|
28
|
-
%i[fail_fast
|
27
|
+
%i[fail_fast].each do |name|
|
29
28
|
define_method(:"#{name}?") { public_send(name) }
|
30
29
|
end
|
31
30
|
|
@@ -42,7 +41,7 @@ module Mutant
|
|
42
41
|
MUTATION_TIMEOUT_DEPRECATION = <<~'MESSAGE'
|
43
42
|
Deprecated configuration toplevel key `mutation_timeout` found.
|
44
43
|
|
45
|
-
This key will be removed in the next
|
44
|
+
This key will be removed in the next major version.
|
46
45
|
Instead place your mutation timeout configuration under the `mutation` key
|
47
46
|
like this:
|
48
47
|
|
@@ -74,8 +73,7 @@ module Mutant
|
|
74
73
|
jobs: other.jobs || jobs,
|
75
74
|
matcher: matcher.merge(other.matcher),
|
76
75
|
mutation: mutation.merge(other.mutation),
|
77
|
-
requires: requires + other.requires
|
78
|
-
zombie: zombie || other.zombie
|
76
|
+
requires: requires + other.requires
|
79
77
|
)
|
80
78
|
end
|
81
79
|
# rubocop:enable Metrics/AbcSize
|
@@ -100,16 +98,6 @@ module Mutant
|
|
100
98
|
end
|
101
99
|
end
|
102
100
|
|
103
|
-
# Expand config with defaults
|
104
|
-
#
|
105
|
-
# @return [Config]
|
106
|
-
def expand_defaults
|
107
|
-
with(
|
108
|
-
coverage_criteria: CoverageCriteria::DEFAULT.merge(coverage_criteria),
|
109
|
-
jobs: jobs || 1
|
110
|
-
)
|
111
|
-
end
|
112
|
-
|
113
101
|
def self.load_contents(env, path)
|
114
102
|
Transform::Named
|
115
103
|
.new(
|
@@ -30,8 +30,9 @@ module Mutant
|
|
30
30
|
|
31
31
|
# Instance method specific evaluator
|
32
32
|
class Evaluator < Evaluator
|
33
|
-
|
34
|
-
NAME_INDEX
|
33
|
+
MATCH_NODE_TYPE = :def
|
34
|
+
NAME_INDEX = 0
|
35
|
+
SUBJECT_CLASS = Subject::Method::Instance
|
35
36
|
|
36
37
|
private
|
37
38
|
|
@@ -22,10 +22,11 @@ module Mutant
|
|
22
22
|
# Metaclass method evaluator
|
23
23
|
class Evaluator < Evaluator
|
24
24
|
# Terminology note: the "receiver" is the `self` in `class << self`
|
25
|
-
SUBJECT_CLASS = Subject::Method::Metaclass
|
26
|
-
NAME_INDEX = 0
|
27
25
|
CONST_NAME_INDEX = 1
|
26
|
+
MATCH_NODE_TYPE = :def
|
27
|
+
NAME_INDEX = 0
|
28
28
|
SCLASS_RECEIVER_INDEX = 0
|
29
|
+
SUBJECT_CLASS = Subject::Method::Metaclass
|
29
30
|
RECEIVER_WARNING = 'Can only match :def inside :sclass on ' \
|
30
31
|
':self or :const, got :sclass on %p ' \
|
31
32
|
'unable to match'
|
@@ -45,7 +46,7 @@ module Mutant
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def metaclass_containing(node)
|
48
|
-
AST::FindMetaclassContaining.call(ast
|
49
|
+
AST::FindMetaclassContaining.call(ast, node)
|
49
50
|
end
|
50
51
|
|
51
52
|
def line?(node)
|
@@ -18,10 +18,11 @@ module Mutant
|
|
18
18
|
|
19
19
|
# Singleton method evaluator
|
20
20
|
class Evaluator < Evaluator
|
21
|
-
|
22
|
-
RECEIVER_INDEX = 0
|
21
|
+
MATCH_NODE_TYPE = :defs
|
23
22
|
NAME_INDEX = 1
|
23
|
+
RECEIVER_INDEX = 0
|
24
24
|
RECEIVER_WARNING = 'Can only match :defs on :self or :const got %p unable to match'
|
25
|
+
SUBJECT_CLASS = Subject::Method::Singleton
|
25
26
|
|
26
27
|
private
|
27
28
|
|
@@ -41,23 +41,38 @@ module Mutant
|
|
41
41
|
#
|
42
42
|
# @return [Enumerable<Subject>]
|
43
43
|
def call
|
44
|
-
|
44
|
+
location = source_location
|
45
|
+
|
46
|
+
if location.nil? || !location.first.end_with?('.rb')
|
47
|
+
env.warn(SOURCE_LOCATION_WARNING_FORMAT % target_method)
|
45
48
|
|
46
|
-
|
49
|
+
return EMPTY_ARRAY
|
50
|
+
end
|
51
|
+
|
52
|
+
match_view
|
47
53
|
end
|
48
54
|
|
49
55
|
private
|
50
56
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
file = location&.first
|
57
|
+
def match_view
|
58
|
+
return EMPTY_ARRAY if matched_view.nil?
|
55
59
|
|
56
|
-
if
|
57
|
-
env.warn(SOURCE_LOCATION_WARNING_FORMAT % target_method)
|
58
|
-
elsif matched_node_path.any?(&method(:n_block?))
|
60
|
+
if matched_view.path.any?(&:block.public_method(:equal?))
|
59
61
|
env.warn(CLOSURE_WARNING_FORMAT % target_method)
|
62
|
+
|
63
|
+
return EMPTY_ARRAY
|
60
64
|
end
|
65
|
+
|
66
|
+
[subject]
|
67
|
+
end
|
68
|
+
|
69
|
+
def subject
|
70
|
+
self.class::SUBJECT_CLASS.new(
|
71
|
+
config: subject_config(matched_view.node),
|
72
|
+
context: context,
|
73
|
+
node: matched_view.node,
|
74
|
+
visibility: visibility
|
75
|
+
)
|
61
76
|
end
|
62
77
|
|
63
78
|
def method_name
|
@@ -95,17 +110,6 @@ module Mutant
|
|
95
110
|
T::Private::Methods.signature_for_method(target_method)
|
96
111
|
end
|
97
112
|
|
98
|
-
def subject
|
99
|
-
node = matched_node_path.last || return
|
100
|
-
|
101
|
-
self.class::SUBJECT_CLASS.new(
|
102
|
-
config: subject_config(node),
|
103
|
-
context: context,
|
104
|
-
node: node,
|
105
|
-
visibility: visibility
|
106
|
-
)
|
107
|
-
end
|
108
|
-
|
109
113
|
def subject_config(node)
|
110
114
|
Subject::Config.parse(
|
111
115
|
comments: ast.comment_associations.fetch(node, []),
|
@@ -113,10 +117,15 @@ module Mutant
|
|
113
117
|
)
|
114
118
|
end
|
115
119
|
|
116
|
-
def
|
117
|
-
|
120
|
+
def matched_view
|
121
|
+
return if source_location.nil?
|
122
|
+
|
123
|
+
ast
|
124
|
+
.on_line(source_line)
|
125
|
+
.select { |view| view.node.type.eql?(self.class::MATCH_NODE_TYPE) && match?(view.node) }
|
126
|
+
.last
|
118
127
|
end
|
119
|
-
memoize :
|
128
|
+
memoize :matched_view
|
120
129
|
|
121
130
|
def visibility
|
122
131
|
# This can be cleaned up once we are on >ruby-3.0
|
@@ -38,9 +38,11 @@ module Mutant
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def body_has_control?
|
41
|
-
AST.
|
42
|
-
n_break?(node) || n_next?(node)
|
43
|
-
end
|
41
|
+
AST::Structure.for(body.type).each_node(body) do |node|
|
42
|
+
return true if n_break?(node) || n_next?(node)
|
43
|
+
end
|
44
|
+
|
45
|
+
false
|
44
46
|
end
|
45
47
|
|
46
48
|
def mutate_body_receiver
|
@@ -14,9 +14,10 @@ module Mutant
|
|
14
14
|
emit_body(N_RAISE)
|
15
15
|
emit_body(N_ZSUPER)
|
16
16
|
|
17
|
-
return
|
17
|
+
return if !body || ignore?(body)
|
18
|
+
|
19
|
+
emit_body(nil) unless n_begin?(body) && body.children.any?(&method(:ignore?))
|
18
20
|
|
19
|
-
emit_body(nil) unless body.children.any?(&method(:ignore?))
|
20
21
|
emit_body_mutations
|
21
22
|
end
|
22
23
|
|
data/lib/mutant/parser.rb
CHANGED
data/lib/mutant/version.rb
CHANGED
data/lib/mutant.rb
CHANGED
@@ -273,7 +273,7 @@ module Mutant
|
|
273
273
|
# Reopen class to initialize constant to avoid dep circle
|
274
274
|
class Config
|
275
275
|
DEFAULT = new(
|
276
|
-
coverage_criteria: Config::CoverageCriteria::
|
276
|
+
coverage_criteria: Config::CoverageCriteria::DEFAULT,
|
277
277
|
expression_parser: Expression::Parser.new([
|
278
278
|
Expression::Descendants,
|
279
279
|
Expression::Method,
|
@@ -291,8 +291,7 @@ module Mutant
|
|
291
291
|
matcher: Matcher::Config::DEFAULT,
|
292
292
|
mutation: Mutation::Config::DEFAULT,
|
293
293
|
reporter: Reporter::CLI.build(WORLD.stdout),
|
294
|
-
requires: EMPTY_ARRAY
|
295
|
-
zombie: false
|
294
|
+
requires: EMPTY_ARRAY
|
296
295
|
)
|
297
296
|
end # Config
|
298
297
|
|
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.16
|
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-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|