mutant 0.11.18 → 0.11.19
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/ast/find_metaclass_containing.rb +1 -1
- 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 +3 -3
- data/lib/mutant/ast/meta/symbol.rb +1 -1
- data/lib/mutant/ast/types.rb +2 -1311
- data/lib/mutant/bootstrap.rb +2 -2
- data/lib/mutant/cli/command/environment/run.rb +1 -1
- data/lib/mutant/cli/command/environment.rb +1 -3
- data/lib/mutant/cli/command/util.rb +6 -6
- data/lib/mutant/config/coverage_criteria.rb +13 -4
- data/lib/mutant/config.rb +51 -24
- data/lib/mutant/context.rb +1 -6
- data/lib/mutant/env.rb +1 -1
- data/lib/mutant/expression/method.rb +6 -3
- data/lib/mutant/expression/methods.rb +2 -2
- data/lib/mutant/expression/namespace.rb +2 -2
- data/lib/mutant/expression/parser.rb +1 -1
- data/lib/mutant/hooks.rb +4 -4
- data/lib/mutant/isolation/fork.rb +1 -1
- data/lib/mutant/license/subscription/commercial.rb +3 -3
- data/lib/mutant/license/subscription/opensource.rb +5 -9
- data/lib/mutant/license/subscription.rb +1 -1
- data/lib/mutant/matcher/chain.rb +1 -1
- data/lib/mutant/matcher/config.rb +10 -4
- data/lib/mutant/matcher/descendants.rb +1 -1
- data/lib/mutant/matcher/filter.rb +1 -1
- data/lib/mutant/matcher/method/instance.rb +9 -4
- data/lib/mutant/matcher/method/metaclass.rb +4 -17
- data/lib/mutant/matcher/method/singleton.rb +3 -13
- data/lib/mutant/matcher/method.rb +4 -4
- data/lib/mutant/matcher/methods.rb +4 -2
- data/lib/mutant/matcher/namespace.rb +2 -2
- data/lib/mutant/matcher/scope.rb +3 -3
- data/lib/mutant/matcher/static.rb +1 -1
- data/lib/mutant/matcher.rb +2 -2
- data/lib/mutant/meta/example/verification.rb +2 -2
- data/lib/mutant/meta/example.rb +4 -4
- data/lib/mutant/mutation/config.rb +10 -4
- data/lib/mutant/mutation/runner/sink.rb +80 -0
- data/lib/mutant/mutation/runner.rb +61 -0
- data/lib/mutant/mutation.rb +1 -1
- data/lib/mutant/mutator/node/block.rb +2 -2
- data/lib/mutant/mutator/node/define.rb +1 -1
- data/lib/mutant/mutator/node/if.rb +9 -0
- data/lib/mutant/mutator/node/rescue.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +4 -4
- data/lib/mutant/mutator/regexp.rb +2 -2
- data/lib/mutant/parallel/source.rb +1 -1
- data/lib/mutant/pipe.rb +3 -3
- data/lib/mutant/registry.rb +2 -2
- data/lib/mutant/reporter/cli/format.rb +3 -3
- data/lib/mutant/reporter/cli/printer.rb +2 -2
- data/lib/mutant/reporter/cli.rb +4 -4
- data/lib/mutant/reporter/sequence.rb +1 -1
- data/lib/mutant/repository.rb +1 -1
- data/lib/mutant/result.rb +1 -1
- data/lib/mutant/scope.rb +1 -1
- data/lib/mutant/selector/expression.rb +1 -1
- data/lib/mutant/subject.rb +2 -2
- data/lib/mutant/timer.rb +3 -3
- data/lib/mutant/transform.rb +14 -14
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant.rb +13 -11
- metadata +9 -9
- data/lib/mutant/runner/sink.rb +0 -78
- data/lib/mutant/runner.rb +0 -60
data/lib/mutant/bootstrap.rb
CHANGED
@@ -51,7 +51,7 @@ module Mutant
|
|
51
51
|
env.with(
|
52
52
|
integration: integration,
|
53
53
|
mutations: mutations,
|
54
|
-
selector: Selector::Expression.new(integration),
|
54
|
+
selector: Selector::Expression.new(integration: integration),
|
55
55
|
subjects: selected_subjects
|
56
56
|
)
|
57
57
|
end
|
@@ -115,7 +115,7 @@ module Mutant
|
|
115
115
|
|
116
116
|
scopes = env.world.object_space.each_object(Module).with_object([]) do |scope, aggregate|
|
117
117
|
expression = expression(config.reporter, config.expression_parser, scope) || next
|
118
|
-
aggregate << Scope.new(scope, expression)
|
118
|
+
aggregate << Scope.new(raw: scope, expression: expression)
|
119
119
|
end
|
120
120
|
|
121
121
|
scopes.sort_by { |scope| scope.expression.syntax }
|
@@ -105,9 +105,7 @@ module Mutant
|
|
105
105
|
parser.on('--since REVISION', 'Only select subjects touched since REVISION') do |revision|
|
106
106
|
add_matcher(
|
107
107
|
:subject_filters,
|
108
|
-
Repository::SubjectFilter.new(
|
109
|
-
Repository::Diff.new(to: revision, world: world)
|
110
|
-
)
|
108
|
+
Repository::SubjectFilter.new(diff: Repository::Diff.new(to: revision, world: world))
|
111
109
|
)
|
112
110
|
end
|
113
111
|
end
|
@@ -35,7 +35,7 @@ module Mutant
|
|
35
35
|
memoize :node
|
36
36
|
|
37
37
|
class File < self
|
38
|
-
include
|
38
|
+
include Anima.new(:pathname, :source)
|
39
39
|
|
40
40
|
public :source
|
41
41
|
|
@@ -45,7 +45,7 @@ module Mutant
|
|
45
45
|
end # File
|
46
46
|
|
47
47
|
class Source < self
|
48
|
-
include
|
48
|
+
include Anima.new(:source)
|
49
49
|
|
50
50
|
def identification
|
51
51
|
'<cli-source>'
|
@@ -62,7 +62,7 @@ module Mutant
|
|
62
62
|
|
63
63
|
def add_target_options(parser)
|
64
64
|
parser.on('-e', '--evaluate SOURCE') do |source|
|
65
|
-
@targets << Target::Source.new(source)
|
65
|
+
@targets << Target::Source.new(source: source)
|
66
66
|
end
|
67
67
|
|
68
68
|
parser.on('-i', '--ignore-pattern AST_PATTERN') do |pattern|
|
@@ -78,8 +78,8 @@ module Mutant
|
|
78
78
|
node: target.node
|
79
79
|
).each do |mutation|
|
80
80
|
Reporter::CLI::Printer::Mutation.call(
|
81
|
-
|
82
|
-
|
81
|
+
object: Mutant::Mutation::Evil.new(subject: target, node: mutation),
|
82
|
+
output: world.stdout
|
83
83
|
)
|
84
84
|
end
|
85
85
|
end
|
@@ -97,7 +97,7 @@ module Mutant
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def read_file(pathname)
|
100
|
-
Either::Right.new(Target::File.new(pathname, pathname.read))
|
100
|
+
Either::Right.new(Target::File.new(pathname: pathname, source: pathname.read))
|
101
101
|
rescue StandardError => exception
|
102
102
|
Either::Left.new("Cannot read file: #{exception}")
|
103
103
|
end
|
@@ -20,12 +20,21 @@ module Mutant
|
|
20
20
|
|
21
21
|
TRANSFORM =
|
22
22
|
Transform::Sequence.new(
|
23
|
-
[
|
23
|
+
steps: [
|
24
24
|
Transform::Hash.new(
|
25
25
|
optional: [
|
26
|
-
Transform::Hash::Key.new(
|
27
|
-
|
28
|
-
|
26
|
+
Transform::Hash::Key.new(
|
27
|
+
transform: Transform::BOOLEAN,
|
28
|
+
value: 'process_abort'
|
29
|
+
),
|
30
|
+
Transform::Hash::Key.new(
|
31
|
+
transform: Transform::BOOLEAN,
|
32
|
+
value: 'test_result'
|
33
|
+
),
|
34
|
+
Transform::Hash::Key.new(
|
35
|
+
transform: Transform::BOOLEAN,
|
36
|
+
value: 'timeout'
|
37
|
+
)
|
29
38
|
],
|
30
39
|
required: []
|
31
40
|
),
|
data/lib/mutant/config.rb
CHANGED
@@ -101,8 +101,8 @@ module Mutant
|
|
101
101
|
def self.load_contents(env, path)
|
102
102
|
Transform::Named
|
103
103
|
.new(
|
104
|
-
path.to_s,
|
105
|
-
sequence(env.config.reporter)
|
104
|
+
name: path.to_s,
|
105
|
+
transform: sequence(env.config.reporter)
|
106
106
|
)
|
107
107
|
.call(path)
|
108
108
|
.lmap(&:compact_message)
|
@@ -111,11 +111,11 @@ module Mutant
|
|
111
111
|
|
112
112
|
def self.sequence(reporter)
|
113
113
|
Transform::Sequence.new(
|
114
|
-
[
|
115
|
-
Transform::Exception.new(SystemCallError, :read.to_proc),
|
116
|
-
Transform::Exception.new(YAML::SyntaxError, YAML.public_method(:safe_load)),
|
117
|
-
Transform::Primitive.new(Hash),
|
118
|
-
Transform::Success.new(->(hash) { deprecations(reporter, hash) }),
|
114
|
+
steps: [
|
115
|
+
Transform::Exception.new(error_class: SystemCallError, block: :read.to_proc),
|
116
|
+
Transform::Exception.new(error_class: YAML::SyntaxError, block: YAML.public_method(:safe_load)),
|
117
|
+
Transform::Primitive.new(primitive: Hash),
|
118
|
+
Transform::Success.new(block: ->(hash) { deprecations(reporter, hash) }),
|
119
119
|
*TRANSFORMS
|
120
120
|
]
|
121
121
|
)
|
@@ -130,10 +130,10 @@ module Mutant
|
|
130
130
|
end
|
131
131
|
|
132
132
|
PATHNAME_ARRAY = Transform::Array.new(
|
133
|
-
Transform::Sequence.new(
|
134
|
-
[
|
133
|
+
transform: Transform::Sequence.new(
|
134
|
+
steps: [
|
135
135
|
Transform::STRING,
|
136
|
-
Transform::Exception.new(ArgumentError, Pathname.public_method(:new))
|
136
|
+
Transform::Exception.new(error_class: ArgumentError, block: Pathname.public_method(:new))
|
137
137
|
]
|
138
138
|
)
|
139
139
|
)
|
@@ -170,24 +170,51 @@ module Mutant
|
|
170
170
|
TRANSFORMS = [
|
171
171
|
Transform::Hash.new(
|
172
172
|
optional: [
|
173
|
-
Transform::Hash::Key.new('coverage_criteria', ->(value) { CoverageCriteria::TRANSFORM.call(value) }),
|
174
173
|
Transform::Hash::Key.new(
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
174
|
+
transform: ->(value) { CoverageCriteria::TRANSFORM.call(value) },
|
175
|
+
value: 'coverage_criteria'
|
176
|
+
),
|
177
|
+
Transform::Hash::Key.new(
|
178
|
+
transform: Transform::Sequence.new(
|
179
|
+
steps: [
|
180
|
+
Transform::Primitive.new(primitive: Hash),
|
179
181
|
Transform::Block.capture(:environment_variables, &method(:parse_environment_variables))
|
180
182
|
]
|
181
|
-
)
|
183
|
+
),
|
184
|
+
value: 'environment_variables'
|
185
|
+
),
|
186
|
+
Transform::Hash::Key.new(
|
187
|
+
transform: Transform::BOOLEAN,
|
188
|
+
value: 'fail_fast'
|
189
|
+
),
|
190
|
+
Transform::Hash::Key.new(
|
191
|
+
transform: PATHNAME_ARRAY,
|
192
|
+
value: 'hooks'
|
193
|
+
),
|
194
|
+
Transform::Hash::Key.new(
|
195
|
+
transform: Transform::STRING_ARRAY,
|
196
|
+
value: 'includes'
|
182
197
|
),
|
183
|
-
Transform::Hash::Key.new(
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
Transform::Hash::Key.new(
|
188
|
-
|
189
|
-
|
190
|
-
|
198
|
+
Transform::Hash::Key.new(
|
199
|
+
transform: Transform::STRING,
|
200
|
+
value: 'integration'
|
201
|
+
),
|
202
|
+
Transform::Hash::Key.new(
|
203
|
+
transform: Transform::INTEGER,
|
204
|
+
value: 'jobs'
|
205
|
+
),
|
206
|
+
Transform::Hash::Key.new(
|
207
|
+
transform: Matcher::Config::LOADER,
|
208
|
+
value: 'matcher'
|
209
|
+
),
|
210
|
+
Transform::Hash::Key.new(
|
211
|
+
transform: Mutation::Config::TRANSFORM,
|
212
|
+
value: 'mutation'
|
213
|
+
),
|
214
|
+
Transform::Hash::Key.new(
|
215
|
+
transform: Transform::STRING_ARRAY,
|
216
|
+
value: 'requires'
|
217
|
+
)
|
191
218
|
],
|
192
219
|
required: []
|
193
220
|
),
|
data/lib/mutant/context.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Mutant
|
4
4
|
# An abstract context where mutations can be applied to.
|
5
5
|
class Context
|
6
|
-
include Adamantium,
|
6
|
+
include Adamantium, Anima.new(:scope, :source_path)
|
7
7
|
extend AST::Sexp
|
8
8
|
|
9
9
|
NAMESPACE_DELIMITER = '::'
|
@@ -74,11 +74,6 @@ module Mutant
|
|
74
74
|
end
|
75
75
|
memoize :match_expressions
|
76
76
|
|
77
|
-
# Scope wrapped by context
|
78
|
-
#
|
79
|
-
# @return [Module|Class]
|
80
|
-
attr_reader :scope
|
81
|
-
|
82
77
|
private
|
83
78
|
|
84
79
|
def name_nesting
|
data/lib/mutant/env.rb
CHANGED
@@ -41,11 +41,14 @@ module Mutant
|
|
41
41
|
# @return [Matcher]
|
42
42
|
def matcher
|
43
43
|
matcher_candidates = MATCHERS.fetch(scope_symbol)
|
44
|
-
.map { |submatcher| submatcher.new(scope) }
|
44
|
+
.map { |submatcher| submatcher.new(scope: scope) }
|
45
45
|
|
46
|
-
methods_matcher = Matcher::Chain.new(matcher_candidates)
|
46
|
+
methods_matcher = Matcher::Chain.new(matchers: matcher_candidates)
|
47
47
|
|
48
|
-
Matcher::Filter.new(
|
48
|
+
Matcher::Filter.new(
|
49
|
+
matcher: methods_matcher,
|
50
|
+
predicate: ->(subject) { subject.expression.eql?(self) }
|
51
|
+
)
|
49
52
|
end
|
50
53
|
|
51
54
|
def self.try_parse(input)
|
@@ -36,9 +36,9 @@ module Mutant
|
|
36
36
|
# @return [Matcher::Method]
|
37
37
|
def matcher
|
38
38
|
matcher_candidates = MATCHERS.fetch(scope_symbol)
|
39
|
-
.map { |submatcher| submatcher.new(scope) }
|
39
|
+
.map { |submatcher| submatcher.new(scope: scope) }
|
40
40
|
|
41
|
-
Matcher::Chain.new(matcher_candidates)
|
41
|
+
Matcher::Chain.new(matchers: matcher_candidates)
|
42
42
|
end
|
43
43
|
|
44
44
|
# Length of match with other expression
|
@@ -35,7 +35,7 @@ module Mutant
|
|
35
35
|
#
|
36
36
|
# @return [Matcher]
|
37
37
|
def matcher
|
38
|
-
Matcher::Namespace.new(self)
|
38
|
+
Matcher::Namespace.new(expression: self)
|
39
39
|
end
|
40
40
|
|
41
41
|
# Length of match with other expression
|
@@ -69,7 +69,7 @@ module Mutant
|
|
69
69
|
scope = find_scope
|
70
70
|
|
71
71
|
if scope
|
72
|
-
Matcher::Scope.new(scope)
|
72
|
+
Matcher::Scope.new(scope: scope)
|
73
73
|
else
|
74
74
|
Matcher::Null.new
|
75
75
|
end
|
data/lib/mutant/hooks.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Mutant
|
4
4
|
class Hooks
|
5
|
-
include Adamantium,
|
5
|
+
include Adamantium, Anima.new(:map)
|
6
6
|
|
7
7
|
DEFAULTS = %i[
|
8
8
|
env_infection_pre
|
@@ -23,12 +23,12 @@ module Mutant
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.empty
|
26
|
-
new(DEFAULTS)
|
26
|
+
new(map: DEFAULTS)
|
27
27
|
end
|
28
28
|
|
29
29
|
def merge(other)
|
30
30
|
self.class.new(
|
31
|
-
other.map.merge(map) { |_key, new, old| (old + new).freeze }.freeze
|
31
|
+
map: other.map.merge(map) { |_key, new, old| (old + new).freeze }.freeze
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
@@ -54,7 +54,7 @@ module Mutant
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def to_hooks
|
57
|
-
Hooks.new(@map.transform_values(&:freeze).freeze)
|
57
|
+
Hooks.new(map: @map.transform_values(&:freeze).freeze)
|
58
58
|
end
|
59
59
|
end # Builder
|
60
60
|
|
@@ -5,14 +5,14 @@ module Mutant
|
|
5
5
|
class Subscription
|
6
6
|
class Commercial < self
|
7
7
|
class Author
|
8
|
-
include
|
8
|
+
include Anima.new(:email)
|
9
9
|
|
10
10
|
alias_method :to_s, :email
|
11
11
|
public :to_s
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.from_json(value)
|
15
|
-
new(value.fetch('authors').
|
15
|
+
new(licensed: value.fetch('authors').to_set { |email| Author.new(email: email) })
|
16
16
|
end
|
17
17
|
|
18
18
|
def call(world)
|
@@ -43,7 +43,7 @@ module Mutant
|
|
43
43
|
world
|
44
44
|
.capture_stdout(command)
|
45
45
|
.fmap(&:chomp)
|
46
|
-
.fmap
|
46
|
+
.fmap { |email| Author.new(email: email) }
|
47
47
|
.fmap { |value| Set.new([value]) }
|
48
48
|
.from_right { Set.new }
|
49
49
|
end
|
@@ -5,7 +5,7 @@ module Mutant
|
|
5
5
|
class Subscription
|
6
6
|
class Opensource < self
|
7
7
|
class Repository
|
8
|
-
include
|
8
|
+
include Anima.new(:host, :path)
|
9
9
|
|
10
10
|
REMOTE_REGEXP = /\A[^\t]+\t(?<url>[^ ]+) \((?:fetch|push)\)\n\z/.freeze
|
11
11
|
GIT_SSH_REGEXP = %r{\A[^@]+@(?<host>[^:/]+)[:/](?<path>.+?)(?:\.git)?\z}.freeze
|
@@ -18,7 +18,8 @@ module Mutant
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.parse(input)
|
21
|
-
|
21
|
+
host, path = *input.split('/', 2).map(&:downcase)
|
22
|
+
new(host: host, path: path)
|
22
23
|
end
|
23
24
|
|
24
25
|
def self.parse_remote(input)
|
@@ -36,7 +37,7 @@ module Mutant
|
|
36
37
|
fail "Unmatched git remote URL: #{input.inspect}"
|
37
38
|
end
|
38
39
|
|
39
|
-
new(match[:host], match[:path].downcase)
|
40
|
+
new(host: match[:host], path: match[:path].downcase)
|
40
41
|
end
|
41
42
|
private_class_method :parse_url
|
42
43
|
|
@@ -52,12 +53,7 @@ module Mutant
|
|
52
53
|
end # Opensource
|
53
54
|
|
54
55
|
def self.from_json(value)
|
55
|
-
new(
|
56
|
-
value
|
57
|
-
.fetch('repositories')
|
58
|
-
.map(&Repository.public_method(:parse))
|
59
|
-
.to_set
|
60
|
-
)
|
56
|
+
new(licensed: value.fetch('repositories').map(&Repository.public_method(:parse)).to_set)
|
61
57
|
end
|
62
58
|
|
63
59
|
def call(world)
|
data/lib/mutant/matcher/chain.rb
CHANGED
@@ -31,15 +31,21 @@ module Mutant
|
|
31
31
|
Mutant::Config::DEFAULT.expression_parser.call(input)
|
32
32
|
end
|
33
33
|
|
34
|
-
expression_array = Transform::Array.new(expression)
|
34
|
+
expression_array = Transform::Array.new(transform: expression)
|
35
35
|
|
36
36
|
LOADER =
|
37
37
|
Transform::Sequence.new(
|
38
|
-
[
|
38
|
+
steps: [
|
39
39
|
Transform::Hash.new(
|
40
40
|
optional: [
|
41
|
-
Transform::Hash::Key.new(
|
42
|
-
|
41
|
+
Transform::Hash::Key.new(
|
42
|
+
transform: expression_array,
|
43
|
+
value: 'subjects'
|
44
|
+
),
|
45
|
+
Transform::Hash::Key.new(
|
46
|
+
transform: expression_array,
|
47
|
+
value: 'ignore'
|
48
|
+
)
|
43
49
|
],
|
44
50
|
required: []
|
45
51
|
),
|
@@ -10,7 +10,7 @@ module Mutant
|
|
10
10
|
const = env.world.try_const_get(const_name) or return EMPTY_ARRAY
|
11
11
|
|
12
12
|
Chain.new(
|
13
|
-
matched_scopes(env, const).map { |scope| Scope.new(scope.raw) }
|
13
|
+
matchers: matched_scopes(env, const).map { |scope| Scope.new(scope: scope.raw) }
|
14
14
|
).call(env)
|
15
15
|
end
|
16
16
|
|
@@ -12,7 +12,9 @@ module Mutant
|
|
12
12
|
# @param [UnboundMethod] method
|
13
13
|
#
|
14
14
|
# @return [Matcher::Method::Instance]
|
15
|
-
|
15
|
+
#
|
16
|
+
# rubocop:disable Metrics/MethodLength
|
17
|
+
def self.new(scope:, target_method:)
|
16
18
|
evaluator =
|
17
19
|
if memoized_method?(scope, target_method.name)
|
18
20
|
Evaluator::Memoized
|
@@ -20,8 +22,13 @@ module Mutant
|
|
20
22
|
Evaluator
|
21
23
|
end
|
22
24
|
|
23
|
-
super(
|
25
|
+
super(
|
26
|
+
evaluator: evaluator,
|
27
|
+
scope: scope,
|
28
|
+
target_method: target_method
|
29
|
+
)
|
24
30
|
end
|
31
|
+
# rubocop:enable Metrics/MethodLength
|
25
32
|
|
26
33
|
def self.memoized_method?(scope, method_name)
|
27
34
|
scope < Adamantium && scope.memoized?(method_name)
|
@@ -37,8 +44,6 @@ module Mutant
|
|
37
44
|
private
|
38
45
|
|
39
46
|
def match?(node)
|
40
|
-
n_def?(node) &&
|
41
|
-
node.location.line.equal?(source_line) &&
|
42
47
|
node.children.fetch(NAME_INDEX).equal?(method_name)
|
43
48
|
end
|
44
49
|
|
@@ -11,12 +11,9 @@ module Mutant
|
|
11
11
|
|
12
12
|
# New singleton method matcher
|
13
13
|
#
|
14
|
-
# @param [Class, Module] scope
|
15
|
-
# @param [Symbol] method_name
|
16
|
-
#
|
17
14
|
# @return [Matcher::Method::Singleton]
|
18
|
-
def self.new(scope
|
19
|
-
super(scope,
|
15
|
+
def self.new(scope:, target_method:)
|
16
|
+
super(scope: scope, target_method: target_method, evaluator: Evaluator)
|
20
17
|
end
|
21
18
|
|
22
19
|
# Metaclass method evaluator
|
@@ -34,10 +31,7 @@ module Mutant
|
|
34
31
|
private
|
35
32
|
|
36
33
|
def match?(node)
|
37
|
-
|
38
|
-
name?(node) &&
|
39
|
-
line?(node) &&
|
40
|
-
metaclass_receiver?(node)
|
34
|
+
name?(node) && metaclass_receiver?(node)
|
41
35
|
end
|
42
36
|
|
43
37
|
def metaclass_receiver?(node)
|
@@ -46,14 +40,7 @@ module Mutant
|
|
46
40
|
end
|
47
41
|
|
48
42
|
def metaclass_containing(node)
|
49
|
-
AST::FindMetaclassContaining.call(ast, node)
|
50
|
-
end
|
51
|
-
|
52
|
-
def line?(node)
|
53
|
-
node
|
54
|
-
.location
|
55
|
-
.line
|
56
|
-
.equal?(source_line)
|
43
|
+
AST::FindMetaclassContaining.call(ast: ast, target: node)
|
57
44
|
end
|
58
45
|
|
59
46
|
def name?(node)
|
@@ -8,12 +8,9 @@ module Mutant
|
|
8
8
|
|
9
9
|
# New singleton method matcher
|
10
10
|
#
|
11
|
-
# @param [Class, Module] scope
|
12
|
-
# @param [Symbol] method_name
|
13
|
-
#
|
14
11
|
# @return [Matcher::Method::Singleton]
|
15
|
-
def self.new(scope
|
16
|
-
super(scope,
|
12
|
+
def self.new(scope:, target_method:)
|
13
|
+
super(scope: scope, target_method: target_method, evaluator: Evaluator)
|
17
14
|
end
|
18
15
|
|
19
16
|
# Singleton method evaluator
|
@@ -27,14 +24,7 @@ module Mutant
|
|
27
24
|
private
|
28
25
|
|
29
26
|
def match?(node)
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def line?(node)
|
34
|
-
node
|
35
|
-
.location
|
36
|
-
.line
|
37
|
-
.equal?(source_line)
|
27
|
+
name?(node) && receiver?(node)
|
38
28
|
end
|
39
29
|
|
40
30
|
def name?(node)
|
@@ -6,7 +6,7 @@ module Mutant
|
|
6
6
|
class Method < self
|
7
7
|
include AbstractType,
|
8
8
|
Adamantium,
|
9
|
-
|
9
|
+
Anima.new(:scope, :target_method, :evaluator)
|
10
10
|
|
11
11
|
SOURCE_LOCATION_WARNING_FORMAT =
|
12
12
|
'%s does not have a valid source location, unable to emit subject'
|
@@ -20,7 +20,7 @@ module Mutant
|
|
20
20
|
#
|
21
21
|
# @return [Enumerable<Subject>]
|
22
22
|
def call(env)
|
23
|
-
evaluator.call(scope, target_method, env)
|
23
|
+
evaluator.call(scope: scope, target_method: target_method, env: env)
|
24
24
|
end
|
25
25
|
|
26
26
|
# Abstract method match evaluator
|
@@ -32,7 +32,7 @@ module Mutant
|
|
32
32
|
include(
|
33
33
|
AbstractType,
|
34
34
|
Adamantium,
|
35
|
-
|
35
|
+
Anima.new(:scope, :target_method, :env),
|
36
36
|
Procto,
|
37
37
|
AST::NodePredicates
|
38
38
|
)
|
@@ -80,7 +80,7 @@ module Mutant
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def context
|
83
|
-
Context.new(scope, source_path)
|
83
|
+
Context.new(scope: scope, source_path: source_path)
|
84
84
|
end
|
85
85
|
|
86
86
|
def ast
|
@@ -4,7 +4,7 @@ module Mutant
|
|
4
4
|
class Matcher
|
5
5
|
# Abstract base class for matcher that returns method subjects from scope
|
6
6
|
class Methods < self
|
7
|
-
include AbstractType,
|
7
|
+
include AbstractType, Anima.new(:scope)
|
8
8
|
|
9
9
|
CANDIDATE_NAMES = %i[
|
10
10
|
public_instance_methods
|
@@ -21,7 +21,9 @@ module Mutant
|
|
21
21
|
# @return [Enumerable<Subject>]
|
22
22
|
def call(env)
|
23
23
|
Chain.new(
|
24
|
-
methods(env).map
|
24
|
+
matchers: methods(env).map do |target_method|
|
25
|
+
matcher.new(scope: scope, target_method: target_method)
|
26
|
+
end
|
25
27
|
).call(env)
|
26
28
|
end
|
27
29
|
|