Fix invalid ASTs on mutating attribute assignments

* Also move index reference / assignment mutators to dedicated file
* Move attribute assignment cases to subclass
* Mutations emitted never had been invalid. Since invalid AST was parsed
  to valid source as unparser trusts the AST.
This commit is contained in:
Markus Schirp 2014-04-22 17:01:46 +00:00
parent 802327c847
commit 5dc4ad2e4c
5 changed files with 104 additions and 36 deletions

View file

@ -127,6 +127,8 @@ require 'mutant/mutator/node/zsuper'
require 'mutant/mutator/node/restarg'
require 'mutant/mutator/node/send'
require 'mutant/mutator/node/send/binary'
require 'mutant/mutator/node/send/attribute_assignment'
require 'mutant/mutator/node/send/index'
require 'mutant/mutator/node/when'
require 'mutant/mutator/node/define'
require 'mutant/mutator/node/mlhs'

View file

@ -46,6 +46,10 @@ module Mutant
children.each_with_index.drop(names.length)
end
define_method(:remaining_children_indices) do
children.each_index.drop(names.length)
end
define_method(:remaining_children) do
children.drop(names.length)
end

View file

@ -22,40 +22,6 @@ module Mutant
INDEX_ASSIGN = :[]=
ASSIGN_SUFFIX = '='.freeze
# Base mutator for index operations
class Index < self
# Mutator for index references
class Reference < self
# Perform dispatch
#
# @return [undefined]
#
# @api private
#
def dispatch
emit(receiver)
end
end # Reference
# Mutator for index assignments
class Assign < self
# Perform dispatch
#
# @return [undefined]
#
# @api private
#
def dispatch
emit(receiver)
end
end # Assign
end # Index
private
# Perform dispatch
@ -65,6 +31,7 @@ module Mutant
# @api private
#
def dispatch
emit_nil
case selector
when INDEX_REFERENCE
run(Index::Reference)
@ -73,7 +40,6 @@ module Mutant
else
non_index_dispatch
end
emit_nil
end
# Perform non index dispatch
@ -86,6 +52,8 @@ module Mutant
case
when binary_operator?
run(Binary)
when attribute_assignment?
run(AttributeAssignment)
else
normal_dispatch
end
@ -173,7 +141,6 @@ module Mutant
# @api private
#
def mutate_arguments
return if arguments.empty?
emit_self(receiver, selector)
remaining_children_with_index.each do |node, index|
mutate_child(index)

View file

@ -0,0 +1,52 @@
# encoding: utf-8
module Mutant
class Mutator
class Node
class Send
# Mutator for sends that correspond to an attribute assignment
class AttributeAssignment < self
private
# Emit mutations
#
# @return [undefined]
#
# @api private
#
def dispatch
normal_dispatch
emit_attribute_read
end
# Mutate arguments
#
# @return [undefined]
#
# @api private
#
def mutate_arguments
remaining_children_indices.each do |index|
mutate_child(index)
end
end
# Emit attribute read
#
# @return [undefined]
#
# @api private
#
def emit_attribute_read
emit_self(receiver, selector.to_s[0..-2].to_sym)
end
end # AttributeAssignment
end # Send
end # Node
end # Mutator
end # Mutant

View file

@ -0,0 +1,43 @@
# encoding: UTF-8
module Mutant
class Mutator
class Node
class Send
# Base mutator for index operations
class Index < self
# Mutator for index references
class Reference < self
# Perform dispatch
#
# @return [undefined]
#
# @api private
#
def dispatch
emit(receiver)
end
end # Reference
# Mutator for index assignments
class Assign < self
# Perform dispatch
#
# @return [undefined]
#
# @api private
#
def dispatch
emit(receiver)
end
end # Assign
end # Index
end # Send
end # Node
end # Mutator
end # Mutant