free_mutant/lib/mutant/matcher/method.rb
2012-08-01 18:34:03 +02:00

197 lines
3.7 KiB
Ruby

module Mutant
class Matcher
# Matcher to find AST for method
class Method < Matcher
include Veritas::Immutable
# Parse a method string into filter
#
# @param [String] input
#
# @return [Matcher::Method]
#
# @api private
#
def self.parse(input)
Classifier.run(input)
end
# Enumerate matches
#
# @return [Enumerable]
# returns enumerable when no block given
#
# @return [self]
# returns self when block given
#
# @api private
#
def each(&block)
return to_enum unless block_given?
subject.tap do |subject|
yield subject if subject
end
self
end
# Return context of matcher
#
# @return [Context]
# returns the context this matcher matches AST nodes
#
# @api private
#
def context
Context::Constant.build(constant)
end
private
# Return method name
#
# @return [String]
#
# @api private
#
attr_reader :method_name
private :method_name
# Return constant name
#
# @return [String]
#
# @api private
#
attr_reader :constant_name
private :constant_name
# Initialize method filter
#
# @param [String] constant_name
# @param [Symbol] method_name
#
# @return [undefined]
#
# @api private
#
def initialize(constant_name, method_name)
@constant_name, @method_name = constant_name, method_name
end
# Return method
#
# @return [UnboundMethod]
#
# @api private
#
abstract :method
# Return node classes this matcher matches
#
# @return [Rubinius::AST::Node]
#
# @api private
#
abstract :node_class
# Check if node is matched
#
# @param [Rubinius::AST::Node] node
#
# @return [true]
# returns true if node matches method
#
# @return [false]
# returns false if node NOT matches method
#
# @api private
#
def match?(node)
node.line == source_file_line &&
node.class == node_class &&
node.name == method_name
end
# Return full ast
#
# @return [Rubinius::AST::Node]
#
# @api private
#
def ast
File.read(source_filename).to_ast
end
# Return source filename
#
# @return [String]
#
# @api private
#
def source_filename
source_location.first
end
# Return source file line
#
# @return [Integer]
#
# @api private
#
def source_file_line
source_location.last
end
# Return source location
#
# @return [Array]
#
# @api private
#
def source_location
method.source_location
end
# Return matched node
#
# @return [Rubinis::AST::Node]
#
# @api private
#
abstract :matched_node
# Return subject
#
# @return [Subject]
# returns subject if there is a matched node
#
# @return [nil]
# otherwise
#
# @api private
#
def subject
node = matched_node
if node
Subject.new(context, node)
end
end
# Return constant
#
# @return [Class|Module]
#
# @api private
#
def constant
constant_name.split('::').inject(::Object) do |parent, name|
parent.const_get(name)
end
end
memoize :subject
end
end
end