diff --git a/Changelog.md b/Changelog.md index c167eede4..56611dc49 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,19 @@ +# v0.13.0 unreleased + + Significant unparser upgrade. Mutant now: + + * Avoids emitting mutations that do not round trip against unparsers API. + * Does not emit mutations anymore that are prone to not round tripping. + + This change generates less mutations, and currently slightly increases boot time. + But the number of mutations that are hitting the test suite is much lower so it should balance. + + Also its a good step towards parallel mutation generation reducing boot times. + + This release removes all mutations that modify the local variable scope, mostly as these are + prone to not round trip via unparser. Unused local variables are now also reported by ruby / rubocop + so mutant does not have to spend dynamic analysis capabilty on these anymore. + # v0.12.5 unreleased * [#1458](https://github.com/mbj/mutant/pull/1458) diff --git a/lib/mutant/mutation.rb b/lib/mutant/mutation.rb index 12f8228d5..4ef5765e8 100644 --- a/lib/mutant/mutation.rb +++ b/lib/mutant/mutation.rb @@ -75,10 +75,6 @@ def insert(kernel) end end - # Rendered mutation diff - # - # @return [String, nil] - # the diff, if present def diff Unparser::Diff.build(original_source, source) end diff --git a/lib/mutant/mutator/node/argument.rb b/lib/mutant/mutator/node/argument.rb index 8126a012d..d4ed4d022 100644 --- a/lib/mutant/mutator/node/argument.rb +++ b/lib/mutant/mutator/node/argument.rb @@ -14,14 +14,7 @@ class Argument < self private - def dispatch - emit_name_mutation - end - - def emit_name_mutation - return if skip? - emit_name(:"#{UNDERSCORE}#{name}") - end + def dispatch; end def skip? name.start_with?(UNDERSCORE) @@ -42,7 +35,6 @@ class Optional < self private def dispatch - emit_name_mutation emit_required_mutation emit_default_mutations end diff --git a/lib/mutant/mutator/node/arguments.rb b/lib/mutant/mutator/node/arguments.rb index 04f336fa1..f76e77d30 100644 --- a/lib/mutant/mutator/node/arguments.rb +++ b/lib/mutant/mutator/node/arguments.rb @@ -13,24 +13,11 @@ class Arguments < self private def dispatch - emit_argument_presence emit_argument_mutations emit_mlhs_expansion emit_procarg0_removal end - def emit_argument_presence - emit_type unless removed_block_arg?(EMPTY_ARRAY) || forward_arg? - - children.each_with_index do |removed, index| - new_arguments = children.dup - new_arguments.delete_at(index) - unless forward_type?(removed) || removed_block_arg?(new_arguments) || only_mlhs?(new_arguments) - emit_type(*new_arguments) - end - end - end - def forward_type?(removed) n_forward_arg?(removed) || n_restarg?(removed) || n_kwrestarg?(removed) end diff --git a/lib/mutant/mutator/node/block.rb b/lib/mutant/mutator/node/block.rb index 9e461fc3f..53df93a00 100644 --- a/lib/mutant/mutator/node/block.rb +++ b/lib/mutant/mutator/node/block.rb @@ -25,7 +25,9 @@ def mutate_body emit_body(N_RAISE) return unless body - emit(body) unless body_has_control? + + emit_body_promotion + emit_body_mutations do |node| !(n_nil?(node) && unconditional_loop?) end @@ -45,6 +47,10 @@ def body_has_control? false end + def emit_body_promotion + emit(body) if !body_has_control? && fix_me_argument_need_to_be_empty_on_block) + end + def mutate_body_receiver return if n_lambda?(send) || !n_send?(body) diff --git a/lib/mutant/subject.rb b/lib/mutant/subject.rb index 25d1f7a40..9d128cb34 100644 --- a/lib/mutant/subject.rb +++ b/lib/mutant/subject.rb @@ -19,7 +19,7 @@ def mutations Mutation::Evil .from_node(subject: self, node: wrap_node(mutant)) .either( - ->(validation) { $stderr.puts("generated invalid mutation: #{validation.report}") }, + ->(validation) { report_violation(mutant, validation) }, aggregate.method(:<<) ) end @@ -27,6 +27,14 @@ def mutations end memoize :mutations + def report_violation(mutant, validation) + mutation = Mutation::Evil.new(subject: self, node: wrap_node(mutant), source: validation.original_source.from_right) + puts mutation.diff.colorized_diff + puts validation.report + fail + end + private :report_violation + def inline_disabled? config.inline_disable end diff --git a/meta/block.rb b/meta/block.rb index 9e6ba6c61..ecbcd71b8 100644 --- a/meta/block.rb +++ b/meta/block.rb @@ -20,26 +20,16 @@ singleton_mutations mutation 'foo' mutation 'foo { |a, b| raise }' - mutation 'foo { |a, _b| }' - mutation 'foo { |_a, b| }' - mutation 'foo { |a, | }' - mutation 'foo { |b, | }' - mutation 'foo { || }' end Mutant::Meta::Example.add :block do source 'foo { |(a, b), c| }' singleton_mutations - mutation 'foo { || }' mutation 'foo { |a, b, c| }' mutation 'foo { |(a, b), c| raise }' mutation 'foo { |(a), c| }' mutation 'foo { |(b), c| }' - mutation 'foo { |c, | }' - mutation 'foo { |(_a, b), c| }' - mutation 'foo { |(a, _b), c| }' - mutation 'foo { |(a, b), _c| }' mutation 'foo' end @@ -56,22 +46,11 @@ 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 diff --git a/meta/block_pass.rb b/meta/block_pass.rb index e28e3310c..368913177 100644 --- a/meta/block_pass.rb +++ b/meta/block_pass.rb @@ -44,8 +44,6 @@ Mutant::Meta::Example.add :block_pass do source 'def foo(a, &); foo(&); end' - mutation 'def foo(&); foo(&); end' - mutation 'def foo(_a, &); foo(&); end' mutation 'def foo(a, &); end' mutation 'def foo(a, &); foo; end' mutation 'def foo(a, &); nil; end' diff --git a/meta/blockarg.rb b/meta/blockarg.rb index 03044e7b2..0966d15bb 100644 --- a/meta/blockarg.rb +++ b/meta/blockarg.rb @@ -5,6 +5,5 @@ singleton_mutations mutation 'foo { |&bar| raise }' - mutation 'foo {}' mutation 'foo' end diff --git a/meta/def.rb b/meta/def.rb index 01c3ae9c5..ad4a35a4a 100644 --- a/meta/def.rb +++ b/meta/def.rb @@ -68,17 +68,6 @@ Mutant::Meta::Example.add :def do source 'def foo(a, b); end' - # Deletion of each argument - mutation 'def foo(a); end' - mutation 'def foo(b); end' - - # Deletion of all arguments - mutation 'def foo; end' - - # Rename each argument - mutation 'def foo(_a, b); end' - mutation 'def foo(a, _b); end' - # Mutation of body mutation 'def foo(a, b); raise; end' mutation 'def foo(a, b); super; end' @@ -87,51 +76,23 @@ Mutant::Meta::Example.add :def 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); 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' mutation 'def foo(a, b = nil); super; end' end -Mutant::Meta::Example.add :def, :arg do - source 'def foo(_unused); end' - - mutation 'def foo(_unused); raise; end' - mutation 'def foo; end' - mutation 'def foo(_unused); super; end' -end - -Mutant::Meta::Example.add :def do - source 'def foo(_unused = true); end' - - mutation 'def foo(_unused = false); end' - mutation 'def foo(_unused = true); raise; end' - mutation 'def foo(_unused); end' - mutation 'def foo; end' - mutation 'def foo(_unused = true); super; end' -end - Mutant::Meta::Example.add :def do source 'def foo(a = 0, b = 0); end' - mutation 'def foo(a = 0, _b = 0); end' - mutation 'def foo(_a = 0, b = 0); end' mutation 'def foo(a = 0, b = 1); end' mutation 'def foo(a = 0, b = -1); end' mutation 'def foo(a = 0, b = nil); end' mutation 'def foo(a = -1, b = 0); end' mutation 'def foo(a = nil, b = 0); end' mutation 'def foo(a = 1, b = 0); end' - mutation 'def foo(a = 0); end' - 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' @@ -142,9 +103,7 @@ source 'def foo(a = true); end' mutation 'def foo(a); end' - mutation 'def foo(); end' mutation 'def foo(a = false); end' - mutation 'def foo(_a = true); end' mutation 'def foo(a = true); raise; end' mutation 'def foo(a = true); a = true; end' mutation 'def foo(a = true); super; end' @@ -172,17 +131,6 @@ Mutant::Meta::Example.add :def do source 'def self.foo(a, b); end' - # Deletion of each argument - mutation 'def self.foo(a); end' - mutation 'def self.foo(b); end' - - # Deletion of all arguments - mutation 'def self.foo; end' - - # Rename each argument - mutation 'def self.foo(_a, b); end' - mutation 'def self.foo(a, _b); end' - # Mutation of body mutation 'def self.foo(a, b); raise; end' mutation 'def self.foo(a, b); super; end' @@ -278,10 +226,8 @@ Mutant::Meta::Example.add :def do source 'def foo(a, ...); end' - mutation 'def foo(_a, ...); end' mutation 'def foo(a, ...); raise; end' mutation 'def foo(a, ...); super; end' - mutation 'def foo(...); end' end Mutant::Meta::Example.add :def, :send do diff --git a/meta/kwarg.rb b/meta/kwarg.rb index 2a4f81463..9a4e7f95d 100644 --- a/meta/kwarg.rb +++ b/meta/kwarg.rb @@ -3,8 +3,6 @@ Mutant::Meta::Example.add :kwarg do source 'def foo(bar:); end' - mutation 'def foo; end' mutation 'def foo(bar:); raise; end' mutation 'def foo(bar:); super; end' - mutation 'def foo(_bar:); end' end diff --git a/meta/kwoptarg.rb b/meta/kwoptarg.rb index 7c729e6c6..c8fdf0b48 100644 --- a/meta/kwoptarg.rb +++ b/meta/kwoptarg.rb @@ -3,10 +3,8 @@ Mutant::Meta::Example.add :kwarg do source 'def foo(bar: baz); end' - mutation 'def foo; end' mutation 'def foo(bar: baz); raise; end' mutation 'def foo(bar: baz); super; end' mutation 'def foo(bar: nil); end' mutation 'def foo(bar:); end' - mutation 'def foo(_bar: baz); end' end diff --git a/meta/procarg_zero.rb b/meta/procarg_zero.rb index ffd7fee18..18356ec94 100644 --- a/meta/procarg_zero.rb +++ b/meta/procarg_zero.rb @@ -5,17 +5,6 @@ singleton_mutations mutation 'foo { |a| raise }' - mutation 'foo { |_a| }' - mutation 'foo { }' - mutation 'foo' -end - -Mutant::Meta::Example.add :procarg0 do - source 'foo { |_a| }' - - singleton_mutations - mutation 'foo { |_a| raise }' - mutation 'foo { }' mutation 'foo' end @@ -24,8 +13,6 @@ singleton_mutations mutation 'foo { |(a)| raise }' - mutation 'foo { |(_a)| }' - mutation 'foo { }' mutation 'foo' end @@ -35,9 +22,6 @@ singleton_mutations mutation 'foo { |a, b| }' mutation 'foo { |(a, b)| raise }' - mutation 'foo { |(_a, b)| }' - mutation 'foo { |(a, _b)| }' - mutation 'foo { }' mutation 'foo' end @@ -46,7 +30,6 @@ singleton_mutations mutation 'foo { |(*)| raise }' - mutation 'foo { }' mutation 'foo' end @@ -56,7 +39,5 @@ singleton_mutations mutation 'foo { |a, (*)| }' mutation 'foo { |(a, (*))| raise }' - mutation 'foo { |(_a, (*))| }' - mutation 'foo { }' mutation 'foo' end