free_mutant/lib/mutant/matcher/method/singleton.rb
2012-08-09 23:07:22 +02:00

108 lines
2.6 KiB
Ruby

module Mutant
class Matcher
class Method
# Matcher for singleton methods
class Singleton < self
private
# Return method instance
#
# @return [UnboundMethod]
#
# @api private
#
def method
constant.method(method_name)
end
# Return matched node class
#
# @return [Rubinius::AST::DefineSingletonScope]
#
# @api private
#
def node_class
Rubinius::AST::DefineSingletonScope
end
# Check for stopping AST walk on branch
#
# This method exist to protect against the
# artifical edge case where DefineSingleton nodes
# with differend receivers exist on the same line.
#
# @param [Rubnius::AST::Node] node
#
# @return [true]
# returns true when node should NOT be followed
#
# @return [false]
# returns false when node can be followed
#
# @api private
#
def stop?(node)
node.is_a?(Rubinius::AST::DefineSingleton) && !match_receiver?(node)
end
# Check if receiver matches
#
# @param [Rubinius::AST::DefineSingleton] node
#
# @return [true]
# returns true when receiver is self or constant from pattern
#
# @return [false]
# returns false otherwise
#
# @api private
#
def match_receiver?(node)
receiver = node.receiver
case receiver
when Rubinius::AST::Self
true
when Rubinius::AST::ConstantAccess
match_receiver_name?(receiver)
else
raise 'Can only match receiver on Rubinius::AST::Self or Rubinius::AST::ConstantAccess'
end
end
# Check if reciver name matches context
#
# @param [Rubinius::AST::Node] node
#
# @return [true]
# returns true when node name matches unqualified constant name
#
# @return [false]
# returns false otherwise
#
# @api private
#
def match_receiver_name?(node)
node.name.to_s == context.unqualified_name
end
# Return matched node
#
# @return [Rubinus::AST::DefineSingletonScope]
#
# @api private
#
def matched_node
last_match = nil
ast.walk do |predicate, node|
if match?(node)
last_match = node
end
!stop?(node)
end
last_match
end
end
end
end
end