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

93 lines
2.3 KiB
Ruby

# frozen_string_literal: true
module Mutant
class Matcher
class Method
# Matcher for singleton methods
class Singleton < self
# New singleton method matcher
#
# @param [Class, Module] scope
# @param [Symbol] method_name
#
# @return [Matcher::Method::Singleton]
def self.new(scope, method_name)
super(scope, method_name, Evaluator)
end
# Singleton method evaluator
class Evaluator < Evaluator
SUBJECT_CLASS = Subject::Method::Singleton
RECEIVER_INDEX = 0
NAME_INDEX = 1
RECEIVER_WARNING = 'Can only match :defs on :self or :const got %p unable to match'
private
# Test for node match
#
# @param [Parser::AST::Node] node
#
# @return [Boolean]
def match?(node)
n_defs?(node) && line?(node) && name?(node) && receiver?(node)
end
# Test for line match
#
# @param [Parser::AST::Node] node
#
# @return [Boolean]
def line?(node)
node
.location
.line
.equal?(source_line)
end
# Test for name match
#
# @param [Parser::AST::Node] node
#
# @return [Boolean]
def name?(node)
node.children.fetch(NAME_INDEX).equal?(method_name)
end
# Test for receiver match
#
# @param [Parser::AST::Node] node
#
# @return [Boolean]
def receiver?(node)
receiver = node.children.fetch(RECEIVER_INDEX)
case receiver.type
when :self
true
when :const
receiver_name?(receiver)
else
env.warn(RECEIVER_WARNING % receiver.type)
nil
end
end
# Test if receiver name matches context
#
# @param [Parser::AST::Node] node
#
# @return [Boolean]
def receiver_name?(node)
name = node.children.fetch(NAME_INDEX)
name.to_s.eql?(context.unqualified_name)
end
end # Evaluator
private_constant(*constants(false))
end # Singleton
end # Method
end # Matcher
end # Mutant