diff --git a/lib/mutant/mutator/node/send.rb b/lib/mutant/mutator/node/send.rb index 95bad8f4f..f52e3efe3 100644 --- a/lib/mutant/mutator/node/send.rb +++ b/lib/mutant/mutator/node/send.rb @@ -18,7 +18,7 @@ class Send < self INDEX_REFERENCE = :[] INDEX_ASSIGN = :[]= - ASSIGN_SUFFIX = :'=' + ASSIGN_SUFFIX = '='.freeze # Base mutator for index operations class Index < self @@ -81,11 +81,12 @@ def dispatch # @api private # def non_index_dispatch - if binary_operator? + case + when binary_operator? run(Binary) - return + else + normal_dispatch end - normal_dispatch end # Return arguments @@ -149,6 +150,19 @@ def binary_operator? arguments.one? && BINARY_METHOD_OPERATORS.include?(selector) end + # Test for attribute assignment + # + # @return [true] + # if node represetns and attribute assignment + # + # @return [false] + # + # @api private + # + def attribute_assignment? + !BINARY_OPERATORS.include?(selector) && !UNARY_OPERATORS.include?(selector) && assignment? && !mlhs? + end + # Mutate arguments # # @return [undefined] @@ -196,11 +210,55 @@ def mutate_receiver # @api private # def emit_implicit_self - if receiver.type == :self and !KEYWORDS.include?(selector) + if receiver.type == :self && !KEYWORDS.include?(selector) && !attribute_assignment? emit_receiver(nil) end end + # Test for assignment + # + # FIXME: This also returns true for <= operator! + # + # @return [true] + # if node represents attribute / element assignment + # + # @return [false] + # otherwise + # + # @api private + # + def assignment? + selector.to_s[-1] == ASSIGN_SUFFIX + end + + # Test for mlhs + # + # @return [true] + # if node is within an mlhs + # + # @return [false] + # otherwise + # + # @api private + # + def mlhs? + assignment? && !arguments? + end + + # Test for empty arguments + # + # @return [true] + # if arguments are empty + # + # @return [false] + # otherwise + # + # @api private + # + def arguments? + arguments.any? + end + end # Send end # Node end # Mutator diff --git a/spec/unit/mutant/mutator/node/send_spec.rb b/spec/unit/mutant/mutator/node/send_spec.rb index 76d622faa..f2c2bf3ca 100644 --- a/spec/unit/mutant/mutator/node/send_spec.rb +++ b/spec/unit/mutant/mutator/node/send_spec.rb @@ -56,20 +56,40 @@ end context 'attribute assign' do - let(:source) { 'foo.bar=baz' } - let(:mutations) do - mutations = [] - mutations << 'foo' - mutations << 'nil' - mutations << 'foo.bar=nil' - mutations << 'foo.bar' - mutations << 'baz' - # This one could probably be removed - mutations << 'nil.bar=baz' + context 'to self' do + let(:source) { 'self.bar=baz' } + + let(:mutations) do + mutations = [] + mutations << 'nil' + mutations << 'self.bar=nil' + mutations << 'self' + mutations << 'self.bar' + mutations << 'baz' + # This one could probably be removed + mutations << 'nil.bar=baz' + end + + it_should_behave_like 'a mutator' end - it_should_behave_like 'a mutator' + context 'to other object' do + let(:source) { 'foo.bar=baz' } + + let(:mutations) do + mutations = [] + mutations << 'foo' + mutations << 'nil' + mutations << 'foo.bar=nil' + mutations << 'foo.bar' + mutations << 'baz' + # This one could probably be removed + mutations << 'nil.bar=baz' + end + + it_should_behave_like 'a mutator' + end end context 'index assign' do