lib/mutant/mutator/node/send.rb in mutant-0.2.7 vs lib/mutant/mutator/node/send.rb in mutant-0.2.8
- old
+ new
@@ -4,24 +4,82 @@
# Class for mutations where messages are send to objects
class Send < self
handle(Rubinius::AST::Send)
+ # Test if node corresponds to "self.class"
+ #
+ # @param [Rubinius::AST::Node] node
+ #
+ # @return [true]
+ # if node equals to self.class
+ #
+ # @return [false]
+ # otherwise
+ #
+ # @api private
+ #
+ def self.self_class?(node)
+ node.kind_of?(Rubinius::AST::Send) &&
+ node.name == :class &&
+ node.receiver.kind_of?(Rubinius::AST::Self)
+ end
+
private
# Emit mutations
#
# @return [undefined]
#
# @api private
#
def dispatch
+ emit_receiver
emit_implicit_self_receiver
- emit_attribute_mutations(:block) if node.block
+ emit_receiver_mutations
+ emit_block_mutations
emit_block_absence_mutation
end
+ # Emit receiver
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def emit_receiver
+ unless to_self?
+ emit(receiver)
+ end
+ end
+
+ # Emit block mutations
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def emit_block_mutations
+ if node.block
+ emit_attribute_mutations(:block)
+ end
+ end
+
+ # Emit receiver mutations
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def emit_receiver_mutations
+ util = self.class
+
+ unless to_self? or util.self_class?(receiver)
+ emit_attribute_mutations(:receiver)
+ end
+ end
+
# Emit block absence mutation
#
# @return [undefined]
#
# @api private
@@ -53,18 +111,18 @@
end
# Check if receiver is self
#
# @return [true]
- # returns true when receiver is a Rubinius::AST::Self node
+ # if receiver is a Rubinius::AST::Self node
#
# @return [false]
# return false otherwise
#
# @api private
#
- def self?
+ def to_self?
receiver.kind_of?(Rubinius::AST::Self)
end
# Emit mutation that replaces explicit send to self with implicit send to self
#
@@ -90,13 +148,12 @@
# @return [undefined]
#
# @api private
#
def emit_implicit_self_receiver
- # FIXME: Edge case that is currently not very well undestood
- return if name == :block_given?
- return unless self?
+ return unless to_self?
+ return if self.class.self_class?(node)
mutant = dup_node
mutant.privately = true
# TODO: Fix rubinius to allow this as an attr_accessor
mutant.instance_variable_set(:@vcall_style, true)
emit(mutant)
@@ -114,10 +171,23 @@
#
# @api private
#
def dispatch
super
+ emit_call_remove_mutation
emit_attribute_mutations(:arguments)
+ end
+
+ # Emit transfomr call mutation
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def emit_call_remove_mutation
+ array = node.arguments.array
+ return unless array.length == 1
+ emit(array.first)
end
end
end
end