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