mutant 0.12.4 → 0.13.0
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/lib/mutant/cli/command/util.rb +18 -5
- data/lib/mutant/loader.rb +2 -2
- data/lib/mutant/matcher/method/instance.rb +5 -1
- data/lib/mutant/meta/example/verification.rb +32 -17
- data/lib/mutant/meta/example.rb +5 -5
- data/lib/mutant/mutation.rb +59 -13
- data/lib/mutant/mutator/node/and_asgn.rb +1 -4
- data/lib/mutant/mutator/node/argument.rb +1 -15
- data/lib/mutant/mutator/node/arguments.rb +0 -21
- data/lib/mutant/mutator/node/begin.rb +38 -3
- data/lib/mutant/mutator/node/binary.rb +6 -7
- data/lib/mutant/mutator/node/block.rb +12 -1
- data/lib/mutant/mutator/node/if.rb +1 -4
- data/lib/mutant/mutator/node/index.rb +0 -1
- data/lib/mutant/mutator/node/masgn.rb +3 -4
- data/lib/mutant/mutator/node/mlhs.rb +1 -5
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -11
- data/lib/mutant/mutator/node/op_asgn.rb +0 -3
- data/lib/mutant/mutator/node/resbody.rb +0 -1
- data/lib/mutant/mutator/node/rescue.rb +4 -2
- data/lib/mutant/mutator/node/send.rb +2 -1
- data/lib/mutant/parser.rb +3 -3
- data/lib/mutant/procto.rb +2 -2
- data/lib/mutant/subject.rb +13 -3
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +2 -2
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82b061b05d127f9e8c610effc797e56f102504f0494b908c3e0e6e8bfbb468aa
|
4
|
+
data.tar.gz: ff8e61e682146e74e9853f2580faed2cac0750333e2bb26a9fffe98ace2fec1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a07d644733195d80aea841e88b111f3d7223a22305ab996f5187a362d90db65fab77049bc10b371222e03b7d6c21cf9ea88ba4fe6ac6268ec75726314e74606
|
7
|
+
data.tar.gz: 9a5bcdccede3f23359e35129a436d6eab770f146651024a5a4198dd2df9a97087b22b9c010b5f2a2f3d3c53db5e1844854b7005668cc1969d138c23f77545b5a
|
@@ -20,8 +20,11 @@ module Mutant
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
@targets.
|
24
|
-
|
23
|
+
if @targets.map(&method(:print_mutations)).all?
|
24
|
+
Either::Right.new(nil)
|
25
|
+
else
|
26
|
+
Either::Left.new('Invalid mutation detected!')
|
27
|
+
end
|
25
28
|
end
|
26
29
|
|
27
30
|
private
|
@@ -70,18 +73,28 @@ module Mutant
|
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
76
|
+
# rubocop:disable Metrics/MethodLength
|
73
77
|
def print_mutations(target)
|
74
78
|
world.stdout.puts(target.identification)
|
75
79
|
|
80
|
+
success = true
|
81
|
+
|
76
82
|
Mutator::Node.mutate(
|
77
83
|
config: Mutant::Mutation::Config::DEFAULT.with(ignore_patterns: @ignore_patterns),
|
78
84
|
node: target.node
|
79
85
|
).each do |mutation|
|
80
|
-
|
81
|
-
|
82
|
-
|
86
|
+
Mutant::Mutation::Evil.from_node(subject: target, node: mutation).either(
|
87
|
+
->(violation) { world.stdout.puts(violation.report); success = false },
|
88
|
+
lambda { |object|
|
89
|
+
Reporter::CLI::Printer::Mutation.call(
|
90
|
+
object:,
|
91
|
+
output: world.stdout
|
92
|
+
)
|
93
|
+
}
|
83
94
|
)
|
84
95
|
end
|
96
|
+
|
97
|
+
success
|
85
98
|
end
|
86
99
|
|
87
100
|
def parse_remaining_arguments(arguments)
|
data/lib/mutant/loader.rb
CHANGED
@@ -30,8 +30,12 @@ module Mutant
|
|
30
30
|
end
|
31
31
|
# rubocop:enable Metrics/MethodLength
|
32
32
|
|
33
|
+
TARGET_MEMOIZER = ::Mutant::Adamantium
|
34
|
+
|
35
|
+
private_constant(*constants(false))
|
36
|
+
|
33
37
|
def self.memoized_method?(scope, method_name)
|
34
|
-
scope.raw <
|
38
|
+
scope.raw < TARGET_MEMOIZER && scope.raw.memoized?(method_name)
|
35
39
|
end
|
36
40
|
private_class_method :memoized_method?
|
37
41
|
|
@@ -2,20 +2,31 @@
|
|
2
2
|
|
3
3
|
module Mutant
|
4
4
|
module Meta
|
5
|
+
# rubocop:disable Metrics/ClassLength
|
5
6
|
class Example
|
6
7
|
# Example verification
|
7
8
|
class Verification
|
8
|
-
include Adamantium, Anima.new(:example, :
|
9
|
+
include Adamantium, Anima.new(:example, :invalid, :valid)
|
10
|
+
|
11
|
+
def self.from_mutations(example:, mutations:)
|
12
|
+
valid, invalid = [], []
|
13
|
+
|
14
|
+
mutations.each do |mutation|
|
15
|
+
mutation.either(invalid.public_method(:<<), valid.public_method(:<<))
|
16
|
+
end
|
17
|
+
|
18
|
+
new(example:, invalid:, valid:)
|
19
|
+
end
|
9
20
|
|
10
21
|
# Test if mutation was verified successfully
|
11
22
|
#
|
12
23
|
# @return [Boolean]
|
13
24
|
def success?
|
14
25
|
[
|
15
|
-
|
16
|
-
invalid,
|
26
|
+
invalid_report,
|
17
27
|
missing,
|
18
28
|
no_diffs,
|
29
|
+
original_verification_report,
|
19
30
|
unexpected
|
20
31
|
].all?(&:empty?)
|
21
32
|
end
|
@@ -29,12 +40,12 @@ module Mutant
|
|
29
40
|
|
30
41
|
def reports
|
31
42
|
reports = [example.location]
|
32
|
-
reports.concat(
|
33
|
-
reports.concat(
|
43
|
+
reports.concat(original_report)
|
44
|
+
reports.concat(original_verification_report)
|
34
45
|
reports.concat(make_report('Missing mutations:', missing))
|
35
46
|
reports.concat(make_report('Unexpected mutations:', unexpected))
|
36
47
|
reports.concat(make_report('No-Diff mutations:', no_diffs))
|
37
|
-
reports.concat(
|
48
|
+
reports.concat(invalid_report)
|
38
49
|
end
|
39
50
|
|
40
51
|
def make_report(label, mutations)
|
@@ -52,7 +63,7 @@ module Mutant
|
|
52
63
|
]
|
53
64
|
end
|
54
65
|
|
55
|
-
def
|
66
|
+
def original_report
|
56
67
|
[
|
57
68
|
"Original: (operators: #{example.operators.class.operators_name})",
|
58
69
|
example.node,
|
@@ -60,7 +71,7 @@ module Mutant
|
|
60
71
|
]
|
61
72
|
end
|
62
73
|
|
63
|
-
def
|
74
|
+
def original_verification_report
|
64
75
|
validation = Unparser::Validation.from_string(example.original_source)
|
65
76
|
if validation.success?
|
66
77
|
[]
|
@@ -77,30 +88,34 @@ module Mutant
|
|
77
88
|
end.join
|
78
89
|
end
|
79
90
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
aggregate << prefix('[invalid-mutation]', validation.report) unless validation.success?
|
91
|
+
def invalid_report
|
92
|
+
invalid.map do |validation|
|
93
|
+
prefix('[invalid-mutation]', validation.report)
|
84
94
|
end
|
85
95
|
end
|
86
|
-
memoize :
|
96
|
+
memoize :invalid_report
|
87
97
|
|
88
98
|
def unexpected
|
89
|
-
|
99
|
+
valid.reject do |mutation|
|
90
100
|
example.expected.any? { |expected| expected.node.eql?(mutation.node) }
|
91
101
|
end
|
92
102
|
end
|
93
103
|
memoize :unexpected
|
94
104
|
|
95
105
|
def missing
|
96
|
-
|
97
|
-
|
106
|
+
example.expected.each_with_object([]) do |expected, aggregate|
|
107
|
+
next if valid.any? { |mutation| expected.node.eql?(mutation.node) }
|
108
|
+
aggregate << Mutation::Evil.new(
|
109
|
+
node: expected.node,
|
110
|
+
source: expected.original_source,
|
111
|
+
subject: example
|
112
|
+
)
|
98
113
|
end
|
99
114
|
end
|
100
115
|
memoize :missing
|
101
116
|
|
102
117
|
def no_diffs
|
103
|
-
|
118
|
+
valid.select { |mutation| mutation.source.eql?(example.source) }
|
104
119
|
end
|
105
120
|
memoize :no_diffs
|
106
121
|
|
data/lib/mutant/meta/example.rb
CHANGED
@@ -23,7 +23,7 @@ module Mutant
|
|
23
23
|
#
|
24
24
|
# @return [Verification]
|
25
25
|
def verification
|
26
|
-
Verification.
|
26
|
+
Verification.from_mutations(example: self, mutations: generated)
|
27
27
|
end
|
28
28
|
memoize :verification
|
29
29
|
|
@@ -45,13 +45,13 @@ module Mutant
|
|
45
45
|
)
|
46
46
|
end
|
47
47
|
|
48
|
-
# Original source
|
48
|
+
# Original source
|
49
49
|
#
|
50
50
|
# @return [String]
|
51
|
-
def
|
51
|
+
def source
|
52
52
|
Unparser.unparse(node)
|
53
53
|
end
|
54
|
-
memoize :
|
54
|
+
memoize :source
|
55
55
|
|
56
56
|
# Generated mutations on example source
|
57
57
|
#
|
@@ -61,7 +61,7 @@ module Mutant
|
|
61
61
|
config: Mutation::Config::DEFAULT.with(operators:),
|
62
62
|
node:
|
63
63
|
).map do |node|
|
64
|
-
Mutation::Evil.
|
64
|
+
Mutation::Evil.from_node(subject: self, node:)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
memoize :generated
|
data/lib/mutant/mutation.rb
CHANGED
@@ -4,11 +4,69 @@ module Mutant
|
|
4
4
|
# Represent a mutated node with its subject
|
5
5
|
class Mutation
|
6
6
|
include AbstractType, Adamantium
|
7
|
-
include Anima.new(:subject, :node)
|
7
|
+
include Anima.new(:subject, :node, :source)
|
8
8
|
|
9
9
|
CODE_DELIMITER = "\0"
|
10
10
|
CODE_RANGE = (..4)
|
11
11
|
|
12
|
+
class GenerationError
|
13
|
+
include Anima.new(:subject, :node, :unparser_validation)
|
14
|
+
|
15
|
+
MESSAGE = <<~'MESSAGE'
|
16
|
+
=== Mutation-Generation-Error ===
|
17
|
+
This is a mutant internal issue detected by a mutant internal cross check.
|
18
|
+
Please report an issue with the details below.
|
19
|
+
|
20
|
+
Subject: %<subject_identification>s.
|
21
|
+
|
22
|
+
Mutation-Source-Diff:
|
23
|
+
%<mutation_source_diff>s
|
24
|
+
|
25
|
+
Mutation-Node-Diff:
|
26
|
+
%<mutation_node_diff>s
|
27
|
+
|
28
|
+
Unparser-Validation:
|
29
|
+
%<unparser_validation>s
|
30
|
+
MESSAGE
|
31
|
+
|
32
|
+
def report
|
33
|
+
MESSAGE % {
|
34
|
+
mutation_source_diff:,
|
35
|
+
mutation_node_diff:,
|
36
|
+
subject_identification: subject.identification,
|
37
|
+
unparser_validation: unparser_validation.report
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def mutation_source_diff
|
44
|
+
mutation = Evil.new(
|
45
|
+
subject:,
|
46
|
+
node: nil,
|
47
|
+
source: unparser_validation.original_source.from_right
|
48
|
+
)
|
49
|
+
|
50
|
+
mutation.diff.colorized_diff
|
51
|
+
end
|
52
|
+
|
53
|
+
def mutation_node_diff
|
54
|
+
Unparser::Diff.new(
|
55
|
+
subject.node.to_s.lines,
|
56
|
+
node.to_s.lines
|
57
|
+
).colorized_diff
|
58
|
+
end
|
59
|
+
end # GenerationError
|
60
|
+
|
61
|
+
def self.from_node(subject:, node:)
|
62
|
+
ast = Unparser::AST.from_node(node:)
|
63
|
+
|
64
|
+
Unparser
|
65
|
+
.unparse_validate_ast_either(ast:)
|
66
|
+
.lmap { |unparser_validation| GenerationError.new(subject:, node:, unparser_validation:) }
|
67
|
+
.fmap { |source| new(node:, source:, subject:) }
|
68
|
+
end
|
69
|
+
|
12
70
|
# Mutation identification code
|
13
71
|
#
|
14
72
|
# @return [String]
|
@@ -17,14 +75,6 @@ module Mutant
|
|
17
75
|
end
|
18
76
|
memoize :code
|
19
77
|
|
20
|
-
# Normalized mutation source
|
21
|
-
#
|
22
|
-
# @return [String]
|
23
|
-
def source
|
24
|
-
Unparser.unparse(node)
|
25
|
-
end
|
26
|
-
memoize :source
|
27
|
-
|
28
78
|
# Identification string
|
29
79
|
#
|
30
80
|
# @return [String]
|
@@ -75,10 +125,6 @@ module Mutant
|
|
75
125
|
end
|
76
126
|
end
|
77
127
|
|
78
|
-
# Rendered mutation diff
|
79
|
-
#
|
80
|
-
# @return [String, nil]
|
81
|
-
# the diff, if present
|
82
128
|
def diff
|
83
129
|
Unparser::Diff.build(original_source, source)
|
84
130
|
end
|
@@ -8,24 +8,11 @@ module Mutant
|
|
8
8
|
class Argument < self
|
9
9
|
handle(:arg, :kwarg)
|
10
10
|
|
11
|
-
UNDERSCORE = '_'
|
12
|
-
|
13
11
|
children :name
|
14
12
|
|
15
13
|
private
|
16
14
|
|
17
|
-
def dispatch
|
18
|
-
emit_name_mutation
|
19
|
-
end
|
20
|
-
|
21
|
-
def emit_name_mutation
|
22
|
-
return if skip?
|
23
|
-
emit_name(:"#{UNDERSCORE}#{name}")
|
24
|
-
end
|
25
|
-
|
26
|
-
def skip?
|
27
|
-
name.start_with?(UNDERSCORE)
|
28
|
-
end
|
15
|
+
def dispatch; end
|
29
16
|
|
30
17
|
# Mutator for optional arguments
|
31
18
|
class Optional < self
|
@@ -42,7 +29,6 @@ module Mutant
|
|
42
29
|
private
|
43
30
|
|
44
31
|
def dispatch
|
45
|
-
emit_name_mutation
|
46
32
|
emit_required_mutation
|
47
33
|
emit_default_mutations
|
48
34
|
end
|
@@ -13,36 +13,15 @@ module Mutant
|
|
13
13
|
private
|
14
14
|
|
15
15
|
def dispatch
|
16
|
-
emit_argument_presence
|
17
16
|
emit_argument_mutations
|
18
17
|
emit_mlhs_expansion
|
19
18
|
emit_procarg0_removal
|
20
19
|
end
|
21
20
|
|
22
|
-
def emit_argument_presence
|
23
|
-
emit_type unless removed_block_arg?(EMPTY_ARRAY) || forward_arg?
|
24
|
-
|
25
|
-
children.each_with_index do |removed, index|
|
26
|
-
new_arguments = children.dup
|
27
|
-
new_arguments.delete_at(index)
|
28
|
-
unless forward_type?(removed) || removed_block_arg?(new_arguments) || only_mlhs?(new_arguments)
|
29
|
-
emit_type(*new_arguments)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
21
|
def forward_type?(removed)
|
35
22
|
n_forward_arg?(removed) || n_restarg?(removed) || n_kwrestarg?(removed)
|
36
23
|
end
|
37
24
|
|
38
|
-
def only_mlhs?(new_arguments)
|
39
|
-
new_arguments.one? && n_mlhs?(new_arguments.first)
|
40
|
-
end
|
41
|
-
|
42
|
-
def forward_arg?
|
43
|
-
children.any?(&method(:forward_type?))
|
44
|
-
end
|
45
|
-
|
46
25
|
def removed_block_arg?(new_arguments)
|
47
26
|
anonymous_block_arg? && new_arguments.none?(&ANONYMOUS_BLOCKARG_PRED)
|
48
27
|
end
|
@@ -12,9 +12,44 @@ module Mutant
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def dispatch
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
children.each_index do |index|
|
16
|
+
mutate_child(index)
|
17
|
+
delete_child(index)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# rubocop:disable Lint/EmptyWhen
|
22
|
+
# rubocop:disable Metrics/MethodLength
|
23
|
+
def delete_child(index)
|
24
|
+
dup_children = children.dup
|
25
|
+
child = dup_children.delete_at(index)
|
26
|
+
return if contains_lvar_assignment?(child)
|
27
|
+
return if ignore?(child)
|
28
|
+
|
29
|
+
case dup_children.length
|
30
|
+
when 0
|
31
|
+
when 1
|
32
|
+
one = Mutant::Util.one(dup_children)
|
33
|
+
return if ignore?(one)
|
34
|
+
emit(one)
|
35
|
+
else
|
36
|
+
emit_type(*dup_children)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def contains_lvar_assignment?(node)
|
41
|
+
case node.type
|
42
|
+
when Unparser::AST::ASSIGN_NODES
|
43
|
+
true
|
44
|
+
when *Unparser::AST::RESET_NODES
|
45
|
+
false
|
46
|
+
else
|
47
|
+
node.children.each do |child|
|
48
|
+
if child.instance_of?(::Parser::AST::Node) && contains_lvar_assignment?(child)
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
false
|
18
53
|
end
|
19
54
|
end
|
20
55
|
end # Begin
|
@@ -18,9 +18,8 @@ module Mutant
|
|
18
18
|
private
|
19
19
|
|
20
20
|
def dispatch
|
21
|
-
emit_singletons
|
21
|
+
emit_singletons unless left_lvasgn?
|
22
22
|
emit_promotions
|
23
|
-
emit_operator_mutations
|
24
23
|
|
25
24
|
emit_left_mutations do |mutation|
|
26
25
|
!(n_irange?(mutation) || n_erange?(mutation)) || !mutation.children.fetch(1).nil?
|
@@ -29,13 +28,13 @@ module Mutant
|
|
29
28
|
emit_right_mutations
|
30
29
|
end
|
31
30
|
|
32
|
-
def emit_operator_mutations
|
33
|
-
emit(s(INVERSE.fetch(node.type), left, right))
|
34
|
-
end
|
35
|
-
|
36
31
|
def emit_promotions
|
37
32
|
emit(left)
|
38
|
-
emit(right)
|
33
|
+
emit(right) unless left_lvasgn?
|
34
|
+
end
|
35
|
+
|
36
|
+
def left_lvasgn?
|
37
|
+
n_lvasgn?(left)
|
39
38
|
end
|
40
39
|
|
41
40
|
end # Binary
|
@@ -25,7 +25,9 @@ module Mutant
|
|
25
25
|
emit_body(N_RAISE)
|
26
26
|
|
27
27
|
return unless body
|
28
|
-
|
28
|
+
|
29
|
+
emit_body_promotion
|
30
|
+
|
29
31
|
emit_body_mutations do |node|
|
30
32
|
!(n_nil?(node) && unconditional_loop?)
|
31
33
|
end
|
@@ -45,8 +47,17 @@ module Mutant
|
|
45
47
|
false
|
46
48
|
end
|
47
49
|
|
50
|
+
def emit_body_promotion
|
51
|
+
emit(body) if empty_block_argument? && !body_has_control?
|
52
|
+
end
|
53
|
+
|
54
|
+
def empty_block_argument?
|
55
|
+
arguments.children.empty?
|
56
|
+
end
|
57
|
+
|
48
58
|
def mutate_body_receiver
|
49
59
|
return if n_lambda?(send) || !n_send?(body)
|
60
|
+
return unless empty_block_argument?
|
50
61
|
|
51
62
|
body_meta = AST::Meta::Send.new(node: body)
|
52
63
|
|
@@ -21,10 +21,7 @@ module Mutant
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def mutate_condition
|
24
|
-
emit_condition_mutations
|
25
|
-
!n_self?(node)
|
26
|
-
end
|
27
|
-
emit_type(n_not(condition), if_branch, else_branch) unless n_match_current_line?(condition)
|
24
|
+
emit_condition_mutations
|
28
25
|
emit_type(N_TRUE, if_branch, else_branch)
|
29
26
|
emit_type(N_FALSE, if_branch, else_branch)
|
30
27
|
end
|
@@ -3,9 +3,8 @@
|
|
3
3
|
module Mutant
|
4
4
|
class Mutator
|
5
5
|
class Node
|
6
|
-
|
7
6
|
# Mutation emitter to handle multiple assignment nodes
|
8
|
-
class
|
7
|
+
class Masgn < self
|
9
8
|
|
10
9
|
handle(:masgn)
|
11
10
|
|
@@ -14,10 +13,10 @@ module Mutant
|
|
14
13
|
private
|
15
14
|
|
16
15
|
def dispatch
|
17
|
-
|
16
|
+
emit_right_mutations
|
18
17
|
end
|
19
18
|
|
20
|
-
end #
|
19
|
+
end # Masgn
|
21
20
|
end # Node
|
22
21
|
end # Mutator
|
23
22
|
end # Mutant
|
@@ -26,19 +26,8 @@ module Mutant
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def dispatch
|
29
|
-
emit_singletons
|
30
|
-
mutate_name
|
31
29
|
emit_value_mutations if value # op asgn!
|
32
30
|
end
|
33
|
-
|
34
|
-
def mutate_name
|
35
|
-
prefix, regexp = MAP.fetch(node.type)
|
36
|
-
stripped = name.to_s.sub(regexp, EMPTY_STRING)
|
37
|
-
|
38
|
-
Util::Symbol.call(input: stripped, parent: nil).each do |name|
|
39
|
-
emit_name(:"#{prefix}#{name}")
|
40
|
-
end
|
41
|
-
end
|
42
31
|
end # VariableAssignment
|
43
32
|
end # NamedValue
|
44
33
|
end # Node
|
@@ -14,8 +14,6 @@ module Mutant
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def dispatch
|
17
|
-
emit_singletons
|
18
|
-
|
19
17
|
left_mutations
|
20
18
|
|
21
19
|
emit_right_mutations
|
@@ -25,7 +23,6 @@ module Mutant
|
|
25
23
|
emit_left_mutations do |node|
|
26
24
|
!n_self?(node)
|
27
25
|
end
|
28
|
-
|
29
26
|
emit_left_promotion if n_send?(left)
|
30
27
|
end
|
31
28
|
|
@@ -25,8 +25,10 @@ module Mutant
|
|
25
25
|
def mutate_rescue_bodies
|
26
26
|
children_indices(RESCUE_INDICES).each do |index|
|
27
27
|
mutate_child(index)
|
28
|
-
|
29
|
-
|
28
|
+
resbody = AST::Meta::Resbody.new(node: children.fetch(index))
|
29
|
+
if resbody.body && !resbody.assignment
|
30
|
+
emit_concat(resbody.body)
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -206,7 +206,8 @@ module Mutant
|
|
206
206
|
emit(receiver) if receiver && !left_op_assignment?
|
207
207
|
end
|
208
208
|
|
209
|
-
# rubocop:disable Style/HashEachMethods
|
209
|
+
# rubocop:disable Style/HashEachMethods
|
210
|
+
# - its not a hash ;)
|
210
211
|
def mutate_arguments
|
211
212
|
emit_type(receiver, selector)
|
212
213
|
remaining_children_with_index.each do |_node, index|
|
data/lib/mutant/parser.rb
CHANGED
@@ -24,11 +24,11 @@ module Mutant
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def parse(source)
|
27
|
-
|
27
|
+
ast = Unparser.parse_ast_either(source).from_right
|
28
28
|
|
29
29
|
AST.new(
|
30
|
-
node
|
31
|
-
|
30
|
+
comment_associations: ::Parser::Source::Comment.associate_by_identity(ast.node, ast.comments),
|
31
|
+
node: ast.node
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
data/lib/mutant/procto.rb
CHANGED
data/lib/mutant/subject.rb
CHANGED
@@ -10,13 +10,21 @@ module Mutant
|
|
10
10
|
#
|
11
11
|
# @return [Enumerable<Mutation>]
|
12
12
|
# @return [undefined]
|
13
|
+
#
|
14
|
+
# mutant:disable
|
15
|
+
# rubocop:disable Metrics/MethodLength
|
13
16
|
def mutations
|
14
17
|
[neutral_mutation].concat(
|
15
18
|
Mutator::Node.mutate(
|
16
19
|
config: config.mutation,
|
17
20
|
node:
|
18
|
-
).
|
19
|
-
Mutation::Evil
|
21
|
+
).each_with_object([]) do |mutant, aggregate|
|
22
|
+
Mutation::Evil
|
23
|
+
.from_node(subject: self, node: wrap_node(mutant))
|
24
|
+
.either(
|
25
|
+
->(validation) {},
|
26
|
+
aggregate.public_method(:<<)
|
27
|
+
)
|
20
28
|
end
|
21
29
|
)
|
22
30
|
end
|
@@ -92,7 +100,9 @@ module Mutant
|
|
92
100
|
private
|
93
101
|
|
94
102
|
def neutral_mutation
|
95
|
-
Mutation::Neutral
|
103
|
+
Mutation::Neutral
|
104
|
+
.from_node(subject: self, node: wrap_node(node))
|
105
|
+
.from_right
|
96
106
|
end
|
97
107
|
|
98
108
|
def wrap_node(node)
|
data/lib/mutant/version.rb
CHANGED
data/lib/mutant/zombifier.rb
CHANGED
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.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diff-lcs
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 0.7.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 0.7.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -355,14 +355,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
355
355
|
requirements:
|
356
356
|
- - ">="
|
357
357
|
- !ruby/object:Gem::Version
|
358
|
-
version: '3.
|
358
|
+
version: '3.2'
|
359
359
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
360
360
|
requirements:
|
361
361
|
- - ">="
|
362
362
|
- !ruby/object:Gem::Version
|
363
363
|
version: '0'
|
364
364
|
requirements: []
|
365
|
-
rubygems_version: 3.5.
|
365
|
+
rubygems_version: 3.5.22
|
366
366
|
signing_key:
|
367
367
|
specification_version: 4
|
368
368
|
summary: ''
|