free_mutant/lib/mutant/matcher/method.rb
Dan Kubb 2b6eba8ad3 Refactor conditional logic to use a boolean connective
* Change the guard clause into a simple if/else block. I believe a
  guard clause is only useful if it happens before the majority of
  the code in the method. In this case it adds nothing, and is
  probably more difficult to understand.
2013-07-30 11:00:35 -07:00

164 lines
3.3 KiB
Ruby

# encoding: utf-8
module Mutant
class Matcher
# Matcher for subjects that are a specific method
class Method < self
include Adamantium::Flat, Concord::Public.new(:cache, :scope, :method)
# Methods within rbx kernel directory are precompiled and their source
# cannot be accessed via reading source location
SKIP_METHODS = %w[kernel/ (eval)].freeze
BLACKLIST = /\A#{Regexp.union(*SKIP_METHODS)}/.freeze
# Enumerate matches
#
# @return [Enumerable<Subject>]
# returns enumerable when no block given
#
# @return [self]
# returns self when block given
#
# @api private
#
def each
return to_enum unless block_given?
unless skip?
if subject
yield subject
else
message = sprintf(
'Cannot find definition of: %s in %s',
identification,
source_location.join(':')
)
$stderr.puts(message)
end
end
self
end
private
# Test if method is skipped
#
# @return [true]
# true and print warning if location must be filtered
#
# @return [false]
# otherwise
#
# @api private
#
def skip?
location = source_location
if location.nil? || BLACKLIST.match(location.first)
message = sprintf(
'%s does not have valid source location unable to emit matcher',
method.inspect
)
$stderr.puts(message)
true
else
false
end
end
# Return method name
#
# @return [String]
#
# @api private
#
def method_name
method.name
end
# Return context
#
# @return [Context::Scope]
#
# @api private
#
def context
Context::Scope.new(scope, source_path)
end
# Return full ast
#
# @return [Parser::AST::Node]
#
# @api private
#
def ast
cache.parse(source_path)
end
# Return path to source
#
# @return [String]
#
# @api private
#
def source_path
source_location.first
end
# Return source file line
#
# @return [Integer]
#
# @api private
#
def source_line
source_location.last
end
# Return source location
#
# @return [Array]
#
# @api private
#
def source_location
method.source_location
end
# Return subject
#
# @return [Subject]
# returns subject if there is a matched node
#
# @return [nil]
# otherwise
#
# @api private
#
def subject
node = matched_node
return unless node
self.class::SUBJECT_CLASS.new(context, node)
end
memoize :subject
# Return matched node
#
# @return [Parser::AST::Node]
# if node could be found
#
# @return [nil]
# otherwise
#
# @api private
#
def matched_node
Finder.run(ast) do |node|
match?(node)
end
end
end # Method
end # Matcher
end # Mutant