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