Add optarg arity mutation
- Adds mutation from `def foo(a = true); end` to `def foo(a = true); a = true; end` - closes #310
This commit is contained in:
parent
c025728a09
commit
b19a97084c
6 changed files with 90 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
|||
# v0.8.3 2015-08-xx
|
||||
|
||||
* Remove invalid mutation `super(...)` to `super`
|
||||
* Add mutation from `def foo(a = true); end` to `def foo(a = true); a = true; end` #419
|
||||
|
||||
# v0.8.2 2015-08-11
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
---
|
||||
threshold: 18
|
||||
total_score: 1189
|
||||
total_score: 1200
|
||||
|
|
|
@ -10,6 +10,24 @@ module Mutant
|
|||
children :captures, :assignment, :body
|
||||
end # Resbody
|
||||
|
||||
# Metadata for optional argument nodes
|
||||
class Optarg
|
||||
include NamedChildren, Concord.new(:node)
|
||||
|
||||
UNDERSCORE = '_'.freeze
|
||||
|
||||
children :name, :default_value
|
||||
|
||||
# Test if optarg definition intends to be used
|
||||
#
|
||||
# @return [Boolean]
|
||||
#
|
||||
# @api private
|
||||
def used?
|
||||
!name.to_s.start_with?(UNDERSCORE)
|
||||
end
|
||||
end # Optarg
|
||||
|
||||
# Metadata for send nodes
|
||||
class Send
|
||||
include NamedChildren, Concord.new(:node)
|
||||
|
|
|
@ -13,11 +13,40 @@ module Mutant
|
|||
# @api private
|
||||
def dispatch
|
||||
emit_arguments_mutations
|
||||
emit_optarg_body_assignments
|
||||
emit_body(N_RAISE)
|
||||
emit_body(nil)
|
||||
emit_body_mutations if body
|
||||
end
|
||||
|
||||
# Emit mutations with optional arguments as assignments in method
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
def emit_optarg_body_assignments
|
||||
arguments.children.each do |argument|
|
||||
next unless n_optarg?(argument) && AST::Meta::Optarg.new(argument).used?
|
||||
|
||||
emit_body_prepend(s(:lvasgn, *argument))
|
||||
end
|
||||
end
|
||||
|
||||
# Emit valid body ASTs depending on instance body
|
||||
#
|
||||
# @param node [Parser::AST::Node]
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
def emit_body_prepend(node)
|
||||
if body
|
||||
emit_body(s(:begin, node, body))
|
||||
else
|
||||
emit_body(node)
|
||||
end
|
||||
end
|
||||
|
||||
# Mutator for instance method defines
|
||||
class Instance < self
|
||||
|
||||
|
|
19
meta/def.rb
19
meta/def.rb
|
@ -80,6 +80,22 @@ Mutant::Meta::Example.add do
|
|||
mutation 'def foo(a, b); raise; end'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add do
|
||||
source 'def foo(a, b = nil); true; end'
|
||||
|
||||
mutation 'def foo(_a, b = nil); true; end'
|
||||
mutation 'def foo(a, b = nil); end'
|
||||
mutation 'def foo; true; end'
|
||||
mutation 'def foo(a, b = nil); raise; end'
|
||||
mutation 'def foo(a, b = nil); nil; end'
|
||||
mutation 'def foo(a, b = nil); false; end'
|
||||
mutation 'def foo(a); true; end'
|
||||
mutation 'def foo(a, b = nil); b = nil; true; end'
|
||||
mutation 'def foo(b = nil); true; end'
|
||||
mutation 'def foo(a, _b = nil); true; end'
|
||||
mutation 'def foo(a, b); true; end'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add do
|
||||
source 'def foo(_unused); end'
|
||||
|
||||
|
@ -113,6 +129,8 @@ Mutant::Meta::Example.add do
|
|||
mutation 'def foo(b = 0); end'
|
||||
mutation 'def foo(a, b = 0); end'
|
||||
mutation 'def foo; end'
|
||||
mutation 'def foo(a = 0, b = 0); a = 0; end'
|
||||
mutation 'def foo(a = 0, b = 0); b = 0; end'
|
||||
mutation 'def foo(a = 0, b = 0); raise; end'
|
||||
end
|
||||
|
||||
|
@ -125,6 +143,7 @@ Mutant::Meta::Example.add do
|
|||
mutation 'def foo(a = nil); end'
|
||||
mutation 'def foo(_a = true); end'
|
||||
mutation 'def foo(a = true); raise; end'
|
||||
mutation 'def foo(a = true); a = true; end'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add do
|
||||
|
|
22
spec/unit/mutant/ast/meta/optarg_spec.rb
Normal file
22
spec/unit/mutant/ast/meta/optarg_spec.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
RSpec.describe Mutant::AST::Meta::Optarg do
|
||||
subject(:object) { described_class.new(node) }
|
||||
|
||||
let(:node) { s(:optarg, name, value) }
|
||||
let(:name) { :foo }
|
||||
let(:value) { s(:sym, :bar) }
|
||||
|
||||
its(:name) { should be(:foo) }
|
||||
its(:default_value) { should eql(s(:sym, :bar)) }
|
||||
|
||||
describe '#used?' do
|
||||
subject { object.used? }
|
||||
|
||||
it { should be true }
|
||||
|
||||
context 'when name is prefixed with an underscore' do
|
||||
let(:name) { :_foo }
|
||||
it { should be false }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Add table
Reference in a new issue