mutant 0.5.17 → 0.5.18
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 +6 -0
- data/Rakefile +13 -0
- data/config/flay.yml +1 -1
- data/config/reek.yml +8 -1
- data/lib/mutant.rb +18 -3
- data/lib/mutant/cli.rb +6 -3
- data/lib/mutant/constants.rb +3 -0
- data/lib/mutant/expression.rb +110 -0
- data/lib/mutant/expression/method.rb +92 -0
- data/lib/mutant/expression/namespace.rb +90 -0
- data/lib/mutant/matcher/namespace.rb +3 -4
- data/lib/mutant/meta.rb +31 -0
- data/lib/mutant/meta/example.rb +152 -0
- data/lib/mutant/meta/example/dsl.rb +105 -0
- data/lib/mutant/mutator/node.rb +6 -6
- data/lib/mutant/mutator/node/arguments.rb +1 -1
- data/lib/mutant/mutator/node/begin.rb +1 -1
- data/lib/mutant/mutator/node/const.rb +1 -1
- data/lib/mutant/mutator/node/if.rb +6 -6
- data/lib/mutant/mutator/node/literal/array.rb +2 -2
- data/lib/mutant/mutator/node/literal/hash.rb +2 -2
- data/lib/mutant/mutator/node/literal/range.rb +3 -3
- data/lib/mutant/mutator/node/literal/regex.rb +2 -2
- data/lib/mutant/mutator/node/literal/symbol.rb +1 -1
- data/lib/mutant/mutator/node/op_asgn.rb +1 -3
- data/lib/mutant/mutator/node/or_asgn.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +1 -1
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -1
- data/lib/mutant/reporter/cli/report/mutation.rb +11 -1
- data/lib/mutant/strategy.rb +1 -1
- data/lib/mutant/version.rb +1 -1
- data/meta/and.rb +12 -0
- data/meta/and_asgn.rb +12 -0
- data/meta/array.rb +30 -0
- data/meta/begin.rb +15 -0
- data/meta/binary.rb +12 -0
- data/meta/block.rb +55 -0
- data/meta/block_pass.rb +8 -0
- data/meta/blockarg.rb +10 -0
- data/meta/boolean.rb +15 -0
- data/meta/break.rb +11 -0
- data/meta/case.rb +303 -0
- data/meta/casgn.rb +9 -0
- data/meta/cbase.rb +8 -0
- data/meta/const.rb +9 -0
- data/meta/cvar.rb +7 -0
- data/meta/cvasgn.rb +10 -0
- data/meta/define.rb +118 -0
- data/meta/defined.rb +7 -0
- data/meta/dstr.rb +10 -0
- data/meta/dsym.rb +11 -0
- data/meta/ensure.rb +9 -0
- data/meta/fixnum.rb +19 -0
- data/meta/float.rb +38 -0
- data/meta/gvar.rb +7 -0
- data/meta/gvasgn.rb +10 -0
- data/meta/hash.rb +25 -0
- data/meta/if.rb +57 -0
- data/meta/ivasgn.rb +10 -0
- data/meta/kwbegin.rb +9 -0
- data/meta/lvar.rb +14 -0
- data/meta/lvasgn.rb +10 -0
- data/meta/masgn.rb +7 -0
- data/meta/match_current_line.rb +14 -0
- data/meta/next.rb +11 -0
- data/meta/nil.rb +5 -0
- data/meta/nthref.rb +14 -0
- data/meta/op_assgn.rb +15 -0
- data/meta/or_asgn.rb +22 -0
- data/meta/range.rb +41 -0
- data/meta/redo.rb +5 -0
- data/meta/regex.rb +20 -0
- data/meta/rescue.rb +38 -0
- data/meta/restarg.rb +11 -0
- data/meta/return.rb +15 -0
- data/meta/self.rb +7 -0
- data/meta/send.rb +240 -0
- data/meta/string.rb +7 -0
- data/meta/super.rb +26 -0
- data/meta/symbol.rb +8 -0
- data/meta/unless.rb +15 -0
- data/meta/while.rb +24 -0
- data/meta/yield.rb +10 -0
- data/mutant.gemspec +1 -0
- data/spec/integration/mutant/corpus_spec.rb +29 -25
- data/spec/spec_helper.rb +2 -0
- data/spec/support/mutation_verifier.rb +1 -0
- data/spec/unit/mutant/cli_new_spec.rb +6 -6
- data/spec/unit/mutant/expression/method_spec.rb +50 -0
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +32 -0
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +37 -0
- data/spec/unit/mutant/matcher/namespace_spec.rb +2 -2
- data/spec/unit/mutant/mutation_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node_spec.rb +14 -0
- metadata +123 -139
- data/lib/mutant/cli/classifier.rb +0 -139
- data/lib/mutant/cli/classifier/method.rb +0 -105
- data/lib/mutant/cli/classifier/namespace.rb +0 -49
- data/spec/unit/mutant/cli/classifier/method_spec.rb +0 -77
- data/spec/unit/mutant/cli/classifier/namespace/flat_spec.rb +0 -58
- data/spec/unit/mutant/cli/classifier/namespace/recursive_spec.rb +0 -58
- data/spec/unit/mutant/cli/classifier_spec.rb +0 -59
- data/spec/unit/mutant/mutator/node/and_asgn_spec.rb +0 -19
- data/spec/unit/mutant/mutator/node/begin_spec.rb +0 -32
- data/spec/unit/mutant/mutator/node/binary_spec.rb +0 -41
- data/spec/unit/mutant/mutator/node/block_pass_spec.rb +0 -15
- data/spec/unit/mutant/mutator/node/block_spec.rb +0 -83
- data/spec/unit/mutant/mutator/node/blockarg_spec.rb +0 -17
- data/spec/unit/mutant/mutator/node/case_spec.rb +0 -329
- data/spec/unit/mutant/mutator/node/cbase_spec.rb +0 -15
- data/spec/unit/mutant/mutator/node/conditional_loop_spec.rb +0 -58
- data/spec/unit/mutant/mutator/node/const_spec.rb +0 -16
- data/spec/unit/mutant/mutator/node/define_spec.rb +0 -171
- data/spec/unit/mutant/mutator/node/defined_spec.rb +0 -14
- data/spec/unit/mutant/mutator/node/dstr_spec.rb +0 -17
- data/spec/unit/mutant/mutator/node/dsym_spec.rb +0 -18
- data/spec/unit/mutant/mutator/node/ensure_spec.rb +0 -16
- data/spec/unit/mutant/mutator/node/if_spec.rb +0 -77
- data/spec/unit/mutant/mutator/node/kwbegin_spec.rb +0 -16
- data/spec/unit/mutant/mutator/node/literal/array_spec.rb +0 -47
- data/spec/unit/mutant/mutator/node/literal/boolean_spec.rb +0 -25
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +0 -13
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +0 -53
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +0 -33
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +0 -10
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +0 -56
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +0 -36
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +0 -15
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +0 -15
- data/spec/unit/mutant/mutator/node/loop_ctrl_spec.rb +0 -37
- data/spec/unit/mutant/mutator/node/masgn_spec.rb +0 -14
- data/spec/unit/mutant/mutator/node/match_current_line_spec.rb +0 -21
- data/spec/unit/mutant/mutator/node/named_value/access_spec.rb +0 -78
- data/spec/unit/mutant/mutator/node/named_value/constant_assignment_spec.rb +0 -16
- data/spec/unit/mutant/mutator/node/named_value/variable_assignment_spec.rb +0 -61
- data/spec/unit/mutant/mutator/node/nthref_spec.rb +0 -19
- data/spec/unit/mutant/mutator/node/op_assgn_spec.rb +0 -22
- data/spec/unit/mutant/mutator/node/or_asgn_spec.rb +0 -19
- data/spec/unit/mutant/mutator/node/redo_spec.rb +0 -10
- data/spec/unit/mutant/mutator/node/rescue_spec.rb +0 -63
- data/spec/unit/mutant/mutator/node/restarg_spec.rb +0 -18
- data/spec/unit/mutant/mutator/node/return_spec.rb +0 -31
- data/spec/unit/mutant/mutator/node/send_spec.rb +0 -382
- data/spec/unit/mutant/mutator/node/super_spec.rb +0 -46
- data/spec/unit/mutant/mutator/node/yield_spec.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e86610168e1a64b920f694f5854137186fb808e0
|
4
|
+
data.tar.gz: e33eeafaebdb1a32042f56e03ed0794e25056f16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6237bcc40f7b53097546148fe68488f7b8af9e7c5e9b348cc3fa2811a3fb860f9b92b551ad3daf7aed87158061cc0ade88e894154352f54c6b50a2b0effee5d9
|
7
|
+
data.tar.gz: 42a09a5d0011978606d9ee12fae5bc1b9d4f2919a11aa783dcdc088f22127edd99fbb66a42c1ef7ab2c04efbc842b15c2e8f13af0ffa33ae3c481059ef4495b6
|
data/Changelog.md
CHANGED
data/Rakefile
CHANGED
@@ -15,3 +15,16 @@ if ENV['TRAVIS']
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
+
|
19
|
+
desc 'Generate mutation operator listing'
|
20
|
+
task :list do
|
21
|
+
require 'mutant'
|
22
|
+
# TODO: Add a nice public interface
|
23
|
+
registry = Mutant::Mutator::Registry.send(:registry)
|
24
|
+
registry.keys.select do |key|
|
25
|
+
key.is_a?(Symbol)
|
26
|
+
end.sort.each do |type|
|
27
|
+
mutator = registry.fetch(type)
|
28
|
+
puts '%-18s: %s' % [type, mutator.name.sub(/\AMutant::Mutator::Node::/, '')]
|
29
|
+
end
|
30
|
+
end
|
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
@@ -10,7 +10,8 @@ ClassVariable:
|
|
10
10
|
exclude: []
|
11
11
|
ControlParameter:
|
12
12
|
enabled: true
|
13
|
-
exclude:
|
13
|
+
exclude:
|
14
|
+
- Mutant::Expression#match_length
|
14
15
|
DataClump:
|
15
16
|
enabled: true
|
16
17
|
exclude: []
|
@@ -33,6 +34,8 @@ FeatureEnvy:
|
|
33
34
|
# Nature of OptionParser :(
|
34
35
|
- Mutant::CLI#add_environmental_options
|
35
36
|
- Mutant::CLI#parse
|
37
|
+
# False positive, its a utility
|
38
|
+
- Mutant::Meta::Example::Verification#format_mutation
|
36
39
|
IrresponsibleModule:
|
37
40
|
enabled: true
|
38
41
|
exclude: []
|
@@ -69,6 +72,7 @@ RepeatedConditional:
|
|
69
72
|
- Mutant::Mutator
|
70
73
|
- Mutant::Rspec::Strategy
|
71
74
|
- Mutant::Reporter::CLI
|
75
|
+
- Mutant::Meta::Example::DSL
|
72
76
|
max_ifs: 1
|
73
77
|
TooManyInstanceVariables:
|
74
78
|
enabled: true
|
@@ -94,6 +98,8 @@ TooManyStatements:
|
|
94
98
|
- Mutant::Reporter::CLI#colorized_diff
|
95
99
|
- Mutant::Reporter::CLI::Report::Config#run
|
96
100
|
- Mutant::Runner#visit_collection
|
101
|
+
- Mutant::Runner#initialize
|
102
|
+
- Mutant::Runner::Mutation#run
|
97
103
|
- Mutant::Zombifier::File#self.find
|
98
104
|
- Mutant::RequireHighjack#infect
|
99
105
|
- Mutant::Reporter::CLI::Registry#included
|
@@ -152,4 +158,5 @@ UtilityFunction:
|
|
152
158
|
- Mutant::Rspec::Strategy#options
|
153
159
|
- Mutant::Rspec::Strategy#world
|
154
160
|
- Mutant::Rspec::Strategy#rspec2
|
161
|
+
- Mutant::Meta::Example::Verification#format_mutation
|
155
162
|
max_helper_calls: 0
|
data/lib/mutant.rb
CHANGED
@@ -26,6 +26,20 @@ module Mutant
|
|
26
26
|
# The frozen empty array used within mutant
|
27
27
|
EMPTY_ARRAY = [].freeze
|
28
28
|
|
29
|
+
# Lookup constant for location
|
30
|
+
#
|
31
|
+
# @param [String] location
|
32
|
+
#
|
33
|
+
# @return [Object]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
#
|
37
|
+
def self.constant_lookup(location)
|
38
|
+
location.sub(CBASE_PATTERN, EMPTY_STRING).split(SCOPE_OPERATOR).reduce(Object) do |parent, name|
|
39
|
+
parent.const_get(name, nil)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
29
43
|
# Perform self zombification
|
30
44
|
#
|
31
45
|
# @return [self]
|
@@ -144,6 +158,7 @@ require 'mutant/mutator/node/named_value/constant_assignment'
|
|
144
158
|
require 'mutant/mutator/node/named_value/variable_assignment'
|
145
159
|
require 'mutant/mutator/node/loop_control'
|
146
160
|
require 'mutant/mutator/node/noop'
|
161
|
+
require 'mutant/mutator/node/or_asgn'
|
147
162
|
require 'mutant/mutator/node/op_asgn'
|
148
163
|
require 'mutant/mutator/node/conditional_loop'
|
149
164
|
require 'mutant/mutator/node/yield'
|
@@ -186,6 +201,9 @@ require 'mutant/matcher/namespace'
|
|
186
201
|
require 'mutant/matcher/scope'
|
187
202
|
require 'mutant/matcher/filter'
|
188
203
|
require 'mutant/matcher/null'
|
204
|
+
require 'mutant/expression'
|
205
|
+
require 'mutant/expression/method'
|
206
|
+
require 'mutant/expression/namespace'
|
189
207
|
require 'mutant/killer'
|
190
208
|
require 'mutant/test'
|
191
209
|
require 'mutant/strategy'
|
@@ -195,9 +213,6 @@ require 'mutant/runner/subject'
|
|
195
213
|
require 'mutant/runner/mutation'
|
196
214
|
require 'mutant/runner/killer'
|
197
215
|
require 'mutant/cli'
|
198
|
-
require 'mutant/cli/classifier'
|
199
|
-
require 'mutant/cli/classifier/namespace'
|
200
|
-
require 'mutant/cli/classifier/method'
|
201
216
|
require 'mutant/color'
|
202
217
|
require 'mutant/diff'
|
203
218
|
require 'mutant/reporter'
|
data/lib/mutant/cli.rb
CHANGED
@@ -249,8 +249,11 @@ module Mutant
|
|
249
249
|
#
|
250
250
|
def parse_matchers(patterns)
|
251
251
|
patterns.each do |pattern|
|
252
|
-
|
253
|
-
|
252
|
+
expression = Expression.parse(pattern)
|
253
|
+
unless expression
|
254
|
+
raise Error, "Invalid mutant expression: #{pattern.inspect}"
|
255
|
+
end
|
256
|
+
@builder.add_matcher(expression.matcher(@cache))
|
254
257
|
end
|
255
258
|
end
|
256
259
|
|
@@ -321,7 +324,7 @@ module Mutant
|
|
321
324
|
#
|
322
325
|
def add_filter_options(opts)
|
323
326
|
opts.on('--ignore-subject PATTERN', 'Ignore subjects that match PATTERN') do |pattern|
|
324
|
-
@builder.add_subject_ignore(
|
327
|
+
@builder.add_subject_ignore(Expression.parse(pattern).matcher(@cache))
|
325
328
|
end
|
326
329
|
opts.on('--code CODE', 'Scope execution to subjects with CODE') do |code|
|
327
330
|
@builder.add_subject_selector(Morpher.compile(s(:eql, s(:attribute, :code), s(:static, code))))
|
data/lib/mutant/constants.rb
CHANGED
@@ -4,6 +4,9 @@ module Mutant
|
|
4
4
|
|
5
5
|
symbolset = ->(strings) { strings.map(&:to_sym).to_set.freeze }
|
6
6
|
|
7
|
+
SCOPE_OPERATOR = '::'.freeze
|
8
|
+
CBASE_PATTERN = /\A#{SCOPE_OPERATOR}/.freeze
|
9
|
+
|
7
10
|
# Set of nodes that cannot be on the LHS of an assignment
|
8
11
|
NOT_ASSIGNABLE = symbolset.(%w[int float str dstr class module self])
|
9
12
|
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Mutant
|
2
|
+
|
3
|
+
# Abstract base class for match expression
|
4
|
+
class Expression
|
5
|
+
include AbstractType, Adamantium, Concord::Public.new(:match)
|
6
|
+
|
7
|
+
include Equalizer.new(:syntax)
|
8
|
+
|
9
|
+
SCOPE_NAME_PATTERN = /[A-Za-z][A-Za-z\d_]*/.freeze
|
10
|
+
|
11
|
+
METHOD_NAME_PATTERN = Regexp.union(
|
12
|
+
/[A-Za-z_][A-Za-z\d_]*[!?=]?/,
|
13
|
+
*OPERATOR_METHODS.map(&:to_s)
|
14
|
+
).freeze
|
15
|
+
|
16
|
+
SCOPE_PATTERN = /
|
17
|
+
(?:#{SCOPE_OPERATOR})?#{SCOPE_NAME_PATTERN}
|
18
|
+
(?:#{SCOPE_OPERATOR}#{SCOPE_NAME_PATTERN})*
|
19
|
+
/x.freeze
|
20
|
+
|
21
|
+
REGISTRY = {}
|
22
|
+
|
23
|
+
# Initialize expression
|
24
|
+
#
|
25
|
+
# @param [MatchData] match
|
26
|
+
def initialize(*)
|
27
|
+
super
|
28
|
+
@syntax = match.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return syntax
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
#
|
37
|
+
attr_reader :syntax
|
38
|
+
|
39
|
+
# Return match length for expression
|
40
|
+
#
|
41
|
+
# @param [Expression] neddle
|
42
|
+
#
|
43
|
+
# @return [Fixnum]
|
44
|
+
#
|
45
|
+
def match_length(neddle)
|
46
|
+
if eql?(neddle)
|
47
|
+
syntax.length
|
48
|
+
else
|
49
|
+
0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Register expression
|
54
|
+
#
|
55
|
+
# @return [undefined]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
#
|
59
|
+
def self.register(regexp)
|
60
|
+
REGISTRY[regexp] = self
|
61
|
+
end
|
62
|
+
private_class_method :register
|
63
|
+
|
64
|
+
# Parse input into expression
|
65
|
+
#
|
66
|
+
# @param [String] pattern
|
67
|
+
#
|
68
|
+
# @return [Expression]
|
69
|
+
# if expression is valid
|
70
|
+
#
|
71
|
+
# @return [nil]
|
72
|
+
# otherwise
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
#
|
76
|
+
def self.parse(pattern)
|
77
|
+
expressions = expressions(pattern)
|
78
|
+
case expressions.length
|
79
|
+
when 0
|
80
|
+
when 1
|
81
|
+
expressions.first
|
82
|
+
else
|
83
|
+
fail "Ambigous expression: #{pattern.inspect}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return expressions for input
|
88
|
+
#
|
89
|
+
# @param [String] input
|
90
|
+
#
|
91
|
+
# @return [Classifier]
|
92
|
+
# if classifier can be found
|
93
|
+
#
|
94
|
+
# @return [nil]
|
95
|
+
# otherwise
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
#
|
99
|
+
def self.expressions(input)
|
100
|
+
REGISTRY.each_with_object([]) do |(regexp, klass), expressions|
|
101
|
+
match = regexp.match(input)
|
102
|
+
if match
|
103
|
+
expressions << klass.new(match)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
private_class_method :expressions
|
108
|
+
|
109
|
+
end # Expression
|
110
|
+
end # Mutant
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Expression
|
3
|
+
|
4
|
+
# Explicit method expression
|
5
|
+
class Method < self
|
6
|
+
|
7
|
+
MATCHERS = {
|
8
|
+
'.' => Matcher::Methods::Singleton,
|
9
|
+
'#' => Matcher::Methods::Instance
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
regexp = /
|
13
|
+
\A
|
14
|
+
(?<scope_name>#{SCOPE_PATTERN})
|
15
|
+
(?<scope_symbol>[.#])
|
16
|
+
(?<method_name>#{METHOD_NAME_PATTERN})
|
17
|
+
\z
|
18
|
+
/x.freeze
|
19
|
+
|
20
|
+
register(regexp)
|
21
|
+
|
22
|
+
# Return method matcher
|
23
|
+
#
|
24
|
+
# @param [Cache] cache
|
25
|
+
#
|
26
|
+
# @return [Matcher::Method]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
def matcher(cache)
|
31
|
+
methods_matcher = MATCHERS.fetch(scope_symbol).new(cache, scope)
|
32
|
+
method = methods_matcher.methods.detect do |meth|
|
33
|
+
meth.name == method_name
|
34
|
+
end or raise NameError, "Cannot find method #{identifier}"
|
35
|
+
methods_matcher.matcher.build(cache, scope, method)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Return scope name
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
#
|
46
|
+
def scope_name
|
47
|
+
match[__method__]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Return scope
|
51
|
+
#
|
52
|
+
# @return [Class, Method]
|
53
|
+
#
|
54
|
+
# @api private
|
55
|
+
#
|
56
|
+
def scope
|
57
|
+
Mutant.constant_lookup(scope_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return method name
|
61
|
+
#
|
62
|
+
# @return [String]
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
#
|
66
|
+
def method_name
|
67
|
+
match[__method__].to_sym
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return scope symbol
|
71
|
+
#
|
72
|
+
# @return [Symbol]
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
#
|
76
|
+
def scope_symbol
|
77
|
+
match[__method__]
|
78
|
+
end
|
79
|
+
|
80
|
+
# Return matcher class
|
81
|
+
#
|
82
|
+
# @return [Class:Mutant::Matcher]
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
#
|
86
|
+
def methods_matcher(cache)
|
87
|
+
MATCHERS.fetch(scope_symbol).new(cache, scope)
|
88
|
+
end
|
89
|
+
|
90
|
+
end # Method
|
91
|
+
end # Expression
|
92
|
+
end # Mutant
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Expression
|
3
|
+
# Abstract base class for expressions matching namespaces
|
4
|
+
class Namespace < self
|
5
|
+
include AbstractType
|
6
|
+
|
7
|
+
# Return matcher
|
8
|
+
#
|
9
|
+
# @param [Cache] cache
|
10
|
+
#
|
11
|
+
# @return [Matcher]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
def matcher(cache)
|
16
|
+
self.class::MATCHER.new(cache, namespace)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Return namespace
|
22
|
+
#
|
23
|
+
# @return [Class, Module]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def namespace
|
28
|
+
Mutant.constant_lookup(match[__method__].to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Recursive namespace expression
|
32
|
+
class Recursive < self
|
33
|
+
|
34
|
+
register(/\A(?<namespace>#{SCOPE_PATTERN})?\*\z/)
|
35
|
+
|
36
|
+
MATCHER = Matcher::Namespace
|
37
|
+
|
38
|
+
# Initialize object
|
39
|
+
#
|
40
|
+
# @return [undefined]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
def initialize(*)
|
44
|
+
super
|
45
|
+
namespace_src = Regexp.escape(namespace)
|
46
|
+
@recursion_pattern = Regexp.union(/\A#{namespace_src}\z/, /\A#{namespace_src}::/)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return length of match
|
50
|
+
#
|
51
|
+
# @param [Expression] expression
|
52
|
+
#
|
53
|
+
# @return [Fixnum]
|
54
|
+
#
|
55
|
+
# @api private
|
56
|
+
#
|
57
|
+
def match_length(expression)
|
58
|
+
if @recursion_pattern =~ expression.syntax
|
59
|
+
namespace.length
|
60
|
+
else
|
61
|
+
0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Return matched namespace
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
#
|
73
|
+
def namespace
|
74
|
+
match[__method__] || ''
|
75
|
+
end
|
76
|
+
|
77
|
+
end # Recursive
|
78
|
+
|
79
|
+
# Exact namespace expression
|
80
|
+
class Exact < self
|
81
|
+
|
82
|
+
register(/\A(?<namespace>#{SCOPE_PATTERN})\z/)
|
83
|
+
|
84
|
+
MATCHER = Matcher::Scope
|
85
|
+
|
86
|
+
end # Exact
|
87
|
+
|
88
|
+
end # Namespace
|
89
|
+
end # Namespace
|
90
|
+
end # Mutant
|