Change to use unparser release with modern AST
This commit is contained in:
parent
d4f0a77ea6
commit
c75db83bd5
27 changed files with 416 additions and 269 deletions
|
@ -15,7 +15,7 @@ PATH
|
|||
parser (~> 2.5.1)
|
||||
procto (~> 0.0.2)
|
||||
regexp_parser (~> 1.2)
|
||||
unparser (~> 0.3.0)
|
||||
unparser (~> 0.4.0)
|
||||
mutant-rspec (0.8.20)
|
||||
mutant (~> 0.8.20)
|
||||
rspec-core (>= 3.4.0, < 4.0.0)
|
||||
|
@ -141,7 +141,7 @@ GEM
|
|||
simplecov-html (0.10.2)
|
||||
thread_safe (0.3.6)
|
||||
unicode-display_width (1.4.0)
|
||||
unparser (0.3.0)
|
||||
unparser (0.4.0)
|
||||
abstract_type (~> 0.0.7)
|
||||
adamantium (~> 0.2.0)
|
||||
concord (~> 0.1.5)
|
||||
|
|
|
@ -135,7 +135,6 @@ require 'mutant/mutator/node/send'
|
|||
require 'mutant/mutator/node/send/binary'
|
||||
require 'mutant/mutator/node/send/conditional'
|
||||
require 'mutant/mutator/node/send/attribute_assignment'
|
||||
require 'mutant/mutator/node/send/index'
|
||||
require 'mutant/mutator/node/when'
|
||||
require 'mutant/mutator/node/class'
|
||||
require 'mutant/mutator/node/define'
|
||||
|
@ -151,6 +150,8 @@ require 'mutant/mutator/node/regopt'
|
|||
require 'mutant/mutator/node/resbody'
|
||||
require 'mutant/mutator/node/rescue'
|
||||
require 'mutant/mutator/node/match_current_line'
|
||||
require 'mutant/mutator/node/index'
|
||||
require 'mutant/mutator/node/procarg_zero'
|
||||
require 'mutant/loader'
|
||||
require 'mutant/context'
|
||||
require 'mutant/scope'
|
||||
|
|
|
@ -30,14 +30,7 @@ module Mutant
|
|||
naked_proc? || proc_new?
|
||||
end
|
||||
|
||||
# Test if AST node is a valid assignment target
|
||||
#
|
||||
# @return [Boolean]
|
||||
def assignment?
|
||||
index_assignment? || attribute_assignment?
|
||||
end
|
||||
|
||||
# Test if AST node is an attribute assignment?
|
||||
# Test if AST node is a valid attribute assignment
|
||||
#
|
||||
# @return [Boolean]
|
||||
def attribute_assignment?
|
||||
|
@ -45,13 +38,6 @@ module Mutant
|
|||
selector.to_s.end_with?(ATTRIBUTE_ASSIGNMENT_SELECTOR_SUFFIX)
|
||||
end
|
||||
|
||||
# Test if AST node is an index assign
|
||||
#
|
||||
# @return [Boolean]
|
||||
def index_assignment?
|
||||
selector.equal?(INDEX_ASSIGNMENT_SELECTOR)
|
||||
end
|
||||
|
||||
# Test for binary operator implemented as method
|
||||
#
|
||||
# @return [Boolean]
|
||||
|
|
|
@ -182,10 +182,12 @@ module Mutant
|
|||
# Nodes that are NOT generated by parser but used by mutant / unparser.
|
||||
GENERATED = Set.new(%i[empty]).freeze
|
||||
|
||||
EXTRA = Set.new(GENERATED + REGEXP)
|
||||
# Nodes missing from parser metadata
|
||||
MISSING = Set.new(%i[index indexasgn lambda procarg0]).freeze
|
||||
|
||||
# All node types mutant handles
|
||||
ALL = Set.new((Parser::Meta::NODE_TYPES + EXTRA) - BLACKLIST).freeze
|
||||
ALL = Set.new(
|
||||
(Parser::Meta::NODE_TYPES + GENERATED + REGEXP + MISSING) - BLACKLIST
|
||||
).freeze
|
||||
end # Types
|
||||
end # AST
|
||||
end # Mutant
|
||||
|
|
|
@ -99,7 +99,7 @@ module Mutant
|
|||
def node(input)
|
||||
case input
|
||||
when String
|
||||
Unparser::Preprocessor.run(::Parser::CurrentRuby.parse(input))
|
||||
Unparser::Preprocessor.run(Unparser.parse(input))
|
||||
when ::Parser::AST::Node
|
||||
input
|
||||
else
|
||||
|
|
|
@ -96,6 +96,13 @@ module Mutant
|
|||
emit(::Parser::AST::Node.new(node.type, children))
|
||||
end
|
||||
|
||||
# Emit propagation if node can stand alone
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_propagation(node)
|
||||
emit(node) unless AST::Types::NOT_STANDALONE.include?(node.type)
|
||||
end
|
||||
|
||||
# Emit singleton literals
|
||||
#
|
||||
# @return [undefined]
|
||||
|
|
|
@ -67,7 +67,6 @@ module Mutant
|
|||
end
|
||||
|
||||
end # Optional
|
||||
|
||||
end # Argument
|
||||
end # Node
|
||||
end # Mutator
|
||||
|
|
|
@ -24,11 +24,23 @@ module Mutant
|
|||
# @return [undefined]
|
||||
def emit_argument_presence
|
||||
emit_type
|
||||
|
||||
Util::Array::Presence.call(children).each do |children|
|
||||
emit_type(*children)
|
||||
if children.one? && n_mlhs?(Mutant::Util.one(children))
|
||||
emit_procarg(Mutant::Util.one(children))
|
||||
else
|
||||
emit_type(*children)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Emit procarg form
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_procarg(arg)
|
||||
emit_type(s(:procarg0, *arg))
|
||||
end
|
||||
|
||||
# Emit argument mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
|
|
|
@ -17,7 +17,7 @@ module Mutant
|
|||
# @return [undefined]
|
||||
def dispatch
|
||||
emit_singletons
|
||||
emit(send)
|
||||
emit(send) unless n_lambda?(send)
|
||||
emit_send_mutations(&method(:n_send?))
|
||||
emit_arguments_mutations
|
||||
|
||||
|
|
129
lib/mutant/mutator/node/index.rb
Normal file
129
lib/mutant/mutator/node/index.rb
Normal file
|
@ -0,0 +1,129 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutant
|
||||
class Mutator
|
||||
class Node
|
||||
# Base mutator for index operations
|
||||
class Index < self
|
||||
NO_VALUE_RANGE = (1..-1).freeze
|
||||
SEND_REPLACEMENTS = %i[at fetch key?].freeze
|
||||
|
||||
private_constant(*constants(false))
|
||||
|
||||
children :receiver
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
def dispatch
|
||||
emit_singletons
|
||||
emit_receiver_mutations { |node| !n_nil?(node) }
|
||||
emit(receiver)
|
||||
emit_send_forms
|
||||
emit_drop_mutation
|
||||
mutate_indices
|
||||
end
|
||||
|
||||
# Emit send forms
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_send_forms
|
||||
return if asgn_left?
|
||||
|
||||
SEND_REPLACEMENTS.each do |selector|
|
||||
emit(s(:send, receiver, selector, *indices))
|
||||
end
|
||||
end
|
||||
|
||||
# Emit mutation `foo[n..-1]` -> `foo.drop(n)`
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_drop_mutation
|
||||
return unless indices.one? && n_irange?(Mutant::Util.one(indices))
|
||||
|
||||
start, ending = *indices.first
|
||||
|
||||
return unless ending.eql?(s(:int, -1))
|
||||
|
||||
emit(s(:send, receiver, :drop, start))
|
||||
end
|
||||
|
||||
# Mutate indices
|
||||
#
|
||||
# @return [undefined]
|
||||
def mutate_indices
|
||||
children_indices(index_range).each do |index|
|
||||
emit_propagation(children.fetch(index)) unless asgn_left?
|
||||
delete_child(index)
|
||||
mutate_child(index)
|
||||
end
|
||||
end
|
||||
|
||||
# The index nodes
|
||||
#
|
||||
# @return [Enumerable<Parser::AST::Node>]
|
||||
def indices
|
||||
children[index_range]
|
||||
end
|
||||
|
||||
class Read < self
|
||||
|
||||
handle :index
|
||||
|
||||
private
|
||||
|
||||
# The range index children can be found
|
||||
#
|
||||
# @return [Range]
|
||||
def index_range
|
||||
NO_VALUE_RANGE
|
||||
end
|
||||
end
|
||||
|
||||
# Mutator for index assignments
|
||||
class Assign < self
|
||||
REGULAR_RANGE = (1..-2).freeze
|
||||
|
||||
private_constant(*constants(false))
|
||||
|
||||
handle :indexasgn
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
def dispatch
|
||||
super()
|
||||
|
||||
return if asgn_left?
|
||||
|
||||
emit_index_read
|
||||
emit(children.last)
|
||||
mutate_child(children.length.pred)
|
||||
end
|
||||
|
||||
# Emit index read
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_index_read
|
||||
emit(s(:index, receiver, *children[index_range]))
|
||||
end
|
||||
|
||||
# Index indices
|
||||
#
|
||||
# @return [Range<Integer>]
|
||||
def index_range
|
||||
if asgn_left?
|
||||
NO_VALUE_RANGE
|
||||
else
|
||||
REGULAR_RANGE
|
||||
end
|
||||
end
|
||||
end # Assign
|
||||
end # Index
|
||||
end # Node
|
||||
end # Mutator
|
||||
end # Mutant
|
|
@ -7,7 +7,7 @@ module Mutant
|
|||
# Mutation emitter to handle noop nodes
|
||||
class Noop < self
|
||||
|
||||
handle(:__ENCODING__, :block_pass, :cbase)
|
||||
handle(:__ENCODING__, :block_pass, :cbase, :lambda)
|
||||
|
||||
private
|
||||
|
||||
|
|
45
lib/mutant/mutator/node/procarg_zero.rb
Normal file
45
lib/mutant/mutator/node/procarg_zero.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutant
|
||||
class Mutator
|
||||
class Node
|
||||
class ProcargZero < self
|
||||
MAP = {
|
||||
::Parser::AST::Node => :emit_argument_node_mutations,
|
||||
Symbol => :emit_argument_symbol_mutations
|
||||
}.freeze
|
||||
|
||||
private_constant(*constants(false))
|
||||
|
||||
handle :procarg0
|
||||
|
||||
children :argument
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
def dispatch
|
||||
__send__(MAP.fetch(argument.class))
|
||||
end
|
||||
|
||||
# Emit argument symbol mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_argument_symbol_mutations
|
||||
emit_type(:"_#{argument}") unless argument.to_s.start_with?('_')
|
||||
end
|
||||
|
||||
# Emit argument node mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_argument_node_mutations
|
||||
emit_argument_mutations
|
||||
first = Mutant::Util.one(argument.children)
|
||||
emit_type(first)
|
||||
end
|
||||
end # ProcargZero
|
||||
end # Node
|
||||
end # Mutator
|
||||
end # Mutant
|
|
@ -40,7 +40,6 @@ module Mutant
|
|||
values_at: %i[fetch_values],
|
||||
match: %i[match?],
|
||||
'=~': %i[match?],
|
||||
:[] => %i[at fetch key?],
|
||||
:== => %i[eql? equal?],
|
||||
:>= => %i[> == eql? equal?],
|
||||
:<= => %i[< == eql? equal?],
|
||||
|
@ -61,17 +60,7 @@ module Mutant
|
|||
# @return [undefined]
|
||||
def dispatch
|
||||
emit_singletons
|
||||
if meta.index_assignment?
|
||||
run(Index::Assign)
|
||||
else
|
||||
non_index_dispatch
|
||||
end
|
||||
end
|
||||
|
||||
# Perform non index dispatch
|
||||
#
|
||||
# @return [undefined]
|
||||
def non_index_dispatch
|
||||
if meta.binary_method_operator?
|
||||
run(Binary)
|
||||
elsif meta.attribute_assignment?
|
||||
|
@ -117,7 +106,6 @@ module Mutant
|
|||
emit_dig_mutation
|
||||
emit_double_negation_mutation
|
||||
emit_lambda_mutation
|
||||
emit_drop_mutation
|
||||
end
|
||||
|
||||
# Emit selector mutations specific to top level constants
|
||||
|
@ -167,19 +155,6 @@ module Mutant
|
|||
emit(s(:send, fetch_mutation, :dig, *tail))
|
||||
end
|
||||
|
||||
# Emit mutation `foo[n..-1]` -> `foo.drop(n)`
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_drop_mutation
|
||||
return if !selector.equal?(:[]) || !arguments.one? || !n_irange?(arguments.first)
|
||||
|
||||
start, ending = *arguments.first
|
||||
|
||||
return unless ending.eql?(s(:int, -1))
|
||||
|
||||
emit(s(:send, receiver, :drop, start))
|
||||
end
|
||||
|
||||
# Emit mutation from `to_i` to `Integer(...)`
|
||||
#
|
||||
# @return [undefined]
|
||||
|
@ -227,8 +202,7 @@ module Mutant
|
|||
#
|
||||
# @return [undefined]
|
||||
def emit_argument_propagation
|
||||
node = arguments.first
|
||||
emit(node) if arguments.one? && !NOT_STANDALONE.include?(node.type)
|
||||
emit_propagation(Mutant::Util.one(arguments)) if arguments.one?
|
||||
end
|
||||
|
||||
# Emit receiver mutations
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutant
|
||||
class Mutator
|
||||
class Node
|
||||
class Send
|
||||
# Base mutator for index operations
|
||||
class Index < self
|
||||
|
||||
# Mutator for index assignments
|
||||
class Assign < self
|
||||
|
||||
define_named_child(:value, -1)
|
||||
|
||||
INDEX_RANGE = (2..-2).freeze
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
def dispatch
|
||||
emit_naked_receiver
|
||||
emit_value_mutations
|
||||
emit_index_read
|
||||
emit(value)
|
||||
mutate_indices
|
||||
end
|
||||
|
||||
# Mutate indices
|
||||
#
|
||||
# @return [undefined]
|
||||
def mutate_indices
|
||||
children_indices(INDEX_RANGE).each do |index|
|
||||
delete_child(index)
|
||||
mutate_child(index)
|
||||
end
|
||||
end
|
||||
|
||||
# Emit index read
|
||||
#
|
||||
# @return [undefined]
|
||||
def emit_index_read
|
||||
emit_type(receiver, :[], *children[INDEX_RANGE])
|
||||
end
|
||||
|
||||
end # Assign
|
||||
end # Index
|
||||
end # Send
|
||||
end # Node
|
||||
end # Mutator
|
||||
end # Mutant
|
|
@ -18,7 +18,7 @@ module Mutant
|
|||
#
|
||||
# @return [AST::Node]
|
||||
def call(path)
|
||||
@cache[path] ||= ::Parser::CurrentRuby.parse(path.read)
|
||||
@cache[path] ||= Unparser.parse(path.read)
|
||||
end
|
||||
|
||||
end # Parser
|
||||
|
|
|
@ -115,7 +115,7 @@ module Mutant
|
|||
#
|
||||
# @return [Parser::AST::Node]
|
||||
def namespaced_node(source_path)
|
||||
s(:module, s(:const, nil, namespace), ::Parser::CurrentRuby.parse(source_path.read))
|
||||
s(:module, s(:const, nil, namespace), Unparser.parse(source_path.read))
|
||||
end
|
||||
|
||||
end # Zombifier
|
||||
|
|
|
@ -24,8 +24,8 @@ Mutant::Meta::Example.add :block do
|
|||
mutation 'foo { |a, b| raise }'
|
||||
mutation 'foo { |a, _b| }'
|
||||
mutation 'foo { |_a, b| }'
|
||||
mutation 'foo { |a| }'
|
||||
mutation 'foo { |b| }'
|
||||
mutation 'foo { |a, | }'
|
||||
mutation 'foo { |b, | }'
|
||||
mutation 'foo { || }'
|
||||
end
|
||||
|
||||
|
@ -39,7 +39,7 @@ Mutant::Meta::Example.add :block do
|
|||
mutation 'foo { |(a), c| }'
|
||||
mutation 'foo { |(b), c| }'
|
||||
mutation 'foo { |(a, b)| }'
|
||||
mutation 'foo { |c| }'
|
||||
mutation 'foo { |c, | }'
|
||||
mutation 'foo { |(_a, b), c| }'
|
||||
mutation 'foo { |(a, _b), c| }'
|
||||
mutation 'foo { |(a, b), _c| }'
|
||||
|
@ -61,6 +61,25 @@ Mutant::Meta::Example.add :block do
|
|||
mutation 'foo {}'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :block do
|
||||
source 'foo { |_a| }'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'foo { || }'
|
||||
mutation 'foo { |_a| raise }'
|
||||
mutation 'foo'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :block do
|
||||
source 'foo { |a| }'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'foo { || }'
|
||||
mutation 'foo { |a| raise }'
|
||||
mutation 'foo { |_a| }'
|
||||
mutation 'foo'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :block do
|
||||
source 'foo { |(a)| }'
|
||||
|
||||
|
|
133
meta/index.rb
Normal file
133
meta/index.rb
Normal file
|
@ -0,0 +1,133 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'self.foo[]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'self.foo'
|
||||
mutation 'self.foo.at()'
|
||||
mutation 'self.foo.fetch()'
|
||||
mutation 'self.foo.key?()'
|
||||
mutation 'self[]'
|
||||
mutation 'foo[]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'foo[1]'
|
||||
|
||||
singleton_mutations
|
||||
mutation '1'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(1)'
|
||||
mutation 'foo.fetch(1)'
|
||||
mutation 'foo.key?(1)'
|
||||
mutation 'self[1]'
|
||||
mutation 'foo[0]'
|
||||
mutation 'foo[2]'
|
||||
mutation 'foo[-1]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'foo[n..-2]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'n..-2'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(n..-2)'
|
||||
mutation 'foo.fetch(n..-2)'
|
||||
mutation 'foo.key?(n..-2)'
|
||||
mutation 'self[n..-2]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[n..nil]'
|
||||
mutation 'foo[n..self]'
|
||||
mutation 'foo[n..-1]'
|
||||
mutation 'foo[n..2]'
|
||||
mutation 'foo[n..0]'
|
||||
mutation 'foo[n..1]'
|
||||
mutation 'foo[n..-3]'
|
||||
mutation 'foo[n...-2]'
|
||||
mutation 'foo[nil..-2]'
|
||||
mutation 'foo[self..-2]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'foo[n...-1]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'n...-1'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(n...-1)'
|
||||
mutation 'foo.fetch(n...-1)'
|
||||
mutation 'foo.key?(n...-1)'
|
||||
mutation 'self[n...-1]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[n...nil]'
|
||||
mutation 'foo[n...self]'
|
||||
mutation 'foo[n..-1]'
|
||||
mutation 'foo[n...0]'
|
||||
mutation 'foo[n...1]'
|
||||
mutation 'foo[n...-2]'
|
||||
mutation 'foo[nil...-1]'
|
||||
mutation 'foo[self...-1]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'foo[n..-1]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'n..-1'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(n..-1)'
|
||||
mutation 'foo.fetch(n..-1)'
|
||||
mutation 'foo.key?(n..-1)'
|
||||
mutation 'self[n..-1]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[n..nil]'
|
||||
mutation 'foo[n..self]'
|
||||
mutation 'foo[n..0]'
|
||||
mutation 'foo[n..1]'
|
||||
mutation 'foo[n..-2]'
|
||||
mutation 'foo[n...-1]'
|
||||
mutation 'foo[nil..-1]'
|
||||
mutation 'foo[self..-1]'
|
||||
mutation 'foo.drop(n)'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'self[foo]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'self[self]'
|
||||
mutation 'self[nil]'
|
||||
mutation 'self[]'
|
||||
mutation 'self.at(foo)'
|
||||
mutation 'self.fetch(foo)'
|
||||
mutation 'self.key?(foo)'
|
||||
mutation 'foo'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :index do
|
||||
source 'foo[*bar]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(*bar)'
|
||||
mutation 'foo.fetch(*bar)'
|
||||
mutation 'foo.key?(*bar)'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[bar]'
|
||||
mutation 'foo[*self]'
|
||||
mutation 'foo[*nil]'
|
||||
mutation 'self[*bar]'
|
||||
end
|
31
meta/indexasgn.rb
Normal file
31
meta/indexasgn.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Mutant::Meta::Example.add :indexasgn do
|
||||
source 'foo[bar] = baz'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'self[bar] = baz'
|
||||
mutation 'foo'
|
||||
mutation 'foo[bar]'
|
||||
mutation 'foo.at(bar)'
|
||||
mutation 'foo.fetch(bar)'
|
||||
mutation 'foo.key?(bar)'
|
||||
mutation 'foo[bar] = self'
|
||||
mutation 'foo[bar] = nil'
|
||||
mutation 'foo[nil] = baz'
|
||||
mutation 'foo[self] = baz'
|
||||
mutation 'foo[] = baz'
|
||||
mutation 'baz'
|
||||
mutation 'bar'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :indexasgn, :op_asgn do
|
||||
source 'self[foo] += bar'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'self[] += bar'
|
||||
mutation 'self[nil] += bar'
|
||||
mutation 'self[self] += bar'
|
||||
mutation 'self[foo] += nil'
|
||||
mutation 'self[foo] += self'
|
||||
end
|
9
meta/lambda.rb
Normal file
9
meta/lambda.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Mutant::Meta::Example.add :block, :lambda do
|
||||
source '->() {}'
|
||||
|
||||
singleton_mutations
|
||||
|
||||
mutation '->() { raise }'
|
||||
end
|
146
meta/send.rb
146
meta/send.rb
|
@ -353,20 +353,6 @@ Mutant::Meta::Example.add :send do
|
|||
mutation 'baz'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo[bar] = baz'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'foo'
|
||||
mutation 'foo[bar]'
|
||||
mutation 'foo[bar] = self'
|
||||
mutation 'foo[bar] = nil'
|
||||
mutation 'foo[nil] = baz'
|
||||
mutation 'foo[self] = baz'
|
||||
mutation 'foo[] = baz'
|
||||
mutation 'baz'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo(*bar)'
|
||||
|
||||
|
@ -484,36 +470,6 @@ Mutant::Meta::Example.add :send do
|
|||
mutation 'self / foo'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo[1]'
|
||||
|
||||
singleton_mutations
|
||||
mutation '1'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(1)'
|
||||
mutation 'foo.fetch(1)'
|
||||
mutation 'foo.key?(1)'
|
||||
mutation 'self[1]'
|
||||
mutation 'foo[0]'
|
||||
mutation 'foo[2]'
|
||||
mutation 'foo[-1]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'self.foo[]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'self.foo'
|
||||
mutation 'self.foo.at()'
|
||||
mutation 'self.foo.fetch()'
|
||||
mutation 'self.foo.key?()'
|
||||
mutation 'self[]'
|
||||
mutation 'foo[]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo(n..-1)'
|
||||
|
||||
|
@ -532,108 +488,6 @@ Mutant::Meta::Example.add :send do
|
|||
mutation 'foo(n..-2)'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo[n..-2]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'n..-2'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(n..-2)'
|
||||
mutation 'foo.fetch(n..-2)'
|
||||
mutation 'foo.key?(n..-2)'
|
||||
mutation 'self[n..-2]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[n..nil]'
|
||||
mutation 'foo[n..self]'
|
||||
mutation 'foo[n..-1]'
|
||||
mutation 'foo[n..2]'
|
||||
mutation 'foo[n..0]'
|
||||
mutation 'foo[n..1]'
|
||||
mutation 'foo[n..-3]'
|
||||
mutation 'foo[n...-2]'
|
||||
mutation 'foo[nil..-2]'
|
||||
mutation 'foo[self..-2]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo[n...-1]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'n...-1'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(n...-1)'
|
||||
mutation 'foo.fetch(n...-1)'
|
||||
mutation 'foo.key?(n...-1)'
|
||||
mutation 'self[n...-1]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[n...nil]'
|
||||
mutation 'foo[n...self]'
|
||||
mutation 'foo[n..-1]'
|
||||
mutation 'foo[n...0]'
|
||||
mutation 'foo[n...1]'
|
||||
mutation 'foo[n...-2]'
|
||||
mutation 'foo[nil...-1]'
|
||||
mutation 'foo[self...-1]'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo[n..-1]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'n..-1'
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(n..-1)'
|
||||
mutation 'foo.fetch(n..-1)'
|
||||
mutation 'foo.key?(n..-1)'
|
||||
mutation 'self[n..-1]'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[n..nil]'
|
||||
mutation 'foo[n..self]'
|
||||
mutation 'foo[n..0]'
|
||||
mutation 'foo[n..1]'
|
||||
mutation 'foo[n..-2]'
|
||||
mutation 'foo[n...-1]'
|
||||
mutation 'foo[nil..-1]'
|
||||
mutation 'foo[self..-1]'
|
||||
mutation 'foo.drop(n)'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'self[foo]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'self[self]'
|
||||
mutation 'self[nil]'
|
||||
mutation 'self[]'
|
||||
mutation 'self.at(foo)'
|
||||
mutation 'self.fetch(foo)'
|
||||
mutation 'self.key?(foo)'
|
||||
mutation 'foo'
|
||||
end
|
||||
|
||||
Mutant::Meta::Example.add :send do
|
||||
source 'foo[*bar]'
|
||||
|
||||
singleton_mutations
|
||||
mutation 'foo'
|
||||
mutation 'foo[]'
|
||||
mutation 'foo.at(*bar)'
|
||||
mutation 'foo.fetch(*bar)'
|
||||
mutation 'foo.key?(*bar)'
|
||||
mutation 'foo[nil]'
|
||||
mutation 'foo[self]'
|
||||
mutation 'foo[bar]'
|
||||
mutation 'foo[*self]'
|
||||
mutation 'foo[*nil]'
|
||||
mutation 'self[*bar]'
|
||||
end
|
||||
|
||||
(Mutant::AST::Types::BINARY_METHOD_OPERATORS - %i[=~ <= >= < > == != eql?]).each do |operator|
|
||||
Mutant::Meta::Example.add :send do
|
||||
source "true #{operator} false"
|
||||
|
|
|
@ -36,7 +36,7 @@ Gem::Specification.new do |gem|
|
|||
gem.add_runtime_dependency('parser', '~> 2.5.1')
|
||||
gem.add_runtime_dependency('procto', '~> 0.0.2')
|
||||
gem.add_runtime_dependency('regexp_parser', '~> 1.2')
|
||||
gem.add_runtime_dependency('unparser', '~> 0.3.0')
|
||||
gem.add_runtime_dependency('unparser', '~> 0.4.0')
|
||||
|
||||
gem.add_development_dependency('devtools', '~> 0.1.22')
|
||||
gem.add_development_dependency('parallel', '~> 1.3')
|
||||
|
|
|
@ -44,7 +44,7 @@ module ParserHelper
|
|||
end
|
||||
|
||||
def parse(string)
|
||||
Unparser::Preprocessor.run(Parser::CurrentRuby.parse(string))
|
||||
Unparser::Preprocessor.run(Unparser.parse(string))
|
||||
end
|
||||
|
||||
def parse_expression(string)
|
||||
|
|
|
@ -4,7 +4,7 @@ RSpec.describe Mutant::AST::Meta::Send, '#proc?' do
|
|||
subject { described_class.new(node).proc? }
|
||||
|
||||
shared_context 'proc send' do |source|
|
||||
let(:node) { Parser::CurrentRuby.parse(source).children.first }
|
||||
let(:node) { Unparser.parse(source).children.first }
|
||||
end
|
||||
|
||||
shared_examples 'proc definition' do |*args|
|
||||
|
|
|
@ -4,7 +4,7 @@ RSpec.describe Mutant::AST::Meta::Send, '#receiver_possible_top_level_const?' do
|
|||
subject { described_class.new(node).receiver_possible_top_level_const? }
|
||||
|
||||
def parse(source)
|
||||
Parser::CurrentRuby.parse(source)
|
||||
Unparser.parse(source)
|
||||
end
|
||||
|
||||
context 'when implicit top level const' do
|
||||
|
|
|
@ -4,24 +4,22 @@ RSpec.describe Mutant::AST::Meta::Send do
|
|||
let(:object) { described_class.new(node) }
|
||||
|
||||
def parse(source)
|
||||
Parser::CurrentRuby.parse(source)
|
||||
Unparser.parse(source)
|
||||
end
|
||||
|
||||
let(:method_call) { parse('foo.bar(baz)') }
|
||||
let(:attribute_read) { parse('foo.bar') }
|
||||
let(:index_assignment) { parse('foo[0] = bar') }
|
||||
let(:attribute_assignment) { parse('foo.bar = baz') }
|
||||
let(:binary_method_operator) { parse('foo == bar') }
|
||||
|
||||
class Expectation
|
||||
include Adamantium, Anima.new(:name, :assignment, :attribute_assignment, :index_assignment, :binary_method_operator)
|
||||
include Adamantium, Anima.new(:name, :attribute_assignment, :binary_method_operator)
|
||||
|
||||
ALL = [
|
||||
[:method_call, false, false, false, false],
|
||||
[:attribute_read, false, false, false, false],
|
||||
[:index_assignment, true, false, true, false],
|
||||
[:attribute_assignment, true, true, false, false],
|
||||
[:binary_method_operator, false, false, false, true]
|
||||
[:method_call, false, false],
|
||||
[:attribute_read, false, false],
|
||||
[:attribute_assignment, true, false],
|
||||
[:binary_method_operator, false, true]
|
||||
].map do |values|
|
||||
new(Hash[anima.attribute_names.zip(values)])
|
||||
end.freeze
|
||||
|
|
|
@ -19,7 +19,7 @@ RSpec.describe Mutant::Subject do
|
|||
let(:object) { class_under_test.new(context, node) }
|
||||
|
||||
let(:node) do
|
||||
Parser::CurrentRuby.parse(<<-RUBY)
|
||||
Unparser.parse(<<-RUBY)
|
||||
def foo
|
||||
end
|
||||
RUBY
|
||||
|
|
Loading…
Reference in a new issue