Port regular (non operator) sends to parser

This commit is contained in:
Markus Schirp 2013-06-14 19:47:23 +02:00
parent d35df6d70c
commit b1f864d10f
2 changed files with 123 additions and 103 deletions

View file

@ -7,6 +7,8 @@ module Mutant
handle(:send)
RECEIVER_INDEX, SELECTOR_INDEX, ARGUMENTS_INDEX = 0, 1, 2..-1
private
# Emit mutations
@ -16,8 +18,85 @@ module Mutant
# @api private
#
def dispatch
emit(receiver) if receiver
mutate_receiver
mutate_arguments
end
# Mutate arguments
#
# @return [undefined]
#
# @api private
#
def mutate_arguments
return if arguments.empty?
if arguments.one?
emit(arguments.first)
end
emit_self(receiver, selector)
children.each_index do |index|
next if index <= SELECTOR_INDEX
mutate_child(index)
delete_child(index)
end
end
# Emit receiver mutations
#
# @return [undefined]
#
# @api private
#
def mutate_receiver
return unless receiver
emit_implicit_self
mutate_child(RECEIVER_INDEX)
end
# Emit implicit self mutation
#
# @return [undefined]
#
# @api rpivate
#
def emit_implicit_self
if receiver.type == :self and !KEYWORDS.include?(selector)
emit_child_update(RECEIVER_INDEX, nil)
end
end
# Return receiver
#
# @return [Parser::Node::AST]
#
# @api private
#
def receiver
children[RECEIVER_INDEX]
end
# Return selector
#
# @return [Symbol]
#
# @api private
#
def selector
children[SELECTOR_INDEX]
end
# Return arguments
#
# @return [Array<Parser::AST::Node>]
#
# @api private
#
def arguments
children[ARGUMENTS_INDEX]
end
memoize :arguments
end # Send
end # Node
end # Mutator

View file

@ -3,38 +3,38 @@ require 'spec_helper'
# FIXME: This spec needs to be structured better!
describe Mutant::Mutator, 'send' do
context 'send without arguments' do
context 'with self as' do
context 'implicit' do
let(:source) { 'foo' }
context 'with self as' do
context 'implicit' do
let(:source) { 'foo' }
it_should_behave_like 'a noop mutator'
end
it_should_behave_like 'a noop mutator'
context 'explict receiver' do
let(:source) { 'self.foo' }
let(:mutations) do
mutations = []
mutations << 'foo'
mutations << 'self'
end
context 'explict receiver' do
let(:source) { 'self.foo' }
it_should_behave_like 'a mutator'
end
let(:mutations) do
mutations = []
mutations << 'foo'
mutations << 'self'
end
it_should_behave_like 'a mutator'
end
context 'explicit receiver with keyword message name' do
Unparser::Constants::KEYWORDS.each do |keyword|
context "with keyword: #{keyword}" do
let(:source) { "self.#{keyword}" }
let(:mutations) do
['self']
end
context 'explicit receiver with keyword message name' do
Unparser::Constants::KEYWORDS.each do |keyword|
context "with keyword: #{keyword}" do
let(:source) { "self.#{keyword}" }
let(:mutations) do
['self']
end
end
end
end
end
context 'without arguments' do
context 'to some object' do
let(:source) { 'foo.bar' }
@ -53,73 +53,14 @@ describe Mutant::Mutator, 'send' do
let(:mutations) do
mutations = []
mutations << 'self.class'
mutations << 'self.foo'
end
it_should_behave_like 'a mutator'
end
end
context 'with block' do
let(:source) { 'foo() { a; b }' }
let(:mutations) do
mutations = []
mutations << 'foo() { a }'
mutations << 'foo() { b }'
mutations << 'foo() { }'
mutations << 'foo'
end
it_should_behave_like 'a mutator'
end
context 'with block args' do
let(:source) { 'foo { |a, b| }' }
before do
Mutant::Random.stub(:hex_string => :random)
end
let(:mutations) do
mutations = []
mutations << 'foo'
mutations << 'foo { |a, b| Object.new }'
mutations << 'foo { |a, srandom| }'
mutations << 'foo { |srandom, b| }'
mutations << 'foo { |a| }'
mutations << 'foo { |b| }'
mutations << 'foo { || }'
end
it_should_behave_like 'a mutator'
end
context 'with block pattern args' do
before do
Mutant::Random.stub(:hex_string => :random)
end
let(:source) { 'foo { |(a, b), c| }' }
let(:mutations) do
mutations = []
mutations << 'foo { || }'
mutations << 'foo { |a, b, c| }'
mutations << 'foo { |(a, b), c| Object.new }'
mutations << 'foo { |(a, b)| }'
mutations << 'foo { |c| }'
mutations << 'foo { |(srandom, b), c| }'
mutations << 'foo { |(a, srandom), c| }'
mutations << 'foo { |(a, b), srandom| }'
mutations << 'foo'
end
it_should_behave_like 'a mutator'
end
context 'send with arguments' do
context 'with arguments' do
context 'one argument' do
let(:source) { 'foo(nil)' }
@ -128,7 +69,7 @@ describe Mutant::Mutator, 'send' do
mutations = []
mutations << 'foo'
mutations << 'nil'
mutations << 'foo(Object.new)'
mutations << 'foo(::Object.new)'
end
it_should_behave_like 'a mutator'
@ -139,10 +80,11 @@ describe Mutant::Mutator, 'send' do
let(:mutations) do
mutations = []
mutations << 'self'
mutations << 'self.foo'
mutations << 'foo(nil)'
mutations << 'nil'
mutations << 'self.foo(Object.new)'
mutations << 'self.foo(::Object.new)'
end
it_should_behave_like 'a mutator'
@ -156,9 +98,9 @@ describe Mutant::Mutator, 'send' do
let(:mutations) do
mutations = []
mutations << "foo.#{keyword}"
mutations << "foo"
mutations << 'foo'
mutations << 'nil'
mutations << "foo.#{keyword}(Object.new)"
mutations << "foo.#{keyword}(::Object.new)"
end
it_should_behave_like 'a mutator'
@ -166,6 +108,20 @@ describe Mutant::Mutator, 'send' do
end
end
context 'two arguments' do
let(:source) { 'foo(nil, nil)' }
let(:mutations) do
mutations = []
mutations << 'foo()'
mutations << 'foo(nil)'
mutations << 'foo(::Object.new, nil)'
mutations << 'foo(nil, ::Object.new)'
end
it_should_behave_like 'a mutator'
end
context 'binary operator methods' do
Mutant::BINARY_METHOD_OPERATORS.each do |operator|
let(:source) { "true #{operator} false" }
@ -183,20 +139,5 @@ describe Mutant::Mutator, 'send' do
it_should_behave_like 'a mutator'
end
end
context 'two arguments' do
let(:source) { 'foo(nil, nil)' }
let(:mutations) do
mutations = []
mutations << 'foo()'
mutations << 'foo(nil)'
mutations << 'foo(Object.new, nil)'
mutations << 'foo(nil, Object.new)'
end
it_should_behave_like 'a mutator'
end
end
end