mutant 0.8.0 → 0.8.1
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/Changelog.md +7 -0
- data/config/flay.yml +1 -1
- data/config/reek.yml +1 -0
- data/lib/mutant.rb +10 -3
- data/lib/mutant/actor.rb +2 -5
- data/lib/mutant/actor/env.rb +1 -3
- data/lib/mutant/actor/mailbox.rb +2 -4
- data/lib/mutant/actor/receiver.rb +0 -2
- data/lib/mutant/actor/sender.rb +0 -1
- data/lib/mutant/ast.rb +22 -28
- data/lib/mutant/ast/meta.rb +8 -88
- data/lib/mutant/ast/named_children.rb +1 -8
- data/lib/mutant/ast/sexp.rb +0 -2
- data/lib/mutant/cache.rb +1 -3
- data/lib/mutant/cli.rb +9 -19
- data/lib/mutant/color.rb +0 -3
- data/lib/mutant/config.rb +6 -2
- data/lib/mutant/context.rb +2 -4
- data/lib/mutant/context/scope.rb +10 -16
- data/lib/mutant/delegator.rb +0 -3
- data/lib/mutant/diff.rb +8 -17
- data/lib/mutant/env.rb +3 -5
- data/lib/mutant/env/bootstrap.rb +32 -39
- data/lib/mutant/expression.rb +14 -132
- data/lib/mutant/expression/method.rb +25 -42
- data/lib/mutant/expression/methods.rb +17 -29
- data/lib/mutant/expression/namespace.rb +33 -28
- data/lib/mutant/expression/parser.rb +71 -0
- data/lib/mutant/integration.rb +17 -16
- data/lib/mutant/isolation.rb +14 -14
- data/lib/mutant/loader.rb +2 -4
- data/lib/mutant/matcher.rb +1 -11
- data/lib/mutant/matcher/chain.rb +0 -1
- data/lib/mutant/matcher/compiler.rb +19 -52
- data/lib/mutant/matcher/config.rb +65 -5
- data/lib/mutant/matcher/filter.rb +11 -1
- data/lib/mutant/matcher/method.rb +11 -21
- data/lib/mutant/matcher/method/instance.rb +2 -16
- data/lib/mutant/matcher/method/singleton.rb +3 -20
- data/lib/mutant/matcher/methods.rb +11 -21
- data/lib/mutant/matcher/namespace.rb +0 -4
- data/lib/mutant/matcher/null.rb +0 -1
- data/lib/mutant/matcher/scope.rb +0 -12
- data/lib/mutant/meta.rb +0 -1
- data/lib/mutant/meta/example.rb +12 -26
- data/lib/mutant/meta/example/dsl.rb +1 -8
- data/lib/mutant/mutation.rb +6 -14
- data/lib/mutant/mutator.rb +2 -14
- data/lib/mutant/mutator/node.rb +6 -33
- data/lib/mutant/mutator/node/and_asgn.rb +0 -1
- data/lib/mutant/mutator/node/argument.rb +0 -5
- data/lib/mutant/mutator/node/arguments.rb +1 -7
- data/lib/mutant/mutator/node/begin.rb +0 -2
- data/lib/mutant/mutator/node/binary.rb +0 -3
- data/lib/mutant/mutator/node/block.rb +0 -2
- data/lib/mutant/mutator/node/break.rb +0 -1
- data/lib/mutant/mutator/node/case.rb +0 -3
- data/lib/mutant/mutator/node/conditional_loop.rb +0 -1
- data/lib/mutant/mutator/node/const.rb +0 -1
- data/lib/mutant/mutator/node/define.rb +0 -1
- data/lib/mutant/mutator/node/defined.rb +0 -1
- data/lib/mutant/mutator/node/dstr.rb +0 -1
- data/lib/mutant/mutator/node/dsym.rb +0 -1
- data/lib/mutant/mutator/node/generic.rb +0 -1
- data/lib/mutant/mutator/node/if.rb +0 -4
- data/lib/mutant/mutator/node/kwbegin.rb +0 -1
- data/lib/mutant/mutator/node/literal/array.rb +0 -2
- data/lib/mutant/mutator/node/literal/boolean.rb +0 -1
- data/lib/mutant/mutator/node/literal/fixnum.rb +2 -5
- data/lib/mutant/mutator/node/literal/float.rb +1 -4
- data/lib/mutant/mutator/node/literal/hash.rb +0 -3
- data/lib/mutant/mutator/node/literal/nil.rb +0 -1
- data/lib/mutant/mutator/node/literal/range.rb +1 -5
- data/lib/mutant/mutator/node/literal/regex.rb +1 -3
- data/lib/mutant/mutator/node/literal/string.rb +0 -1
- data/lib/mutant/mutator/node/literal/symbol.rb +0 -1
- data/lib/mutant/mutator/node/masgn.rb +0 -1
- data/lib/mutant/mutator/node/match_current_line.rb +0 -1
- data/lib/mutant/mutator/node/mlhs.rb +0 -1
- data/lib/mutant/mutator/node/named_value/access.rb +0 -1
- data/lib/mutant/mutator/node/named_value/constant_assignment.rb +0 -2
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +0 -2
- data/lib/mutant/mutator/node/next.rb +0 -1
- data/lib/mutant/mutator/node/noop.rb +0 -1
- data/lib/mutant/mutator/node/nthref.rb +0 -1
- data/lib/mutant/mutator/node/op_asgn.rb +0 -1
- data/lib/mutant/mutator/node/or_asgn.rb +1 -2
- data/lib/mutant/mutator/node/resbody.rb +0 -2
- data/lib/mutant/mutator/node/rescue.rb +1 -6
- data/lib/mutant/mutator/node/return.rb +0 -1
- data/lib/mutant/mutator/node/send.rb +16 -17
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +0 -3
- data/lib/mutant/mutator/node/send/binary.rb +0 -1
- data/lib/mutant/mutator/node/send/index.rb +0 -3
- data/lib/mutant/mutator/node/splat.rb +0 -1
- data/lib/mutant/mutator/node/super.rb +0 -1
- data/lib/mutant/mutator/node/when.rb +2 -7
- data/lib/mutant/mutator/node/yield.rb +0 -1
- data/lib/mutant/mutator/node/zsuper.rb +0 -1
- data/lib/mutant/mutator/registry.rb +1 -4
- data/lib/mutant/mutator/util.rb +0 -2
- data/lib/mutant/mutator/util/array.rb +0 -3
- data/lib/mutant/mutator/util/symbol.rb +0 -1
- data/lib/mutant/parallel.rb +3 -9
- data/lib/mutant/parallel/master.rb +7 -17
- data/lib/mutant/parallel/source.rb +2 -7
- data/lib/mutant/parallel/worker.rb +1 -5
- data/lib/mutant/reporter.rb +0 -4
- data/lib/mutant/reporter/cli.rb +1 -8
- data/lib/mutant/reporter/cli/format.rb +7 -18
- data/lib/mutant/reporter/cli/printer.rb +2 -12
- data/lib/mutant/reporter/cli/printer/config.rb +1 -4
- data/lib/mutant/reporter/cli/printer/env_progress.rb +3 -7
- data/lib/mutant/reporter/cli/printer/env_result.rb +0 -1
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -2
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +3 -11
- data/lib/mutant/reporter/cli/printer/status.rb +1 -4
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +1 -3
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -5
- data/lib/mutant/reporter/cli/printer/subject_result.rb +0 -1
- data/lib/mutant/reporter/cli/printer/test_result.rb +0 -1
- data/lib/mutant/reporter/cli/tput.rb +4 -1
- data/lib/mutant/reporter/trace.rb +2 -4
- data/lib/mutant/repository.rb +88 -0
- data/lib/mutant/require_highjack.rb +0 -1
- data/lib/mutant/result.rb +25 -48
- data/lib/mutant/runner.rb +7 -16
- data/lib/mutant/runner/sink.rb +3 -11
- data/lib/mutant/selector.rb +1 -2
- data/lib/mutant/selector/expression.rb +1 -2
- data/lib/mutant/subject.rb +10 -21
- data/lib/mutant/subject/method.rb +11 -12
- data/lib/mutant/subject/method/instance.rb +1 -5
- data/lib/mutant/subject/method/singleton.rb +1 -3
- data/lib/mutant/test.rb +1 -2
- data/lib/mutant/version.rb +2 -2
- data/lib/mutant/warning_filter.rb +2 -7
- data/lib/mutant/zombifier.rb +6 -10
- data/meta/send.rb +8 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/support/corpus.rb +5 -9
- data/spec/support/rb_bug.rb +0 -1
- data/spec/support/rspec.rb +0 -1
- data/spec/support/ruby_vm.rb +0 -2
- data/spec/unit/mutant/ast/meta/send_spec.rb +42 -0
- data/spec/unit/mutant/ast/named_children_spec.rb +51 -0
- data/spec/unit/mutant/ast/sexp_spec.rb +36 -0
- data/spec/unit/mutant/ast_spec.rb +8 -0
- data/spec/unit/mutant/cli_spec.rb +34 -19
- data/spec/unit/mutant/context/scope_spec.rb +11 -0
- data/spec/unit/mutant/env/boostrap_spec.rb +5 -2
- data/spec/unit/mutant/env_spec.rb +14 -15
- data/spec/unit/mutant/expression/method_spec.rb +10 -14
- data/spec/unit/mutant/expression/methods_spec.rb +24 -11
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +5 -6
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +16 -10
- data/spec/unit/mutant/expression/parser_spec.rb +67 -0
- data/spec/unit/mutant/expression_spec.rb +24 -57
- data/spec/unit/mutant/integration/rspec_spec.rb +7 -7
- data/spec/unit/mutant/integration_spec.rb +2 -2
- data/spec/unit/mutant/isolation_spec.rb +31 -29
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +2 -2
- data/spec/unit/mutant/matcher/compiler_spec.rb +27 -58
- data/spec/unit/mutant/matcher/config_spec.rb +45 -0
- data/spec/unit/mutant/matcher/filter_spec.rb +12 -5
- data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -1
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -1
- data/spec/unit/mutant/matcher/namespace_spec.rb +4 -4
- data/spec/unit/mutant/parallel/worker_spec.rb +1 -1
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +4 -4
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +7 -7
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +2 -2
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +2 -2
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +12 -12
- data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +1 -1
- data/spec/unit/mutant/reporter/cli_spec.rb +9 -10
- data/spec/unit/mutant/repository/diff_spec.rb +80 -0
- data/spec/unit/mutant/repository/subject_filter_spec.rb +28 -0
- data/spec/unit/mutant/result/env_spec.rb +1 -1
- data/spec/unit/mutant/runner_spec.rb +0 -1
- data/spec/unit/mutant/selector/expression_spec.rb +14 -14
- data/spec/unit/mutant/subject/method/instance_spec.rb +2 -2
- data/spec/unit/mutant/subject/method/singleton_spec.rb +2 -2
- data/spec/unit/mutant/subject_spec.rb +5 -2
- metadata +20 -3
- data/spec/support/mutation_verifier.rb +0 -96
data/lib/mutant/matcher.rb
CHANGED
@@ -11,30 +11,20 @@ module Mutant
|
|
11
11
|
# @return [undefined]
|
12
12
|
#
|
13
13
|
# @api private
|
14
|
-
#
|
15
14
|
def self.build(*arguments)
|
16
15
|
new(*arguments)
|
17
16
|
end
|
18
17
|
|
19
18
|
# Enumerate subjects
|
20
19
|
#
|
21
|
-
# @api private
|
22
|
-
#
|
23
20
|
# @return [self]
|
24
21
|
# if block given
|
25
22
|
#
|
26
23
|
# @return [Enumerable<Subject>]
|
27
24
|
# otherwise
|
28
25
|
#
|
29
|
-
abstract_method :each
|
30
|
-
|
31
|
-
# Return identification
|
32
|
-
#
|
33
|
-
# @return [String
|
34
|
-
#
|
35
26
|
# @api private
|
36
|
-
|
37
|
-
abstract_method :identification
|
27
|
+
abstract_method :each
|
38
28
|
|
39
29
|
end # Matcher
|
40
30
|
end # Mutant
|
data/lib/mutant/matcher/chain.rb
CHANGED
@@ -5,16 +5,20 @@ module Mutant
|
|
5
5
|
class Compiler
|
6
6
|
include Concord.new(:env, :config), AST::Sexp, Procto.call(:result)
|
7
7
|
|
8
|
-
#
|
8
|
+
# Generated matcher
|
9
9
|
#
|
10
|
-
# @return [
|
10
|
+
# @return [Matcher]
|
11
11
|
#
|
12
12
|
# @api private
|
13
|
-
#
|
14
13
|
def result
|
15
14
|
Filter.new(
|
16
15
|
Chain.build(config.match_expressions.map(&method(:matcher))),
|
17
|
-
|
16
|
+
Morpher::Evaluator::Predicate::Boolean::And.new(
|
17
|
+
[
|
18
|
+
ignored_subjects,
|
19
|
+
filtered_subjects
|
20
|
+
]
|
21
|
+
)
|
18
22
|
)
|
19
23
|
end
|
20
24
|
|
@@ -27,7 +31,6 @@ module Mutant
|
|
27
31
|
# @return [Boolean]
|
28
32
|
#
|
29
33
|
# @api private
|
30
|
-
#
|
31
34
|
def call(subject)
|
32
35
|
expression.prefix?(subject.expression)
|
33
36
|
end
|
@@ -36,71 +39,35 @@ module Mutant
|
|
36
39
|
|
37
40
|
private
|
38
41
|
|
39
|
-
#
|
42
|
+
# Predicate returning false on expression ignored subject
|
40
43
|
#
|
41
44
|
# @return [#call]
|
42
45
|
#
|
43
46
|
# @api private
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
subject_selector,
|
51
|
-
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
|
52
|
-
])
|
53
|
-
elsif subject_selector
|
54
|
-
subject_selector
|
55
|
-
elsif subject_rejector
|
56
|
-
Morpher::Evaluator::Predicate::Negation.new(subject_rejector)
|
57
|
-
else
|
58
|
-
Morpher::Evaluator::Predicate::Tautology.new
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Return subject selector
|
63
|
-
#
|
64
|
-
# @return [#call]
|
65
|
-
# if selector is present
|
66
|
-
#
|
67
|
-
# @return [nil]
|
68
|
-
# otherwise
|
69
|
-
#
|
70
|
-
# @api private
|
71
|
-
#
|
72
|
-
def subject_selector
|
73
|
-
selectors = config.subject_selects.map do |attribute, value|
|
74
|
-
Morpher.compile(s(:eql, s(:attribute, attribute), s(:static, value)))
|
75
|
-
end
|
76
|
-
|
77
|
-
Morpher::Evaluator::Predicate::Boolean::Or.new(selectors) if selectors.any?
|
47
|
+
def ignored_subjects
|
48
|
+
Morpher::Evaluator::Predicate::Boolean::Negation.new(
|
49
|
+
Morpher::Evaluator::Predicate::Boolean::Or.new(
|
50
|
+
config.ignore_expressions.map(&SubjectPrefix.method(:new))
|
51
|
+
)
|
52
|
+
)
|
78
53
|
end
|
79
54
|
|
80
|
-
#
|
55
|
+
# Predicate returning false on filtered subject
|
81
56
|
#
|
82
57
|
# @return [#call]
|
83
|
-
# if there is a subject rejector
|
84
|
-
#
|
85
|
-
# @return [nil]
|
86
|
-
# otherwise
|
87
58
|
#
|
88
59
|
# @api private
|
89
|
-
|
90
|
-
|
91
|
-
rejectors = config.subject_ignores.map(&SubjectPrefix.method(:new))
|
92
|
-
|
93
|
-
Morpher::Evaluator::Predicate::Boolean::Or.new(rejectors) if rejectors.any?
|
60
|
+
def filtered_subjects
|
61
|
+
Morpher::Evaluator::Predicate::Boolean::And.new(config.subject_filters)
|
94
62
|
end
|
95
63
|
|
96
|
-
#
|
64
|
+
# Matcher for expression on env
|
97
65
|
#
|
98
66
|
# @param [Mutant::Expression] expression
|
99
67
|
#
|
100
68
|
# @return [Matcher]
|
101
69
|
#
|
102
70
|
# @api private
|
103
|
-
#
|
104
71
|
def matcher(expression)
|
105
72
|
expression.matcher(env)
|
106
73
|
end
|
@@ -1,16 +1,38 @@
|
|
1
1
|
module Mutant
|
2
2
|
class Matcher
|
3
|
-
#
|
3
|
+
# Subject matcher configuration
|
4
4
|
class Config
|
5
5
|
include Adamantium, Anima::Update, Anima.new(
|
6
6
|
:match_expressions,
|
7
|
-
:
|
8
|
-
:
|
7
|
+
:ignore_expressions,
|
8
|
+
:subject_filters
|
9
9
|
)
|
10
10
|
|
11
|
+
INSPECT_FORMAT = "#<#{self} %s>".freeze
|
12
|
+
ATTRIBUTE_DELIMITER = ' '.freeze
|
13
|
+
ATTRIBUTE_FORMAT = '%s: [%s]'.freeze
|
14
|
+
ENUM_DELIMITER = ','.freeze
|
15
|
+
EMPTY_ATTRIBUTES = 'empty'.freeze
|
16
|
+
PRESENTATIONS = IceNine.deep_freeze(
|
17
|
+
match_expressions: :syntax,
|
18
|
+
ignore_expressions: :syntax,
|
19
|
+
subject_filters: :inspect
|
20
|
+
)
|
21
|
+
private_constant(*constants(false))
|
22
|
+
|
11
23
|
DEFAULT = new(Hash[anima.attribute_names.map { |name| [name, []] }])
|
12
24
|
|
13
|
-
#
|
25
|
+
# Inspection string
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
def inspect
|
31
|
+
INSPECT_FORMAT % inspect_attributes
|
32
|
+
end
|
33
|
+
memoize :inspect
|
34
|
+
|
35
|
+
# Add value to configurable collection
|
14
36
|
#
|
15
37
|
# @param [Symbol] attribute
|
16
38
|
# @param [Object] value
|
@@ -18,11 +40,49 @@ module Mutant
|
|
18
40
|
# @return [Config]
|
19
41
|
#
|
20
42
|
# @api private
|
21
|
-
#
|
22
43
|
def add(attribute, value)
|
23
44
|
update(attribute => public_send(attribute).dup << value)
|
24
45
|
end
|
25
46
|
|
47
|
+
private
|
48
|
+
|
49
|
+
# Present attributes
|
50
|
+
#
|
51
|
+
# @return [Array<Symbol>]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
def present_attributes
|
55
|
+
to_h.reject { |_key, value| value.empty? }.keys
|
56
|
+
end
|
57
|
+
|
58
|
+
# Formatted attributes
|
59
|
+
#
|
60
|
+
# @return [String]
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
def inspect_attributes
|
64
|
+
attributes = present_attributes
|
65
|
+
.map(&method(:format_attribute))
|
66
|
+
.join(ATTRIBUTE_DELIMITER)
|
67
|
+
|
68
|
+
attributes.empty? ? EMPTY_ATTRIBUTES : attributes
|
69
|
+
end
|
70
|
+
|
71
|
+
# Format attribute
|
72
|
+
#
|
73
|
+
# @param [Symbol] attribute_name
|
74
|
+
#
|
75
|
+
# @return [String]
|
76
|
+
def format_attribute(attribute_name)
|
77
|
+
ATTRIBUTE_FORMAT %
|
78
|
+
[
|
79
|
+
attribute_name,
|
80
|
+
public_send(attribute_name)
|
81
|
+
.map(&PRESENTATIONS.fetch(attribute_name))
|
82
|
+
.join(ENUM_DELIMITER)
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
26
86
|
end # Config
|
27
87
|
end # Matcher
|
28
88
|
end # Mutant
|
@@ -4,6 +4,17 @@ module Mutant
|
|
4
4
|
class Filter < self
|
5
5
|
include Concord.new(:matcher, :predicate)
|
6
6
|
|
7
|
+
# New matcher
|
8
|
+
#
|
9
|
+
# @param [Matcher] matcher
|
10
|
+
#
|
11
|
+
# @return [Matcher]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def self.build(matcher, &predicate)
|
15
|
+
new(matcher, predicate)
|
16
|
+
end
|
17
|
+
|
7
18
|
# Enumerate matches
|
8
19
|
#
|
9
20
|
# @return [self]
|
@@ -13,7 +24,6 @@ module Mutant
|
|
13
24
|
# otherwise
|
14
25
|
#
|
15
26
|
# @api private
|
16
|
-
#
|
17
27
|
def each(&block)
|
18
28
|
return to_enum unless block_given?
|
19
29
|
matcher.select(&predicate.method(:call)).each(&block)
|
@@ -3,7 +3,7 @@ module Mutant
|
|
3
3
|
# Matcher for subjects that are a specific method
|
4
4
|
class Method < self
|
5
5
|
include Adamantium::Flat, Concord::Public.new(:env, :scope, :target_method)
|
6
|
-
include AST::NodePredicates
|
6
|
+
include AST::NodePredicates
|
7
7
|
|
8
8
|
# Methods within rbx kernel directory are precompiled and their source
|
9
9
|
# cannot be accessed via reading source location. Same for methods created by eval.
|
@@ -18,7 +18,6 @@ module Mutant
|
|
18
18
|
# otherwise
|
19
19
|
#
|
20
20
|
# @api private
|
21
|
-
#
|
22
21
|
def each
|
23
22
|
return to_enum unless block_given?
|
24
23
|
|
@@ -36,7 +35,6 @@ module Mutant
|
|
36
35
|
# @return [Boolean]
|
37
36
|
#
|
38
37
|
# @api private
|
39
|
-
#
|
40
38
|
def skip?
|
41
39
|
location = source_location
|
42
40
|
if location.nil? || BLACKLIST.match(location.first)
|
@@ -50,67 +48,61 @@ module Mutant
|
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
53
|
-
#
|
51
|
+
# Target method name
|
54
52
|
#
|
55
53
|
# @return [String]
|
56
54
|
#
|
57
55
|
# @api private
|
58
|
-
#
|
59
56
|
def method_name
|
60
57
|
target_method.name
|
61
58
|
end
|
62
59
|
|
63
|
-
#
|
60
|
+
# Target context
|
64
61
|
#
|
65
62
|
# @return [Context::Scope]
|
66
63
|
#
|
67
64
|
# @api private
|
68
|
-
#
|
69
65
|
def context
|
70
66
|
Context::Scope.new(scope, source_path)
|
71
67
|
end
|
72
68
|
|
73
|
-
#
|
69
|
+
# Root source node
|
74
70
|
#
|
75
71
|
# @return [Parser::AST::Node]
|
76
72
|
#
|
77
73
|
# @api private
|
78
|
-
#
|
79
74
|
def ast
|
80
75
|
env.cache.parse(source_path)
|
81
76
|
end
|
82
77
|
|
83
|
-
#
|
78
|
+
# Path to source
|
84
79
|
#
|
85
80
|
# @return [String]
|
86
81
|
#
|
87
82
|
# @api private
|
88
|
-
#
|
89
83
|
def source_path
|
90
84
|
source_location.first
|
91
85
|
end
|
92
86
|
|
93
|
-
#
|
87
|
+
# Source file line
|
94
88
|
#
|
95
|
-
# @return [
|
89
|
+
# @return [Fixnum]
|
96
90
|
#
|
97
91
|
# @api private
|
98
|
-
#
|
99
92
|
def source_line
|
100
93
|
source_location.last
|
101
94
|
end
|
102
95
|
|
103
|
-
#
|
96
|
+
# Full source location
|
104
97
|
#
|
105
|
-
# @return [Array]
|
98
|
+
# @return [Array{String,Fixnum}]
|
106
99
|
#
|
107
100
|
# @api private
|
108
|
-
#
|
109
101
|
def source_location
|
110
102
|
target_method.source_location
|
111
103
|
end
|
112
104
|
|
113
|
-
#
|
105
|
+
# Matched subject
|
114
106
|
#
|
115
107
|
# @return [Subject]
|
116
108
|
# if there is a matched node
|
@@ -119,7 +111,6 @@ module Mutant
|
|
119
111
|
# otherwise
|
120
112
|
#
|
121
113
|
# @api private
|
122
|
-
#
|
123
114
|
def subject
|
124
115
|
node = matched_node_path.last
|
125
116
|
return unless node
|
@@ -127,12 +118,11 @@ module Mutant
|
|
127
118
|
end
|
128
119
|
memoize :subject
|
129
120
|
|
130
|
-
#
|
121
|
+
# Matched node path
|
131
122
|
#
|
132
123
|
# @return [Array<Parser::AST::Node>]
|
133
124
|
#
|
134
125
|
# @api private
|
135
|
-
#
|
136
126
|
def matched_node_path
|
137
127
|
AST.find_last_path(ast, &method(:match?))
|
138
128
|
end
|
@@ -14,7 +14,6 @@ module Mutant
|
|
14
14
|
# @return [Matcher::Method::Instance]
|
15
15
|
#
|
16
16
|
# @api private
|
17
|
-
#
|
18
17
|
def self.build(env, scope, target_method)
|
19
18
|
name = target_method.name
|
20
19
|
if scope.ancestors.include?(::Memoizable) && scope.memoized?(name)
|
@@ -23,17 +22,6 @@ module Mutant
|
|
23
22
|
super
|
24
23
|
end
|
25
24
|
|
26
|
-
# Return identification
|
27
|
-
#
|
28
|
-
# @return [String]
|
29
|
-
#
|
30
|
-
# @api private
|
31
|
-
#
|
32
|
-
def identification
|
33
|
-
"#{scope.name}##{method_name}"
|
34
|
-
end
|
35
|
-
memoize :identification
|
36
|
-
|
37
25
|
NAME_INDEX = 0
|
38
26
|
|
39
27
|
private
|
@@ -45,7 +33,6 @@ module Mutant
|
|
45
33
|
# @return [Boolean]
|
46
34
|
#
|
47
35
|
# @api private
|
48
|
-
#
|
49
36
|
def match?(node)
|
50
37
|
location = node.location || return
|
51
38
|
expression = location.expression || return
|
@@ -61,12 +48,11 @@ module Mutant
|
|
61
48
|
|
62
49
|
private
|
63
50
|
|
64
|
-
#
|
51
|
+
# Source location
|
65
52
|
#
|
66
|
-
# @return [Array]
|
53
|
+
# @return [Array{String,Fixnum}]
|
67
54
|
#
|
68
55
|
# @api private
|
69
|
-
#
|
70
56
|
def source_location
|
71
57
|
scope.unmemoized_instance_method(method_name).source_location
|
72
58
|
end
|
@@ -3,21 +3,9 @@ module Mutant
|
|
3
3
|
class Method
|
4
4
|
# Matcher for singleton methods
|
5
5
|
class Singleton < self
|
6
|
-
SUBJECT_CLASS
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
# @return [String]
|
11
|
-
#
|
12
|
-
# @api private
|
13
|
-
#
|
14
|
-
def identification
|
15
|
-
"#{scope.name}.#{method_name}"
|
16
|
-
end
|
17
|
-
memoize :identification
|
18
|
-
|
19
|
-
RECEIVER_INDEX = 0
|
20
|
-
NAME_INDEX = 1
|
6
|
+
SUBJECT_CLASS = Subject::Method::Singleton
|
7
|
+
RECEIVER_INDEX = 0
|
8
|
+
NAME_INDEX = 1
|
21
9
|
|
22
10
|
private
|
23
11
|
|
@@ -28,7 +16,6 @@ module Mutant
|
|
28
16
|
# @return [Boolean]
|
29
17
|
#
|
30
18
|
# @api private
|
31
|
-
#
|
32
19
|
def match?(node)
|
33
20
|
line?(node) && name?(node) && receiver?(node)
|
34
21
|
end
|
@@ -40,7 +27,6 @@ module Mutant
|
|
40
27
|
# @return [Boolean]
|
41
28
|
#
|
42
29
|
# @api private
|
43
|
-
#
|
44
30
|
def line?(node)
|
45
31
|
expression = node.location.expression
|
46
32
|
return false unless expression
|
@@ -54,7 +40,6 @@ module Mutant
|
|
54
40
|
# @return [Boolean]
|
55
41
|
#
|
56
42
|
# @api private
|
57
|
-
#
|
58
43
|
def name?(node)
|
59
44
|
node.children[NAME_INDEX].equal?(method_name)
|
60
45
|
end
|
@@ -66,7 +51,6 @@ module Mutant
|
|
66
51
|
# @return [Boolean]
|
67
52
|
#
|
68
53
|
# @api private
|
69
|
-
#
|
70
54
|
def receiver?(node)
|
71
55
|
receiver = node.children[RECEIVER_INDEX]
|
72
56
|
case receiver.type
|
@@ -87,7 +71,6 @@ module Mutant
|
|
87
71
|
# @return [Boolean]
|
88
72
|
#
|
89
73
|
# @api private
|
90
|
-
#
|
91
74
|
def receiver_name?(node)
|
92
75
|
name = node.children[NAME_INDEX]
|
93
76
|
name.to_s.eql?(context.unqualified_name)
|