free_mutant/lib/mutant/matcher/methods.rb

178 lines
3.5 KiB
Ruby
Raw Normal View History

module Mutant
class Matcher
# Abstract base class for matcher that returns method subjects extracted from scope
class Methods < self
include AbstractType, Equalizer.new(:scope)
# Return scope
#
# @return [Class, Model]
#
# @api private
#
attr_reader :scope
# Initialize object
#
# @param [Class,Module] scope
#
# @return [undefined]
#
# @api private
#
def initialize(scope)
@scope = scope
end
# Enumerate subjects
#
# @return [self]
# if block given
#
# @return [Enumerator<Subject>]
# otherwise
#
# @api private
#
def each(&block)
return to_enum unless block_given?
2012-12-07 17:27:21 -05:00
methods.each do |method|
emit_matches(method, &block)
end
self
end
# Return method matcher class
#
# @return [Class:Matcher::Method]
#
# @api private
#
def matcher
self.class::MATCHER
end
2012-12-07 17:27:21 -05:00
# Return methods
#
# @return [Enumerable<Method, UnboundMethod>]
#
# @api private
#
def methods
method_names.map do |name|
access(name)
end
end
memoize :methods
private
2012-12-07 17:27:21 -05:00
# Return method names
#
# @param [Object] object
#
# @return [Enumerable<Symbol>]
#
# @api private
#
def self.method_names(object)
object.public_instance_methods(false) +
object.private_instance_methods(false) +
object.protected_instance_methods(false)
end
# Emit matches for method
#
2012-12-07 17:27:21 -05:00
# @param [UnboundMethod, Method] method
#
# @return [undefined]
#
# @api private
#
def emit_matches(method)
matcher.new(scope, method).each do |subject|
yield subject
end
end
2012-12-07 17:27:21 -05:00
# Return method names
#
2012-12-07 17:27:21 -05:00
# @return [Enumerable<Symbol>]
#
# @api private
#
2012-12-07 17:27:21 -05:00
abstract_method :method_names
class Singleton < self
MATCHER = Matcher::Method::Singleton
2012-12-07 17:27:21 -05:00
# Return method for name
#
# @param [Symbol] method_name
#
# @return [Method]
#
# @api private
#
def access(method_name)
scope.method(method_name)
end
private
# Return singleton methods defined on scope
#
# @param [Class|Module] scope
#
# @return [Enumerable<Symbol>]
#
# @api private
#
2012-12-07 17:27:21 -05:00
def method_names
singleton_class = scope.singleton_class
names = self.class.method_names(singleton_class)
2012-12-07 17:27:21 -05:00
names.sort.reject do |name|
name.to_sym == :__class_init__
end
end
end
class Instance < self
MATCHER = Matcher::Method::Instance
2012-12-07 17:27:21 -05:00
# Return method for name
#
# @param [Symbol] method_name
#
# @return [UnboundMethod]
#
# @api private
#
def access(method_name)
scope.instance_method(method_name)
end
private
# Return instance methods names of scope
#
# @param [Class|Module] scope
#
# @return [Enumerable<Symbol>]
#
# @api private
#
2012-12-07 17:27:21 -05:00
def method_names
scope = self.scope
return [] unless scope.kind_of?(Module)
names = self.class.method_names(scope)
2012-12-07 17:27:21 -05:00
names.uniq.sort
end
end
end
end
end