Fix differ edge case

Closes #57
This commit is contained in:
Markus Schirp 2013-07-02 19:06:03 +02:00
parent 0451b940b3
commit 2842d0e5ee
2 changed files with 65 additions and 22 deletions

View file

@ -1,10 +1,7 @@
module Mutant module Mutant
# Class to create diffs from source code # Class to create diffs from source code
class Differ class Differ
include Adamantium::Flat include Adamantium::Flat, Concord.new(:old, :new)
FORMAT = :unified
CONTEXT_LINES = 3
# Return source diff # Return source diff
# #
@ -14,12 +11,15 @@ module Mutant
# #
def diff def diff
output = '' output = ''
@diffs.each do |piece| case diffs.length
hunk = Diff::LCS::Hunk.new(@old, @new, piece, CONTEXT_LINES, length_difference) when 0
output << hunk.diff(FORMAT) nil
when 1
output = Diff::LCS::Hunk.new(old, new, diffs.first, max_length, 0).diff(:unified)
output << "\n" output << "\n"
else
raise 'Mutation resulted in more than one diff, should not happen!'
end end
output
end end
memoize :diff memoize :diff
@ -36,32 +36,40 @@ module Mutant
end end
memoize :colorized_diff memoize :colorized_diff
private # Return new object
# Initialize differ object
# #
# @param [String] old # @param [String] old
# @param [String] new # @param [String] new
# #
# @return [undefined] # @return [Differ]
# #
# @api private # @api private
# #
def initialize(old, new) def self.new(old, new)
@old, @new = lines(old), lines(new) super(lines(old), lines(new))
@diffs = Diff::LCS.diff(@old, @new)
end end
# Break up sorce into lines private
# Return diffs
# #
# @param [String] source # @return [Array<Array>]
#
# @return [Array<String>]
# #
# @api private # @api private
# #
def lines(source) def diffs
self.class.lines(source) Diff::LCS.diff(old, new)
end
memoize :diffs
# Return max length
#
# @return [Fixnum]
#
# @api private
#
def max_length
old.length > new.length ? old.length : new.length
end end
# Return length difference # Return length difference
@ -71,7 +79,7 @@ module Mutant
# @api private # @api private
# #
def length_difference def length_difference
@new.size - @old.size new.size - old.size
end end
# Break up source into lines # Break up source into lines
@ -85,6 +93,7 @@ module Mutant
def self.lines(source) def self.lines(source)
source.lines.map { |line| line.chomp } source.lines.map { |line| line.chomp }
end end
private_class_method :lines
# Return colorized diff line # Return colorized diff line
# #

View file

@ -0,0 +1,34 @@
require 'spec_helper'
describe Mutant::Differ, '#diff' do
let(:object) { described_class.new(old, new) }
subject { object.diff }
context 'when there is a diff that is at beginning of hunk' do
let(:old) { "foo\nbar" }
let(:new) { "baz\nbar" }
it { should eql("@@ -1,3 +1,3 @@\n-foo\n+baz\n bar\n") }
it_should_behave_like 'an idempotent method'
end
context 'when there is a diff that is NOT at beginning of hunk' do
let(:old) { "foo\nbar" }
let(:new) { "foo\nbaz\nbar" }
it { should eql("@@ -1,3 +1,4 @@\n foo\n+baz\n bar\n") }
it_should_behave_like 'an idempotent method'
end
context 'when there is no diff' do
let(:old) { '' }
let(:new) { '' }
it { should be(nil) }
it_should_behave_like 'an idempotent method'
end
end