mutant 0.11.12 → 0.11.15
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 +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/license/subscription/opensource.rb +12 -2
- 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/mutator/node/block.rb +5 -3
- data/lib/mutant/parser.rb +0 -7
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant.rb +2 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f0fc5ddcee197485af9a005a41938eb5c056fe7112747e1ed5cefd7860e0d27
|
4
|
+
data.tar.gz: eed2005705a2ff4a58c18390d7f59cf4eff85aa67b6c3846cb44b014e9f3fba9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff9b7d961960b339405eda6b0bf16bbcc7ad0527d52787f7fe402c0689afea3f0e344697af9a87e5331c766b8002ccc03c34b517f47b3edea385948336889634
|
7
|
+
data.tar.gz: bfe080deae82a8b5aae5a281515344ecfd526e8fafc1350727608b989404cf34c821fedd42e1e8c04b8bca744a28d0ad66f2d273871cc044197556eec8ebad48
|
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(
|
@@ -39,7 +39,17 @@ module Mutant
|
|
39
39
|
new(match[:host], match[:path].downcase)
|
40
40
|
end
|
41
41
|
private_class_method :parse_url
|
42
|
-
|
42
|
+
|
43
|
+
def allow?(other)
|
44
|
+
other.host.eql?(host) && path_match?(other.path)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def path_match?(other_path)
|
50
|
+
path.eql?(other_path) || (path.end_with?('/*') && other_path.start_with?(path[..-2]))
|
51
|
+
end
|
52
|
+
end # Opensource
|
43
53
|
|
44
54
|
def self.from_json(value)
|
45
55
|
new(
|
@@ -60,7 +70,7 @@ module Mutant
|
|
60
70
|
private
|
61
71
|
|
62
72
|
def check_subscription(actual)
|
63
|
-
if
|
73
|
+
if licensed.any? { |repository| actual.any? { |other| repository.allow?(other) } }
|
64
74
|
success
|
65
75
|
else
|
66
76
|
failure(licensed, actual)
|
@@ -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
|
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.15
|
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-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|
@@ -393,7 +393,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
393
393
|
- !ruby/object:Gem::Version
|
394
394
|
version: '0'
|
395
395
|
requirements: []
|
396
|
-
rubygems_version: 3.
|
396
|
+
rubygems_version: 3.3.7
|
397
397
|
signing_key:
|
398
398
|
specification_version: 4
|
399
399
|
summary: ''
|