free_mutant/lib/mutant/matcher/method/classifier.rb

126 lines
2.6 KiB
Ruby

module Mutant
class Matcher
class Method < self
# A classifier for input strings
class Classifier
include Adamantium::Flat
TABLE = {
'.' => Matcher::Method::Singleton,
'#' => Matcher::Method::Instance
}.freeze
SCOPE_FORMAT = /\A([^#.]+)(\.|#)(.+)\z/.freeze
# Positions of captured regexp groups
# Freezing fixnums to avoid their singleton classes are patched.
SCOPE_NAME_POSITION = 1.freeze
SCOPE_SYMBOL_POSITION = 2.freeze
METHOD_NAME_POSITION = 3.freeze
private_class_method :new
# Run classifier
#
# @param [String] input
#
# @return [Matcher::Method]
# returns matcher when input is in
#
# @return [nil]
# returns nil otherwise
#
# @api private
#
def self.run(input)
match = SCOPE_FORMAT.match(input)
return unless match
new(match).matcher
end
# Return method matcher
#
# @return [Matcher::Method]
#
# @api private
#
def matcher
matcher_class.new(scope, method_name)
end
# Return match
#
# @return [Matche]
#
# @api private
#
attr_reader :match
private
# Initialize matcher
#
# @param [MatchData] match
#
# @api private
#
def initialize(match)
@match = match
end
# Return scope
#
# @return [Class|Module]
#
# @api private
#
def scope
scope_name.gsub(%r(\A::), '').split('::').inject(::Object) do |parent, name|
parent.const_get(name)
end
end
memoize :scope
# Return scope name
#
# @return [String]
#
# @api private
#
def scope_name
match[SCOPE_NAME_POSITION]
end
# Return method name
#
# @return [String]
#
# @api private
#
def method_name
match[METHOD_NAME_POSITION].to_sym
end
# Return scope symbol
#
# @return [Symbol]
#
# @api private
#
def scope_symbol
match[SCOPE_SYMBOL_POSITION]
end
# Return matcher class
#
# @return [Class:Mutant::Matcher]
#
# @api private
#
def matcher_class
TABLE.fetch(scope_symbol)
end
end
end
end
end