From c976dfb20926146aa66e8f44369e57aa8d28c39c Mon Sep 17 00:00:00 2001 From: Markus Schirp Date: Mon, 11 Aug 2014 17:35:18 +0000 Subject: [PATCH] Allow diffs to be created from overlapping hunks [fix #228][fix #225] --- config/reek.yml | 1 + lib/mutant/diff.rb | 44 ++++++++++++++++++++++++--- lib/mutant/mutator/node/send.rb | 2 +- spec/unit/mutant/diff_spec.rb | 20 ++++++++++++ spec/unit/mutant/reporter/cli_spec.rb | 4 +-- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/config/reek.yml b/config/reek.yml index cf8f0c05..bd207f28 100644 --- a/config/reek.yml +++ b/config/reek.yml @@ -29,6 +29,7 @@ FeatureEnvy: # Nature of OptionParser :( - Mutant::CLI#add_environment_options - Mutant::Env#scope_name + - Mutant::Diff#minimized_hunks - Mutant::Integration::Rspec#run - Mutant::Integration::Rspec::Rspec2#full_description - Mutant::Integration::Rspec::Rspec3#full_description diff --git a/lib/mutant/diff.rb b/lib/mutant/diff.rb index 3a07a1cf..a97a43ea 100644 --- a/lib/mutant/diff.rb +++ b/lib/mutant/diff.rb @@ -18,9 +18,11 @@ module Mutant # @api private # def diff - return unless diffs.length.equal?(1) - ::Diff::LCS::Hunk.new(old, new, diffs.first, max_length, 0) - .diff(:unified) << NEWLINE + return if diffs.length.equal?(0) + + minimized_hunks.map do |hunk| + hunk.diff(:unified) << NEWLINE + end.join end memoize :diff @@ -77,7 +79,41 @@ module Mutant def diffs ::Diff::LCS.diff(old, new) end - memoize :diffs + + # Return hunks + # + # @return [Array] + # + # @api private + # + def hunks + diffs.map do |diff| + ::Diff::LCS::Hunk.new(old, new, diff, max_length, 0) + end + end + + # Return minimized hunks + # + # @return [Array] + # + # @api pirvate + # + # rubocop gets that one wrong. hunks = hunks() iS NOT equivalent to hunks = hunks, unparser does this right ;) + # + # rubocop:disable MethodCallParentheses + # + def minimized_hunks + hunks = hunks() + + hunks.drop(1).each_with_object([hunks.first]) do |right, aggregate| + left = aggregate.last + if right.overlaps?(left) + right.merge(left) + aggregate.pop + end + aggregate << right + end + end # Return max length # diff --git a/lib/mutant/mutator/node/send.rb b/lib/mutant/mutator/node/send.rb index 0e80cd96..e70149d3 100644 --- a/lib/mutant/mutator/node/send.rb +++ b/lib/mutant/mutator/node/send.rb @@ -27,7 +27,7 @@ module Mutant :>= => [:>, :==, :eql?, :equal?], :<= => [:<, :==, :eql?, :equal?], :> => [:==, :eql?, :equal?], - :< => [:==, :eql?, :equal?], + :< => [:==, :eql?, :equal?] ) private diff --git a/spec/unit/mutant/diff_spec.rb b/spec/unit/mutant/diff_spec.rb index a4daade2..b9c0f22d 100644 --- a/spec/unit/mutant/diff_spec.rb +++ b/spec/unit/mutant/diff_spec.rb @@ -41,6 +41,26 @@ RSpec.describe Mutant::Diff do subject { object.diff } + context 'when there is a diff at begin and end' do + let(:old) { %w[foo bar foo] } + let(:new) { %w[baz bar baz] } + + let(:expectation) do + strip_indent(<<-STR) + @@ -1,4 +1,4 @@ + -foo + +baz + bar + -foo + +baz + STR + end + + it { should eql(expectation) } + + it_should_behave_like 'an idempotent method' + end + context 'when there is a diff at begin of hunk' do let(:old) { %w[foo bar] } let(:new) { %w[baz bar] } diff --git a/spec/unit/mutant/reporter/cli_spec.rb b/spec/unit/mutant/reporter/cli_spec.rb index c2ff74fe..1e9f9246 100644 --- a/spec/unit/mutant/reporter/cli_spec.rb +++ b/spec/unit/mutant/reporter/cli_spec.rb @@ -140,9 +140,7 @@ RSpec.describe Mutant::Reporter::CLI do subject { described_class.build(output) } let(:progressive_format) do - described_class::Format::Progressive.new( - tty: tty?, - ) + described_class::Format::Progressive.new(tty: tty?) end let(:framed_format) do