Use expression logic for namespace matching

This commit is contained in:
Markus Schirp 2014-06-29 22:33:40 +00:00
parent 4d08889a7c
commit 11b945fbbe
6 changed files with 61 additions and 49 deletions

View file

@ -4,37 +4,13 @@ module Mutant
class Namespace < self
include AbstractType
# Return matcher
#
# @param [Cache] cache
#
# @return [Matcher]
#
# @api private
#
def matcher(cache)
self.class::MATCHER.new(cache, namespace)
end
private
# Return namespace
#
# @return [Class, Module]
#
# @api private
#
def namespace
Mutant.constant_lookup(match[__method__].to_s)
end
# Recursive namespace expression
class Recursive < self
register(/\A(?<namespace>#{SCOPE_PATTERN})?\*\z/)
MATCHER = Matcher::Namespace
# Initialize object
#
# @return [undefined]
@ -50,6 +26,18 @@ module Mutant
)
end
# Return matcher
#
# @param [Cache] cache
#
# @return [Matcher]
#
# @api private
#
def matcher(cache)
Matcher::Namespace.new(cache, self)
end
# Return length of match
#
# @param [Expression] expression
@ -87,8 +75,31 @@ module Mutant
MATCHER = Matcher::Scope
end # Exact
# Return matcher
#
# @param [Cache] cache
#
# @return [Matcher]
#
# @api private
#
def matcher(cache)
Matcher::Scope.new(cache, Mutant.constant_lookup(namespace))
end
private
# Return namespace
#
# @return [String]
#
# @api private
#
def namespace
match[__method__].to_s
end
end # Exact
end # Namespace
end # Namespace
end # Mutant

View file

@ -5,7 +5,7 @@ module Mutant
#
# rubocop:disable LineLength
class Namespace < self
include Concord::Public.new(:cache, :namespace)
include Concord::Public.new(:cache, :expression)
# Enumerate subjects
#
@ -29,17 +29,6 @@ module Mutant
private
# Return pattern
#
# @return [Regexp]
#
# @api private
#
def pattern
/\A#{Regexp.escape(namespace)}(?:\z|::)/
end
memoize :pattern
# Return scope enumerator
#
# @return [Enumerable<Object>]
@ -85,11 +74,22 @@ module Mutant
#
def emit_scope(scope)
name = self.class.scope_name(scope)
unless name.nil? or name.kind_of?(String)
return if name.nil?
unless name.kind_of?(String)
$stderr.puts("WARNING: #{scope.class}#name from: #{scope.inspect} did not return a String or nil. Fix your lib to support normal ruby semantics!")
return
end
yield scope if pattern =~ name
scope_expression = Expression.parse(name)
unless scope_expression
$stderr.puts("WARNING: #{name.inspect} is not an identifiable ruby class name.")
return
end
yield scope if expression.prefix?(scope_expression)
end
end # Namespace

View file

@ -80,7 +80,7 @@ describe Mutant::CLI, '.new' do
context 'with debug flag' do
let(:pattern) { 'TestApp*' }
let(:arguments) { %W[--debug #{pattern}] }
let(:expected_matcher) { ns::Namespace.new(cache, 'TestApp') }
let(:expected_matcher) { ns::Namespace.new(cache, Mutant::Expression.parse_strict(pattern)) }
it_should_behave_like 'a cli parser'
@ -92,7 +92,7 @@ describe Mutant::CLI, '.new' do
context 'with zombie flag' do
let(:pattern) { 'TestApp*' }
let(:arguments) { %W[--zombie #{pattern}] }
let(:expected_matcher) { ns::Namespace.new(cache, 'TestApp') }
let(:expected_matcher) { ns::Namespace.new(cache, Mutant::Expression.parse_strict(pattern)) }
it_should_behave_like 'a cli parser'
@ -104,7 +104,7 @@ describe Mutant::CLI, '.new' do
context 'with namespace pattern' do
let(:pattern) { 'TestApp*' }
let(:arguments) { [pattern] }
let(:expected_matcher) { ns::Namespace.new(cache, 'TestApp') }
let(:expected_matcher) { ns::Namespace.new(cache, Mutant::Expression.parse_strict(pattern)) }
it_should_behave_like 'a cli parser'
end

View file

@ -9,7 +9,7 @@ describe Mutant::Expression::Namespace::Exact do
describe '#matcher' do
subject { object.matcher(cache) }
it { should eql(Mutant::Matcher::Namespace::Scope.new(cache, TestApp::Literal)) }
it { should eql(Mutant::Matcher::Scope.new(cache, TestApp::Literal)) }
end
describe '#match_length' do

View file

@ -2,13 +2,13 @@ require 'spec_helper'
describe Mutant::Expression::Namespace::Recursive do
let(:object) { described_class.parse(input) }
let(:cache) { Mutant::Cache.new }
let(:input) { 'TestApp::Literal*' }
let(:object) { described_class.parse_strict(input) }
let(:cache) { Mutant::Cache.new }
let(:input) { 'TestApp::Literal*' }
describe '#matcher' do
subject { object.matcher(cache) }
it { should eql(Mutant::Matcher::Namespace.new(cache, 'TestApp::Literal')) }
it { should eql(Mutant::Matcher::Namespace.new(cache, object)) }
end
describe '#match_length' do

View file

@ -1,7 +1,7 @@
require 'spec_helper'
describe Mutant::Matcher::Namespace do
let(:object) { described_class.new(cache, 'TestApp::Literal') }
let(:object) { described_class.new(cache, Mutant::Expression.parse_strict('TestApp::Literal')) }
let(:yields) { [] }
let(:cache) { Mutant::Cache.new }
@ -19,7 +19,8 @@ describe Mutant::Matcher::Namespace do
before do
allow(Mutant::Matcher::Methods::Singleton).to receive(:new).with(cache, singleton_a).and_return([subject_a])
allow(Mutant::Matcher::Methods::Instance).to receive(:new).with(cache, singleton_a).and_return([subject_b])
ObjectSpace.stub(each_object: [singleton_a, singleton_b, singleton_c])
allow(ObjectSpace).to receive(:each_object).with(Module).and_return([singleton_a, singleton_b, singleton_c])
end
context 'with no block' do