mutant 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|