Stop mutation of #to_i to implicit self

The mutations of all calls to `#to_i` include one that mutates the call into a
call to `Integer`. This is a great mutation in all calses where there is an
explicit receiver for the `#to_i` call. However, the way that the implicit call
to `self.to_i` is parsed results in a receiver of `nil` instead of `self`.

As such, we want to limit this particular mutation to calls to `#to_i` that have
an explicit receiver. This feels like the correct behavior because the result of
the mutation would be (if it parsed): `Integer(nil)`, which doesn't retain the
intended behavior of the original source.

Another way to approach this would be to mutate the code to `Integer(self)`, but
that doesn't feel as correct to me because if you're using the implicit `self`
with a call to `#to_i`, you likely are not implementing the strict `#to_int`
method as well, which `Integer` relies on.

This fix feels like the right mix of correctness and minimal invasiveness.

Closes #738
This commit is contained in:
Michael Herold 2018-06-17 10:08:55 -05:00
parent 2beac2ccba
commit f6b9b8b095
No known key found for this signature in database
GPG key ID: 0325A44E1EA06F99
3 changed files with 9 additions and 2 deletions

View file

@ -1,3 +1,3 @@
---
threshold: 16
total_score: 1321
total_score: 1316

View file

@ -182,7 +182,7 @@ module Mutant
#
# @return [undefined]
def emit_integer_mutation
return unless selector.equal?(:to_i)
return unless receiver && selector.equal?(:to_i)
emit(s(:send, nil, :Integer, receiver))
end

View file

@ -135,6 +135,13 @@ Mutant::Meta::Example.add :send do
mutation 'map'
end
Mutant::Meta::Example.add :send do
source 'to_i'
singleton_mutations
mutation 'to_int'
end
Mutant::Meta::Example.add :send do
source 'foo.to_s'