Skip to content

Commit

Permalink
Handle attribute assignments to self correctly
Browse files Browse the repository at this point in the history
* Closes mbj#149
  • Loading branch information
mbj committed Jan 11, 2014
1 parent b73d3c7 commit 5af2af3
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 16 deletions.
68 changes: 63 additions & 5 deletions lib/mutant/mutator/node/send.rb
Expand Up @@ -18,7 +18,7 @@ class Send < self

INDEX_REFERENCE = :[]
INDEX_ASSIGN = :[]=
ASSIGN_SUFFIX = :'='
ASSIGN_SUFFIX = '='.freeze

# Base mutator for index operations
class Index < self
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down
42 changes: 31 additions & 11 deletions spec/unit/mutant/mutator/node/send_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit 5af2af3

Please sign in to comment.