VCS: remove equal start and end parts on Diff class level - for all calls

This commit is contained in:
irengrig
2011-06-01 14:37:32 +04:00
parent 3def4c3ce0
commit 8ed36b16df
7 changed files with 60 additions and 48 deletions
@@ -39,11 +39,15 @@ public class Enumerator<T> {
}
public int[] enumerate(T[] objects) {
int[] idx = ArrayUtil.newIntArray(objects.length);
for (int i = 0; i < objects.length; i++) {
return enumerate(objects, 0, 0);
}
public int[] enumerate(T[] objects, final int startShift, final int endCut) {
int[] idx = ArrayUtil.newIntArray(objects.length - startShift - endCut);
for (int i = startShift; i < (objects.length - endCut); i++) {
final T object = objects[i];
final int number = enumerate(object);
idx[i] = number;
idx[i - startShift] = number;
}
return idx;
}
@@ -32,30 +32,54 @@ public class Diff {
private static final Logger LOG = Logger.getInstance("#com.intellij.util.diff.Diff");
@Nullable
public static Change buildChanges(@NotNull CharSequence before, @NotNull CharSequence after) {
public static Change buildChanges(@NotNull CharSequence before, @NotNull CharSequence after) throws FilesTooBigForDiffException {
final String[] strings1 = LineTokenizer.tokenize(before, false);
final String[] strings2 = LineTokenizer.tokenize(after, false);
return buildChanges(strings1, strings2);
}
public static <T> Change buildChanges(T[] objects1, T[] objects2) {
public static <T> Change buildChanges(T[] objects1, T[] objects2) throws FilesTooBigForDiffException {
// Old variant of enumerator worked incorrectly with null values.
// This check is to ensure that the corrected version does not introduce bugs.
for (T anObjects1 : objects1) LOG.assertTrue(anObjects1 != null);
for (T anObjects2 : objects2) LOG.assertTrue(anObjects2 != null);
final int startShift = getStartShift(objects1, objects2);
final int endCut = getEndCut(objects1, objects2, startShift);
Enumerator<T> enumerator = new Enumerator<T>(objects1.length + objects2.length, TObjectHashingStrategy.CANONICAL);
int[] ints1 = enumerator.enumerate(objects1);
int[] ints2 = enumerator.enumerate(objects2);
int[] ints1 = enumerator.enumerate(objects1, startShift, endCut);
int[] ints2 = enumerator.enumerate(objects2, startShift, endCut);
Reindexer reindexer = new Reindexer();
int[][] discarded = reindexer.discardUnique(ints1, ints2);
IntLCS intLCS = new IntLCS(discarded[0], discarded[1]);
intLCS.execute();
ChangeBuilder builder = new ChangeBuilder();
ChangeBuilder builder = new ChangeBuilder(startShift);
reindexer.reindex(intLCS.getPaths(), builder);
return builder.getFirstChange();
}
private static <T> int getStartShift(final T[] o1, final T[] o2) {
final int size = Math.min(o1.length, o2.length);
int idx = 0;
for (int i = 0; i < size; i++) {
if (! o1[i].equals(o2[i])) break;
++ idx;
}
return idx;
}
private static <T> int getEndCut(final T[] o1, final T[] o2, final int startShift) {
final int size = Math.min(o1.length, o2.length) - startShift;
int idx = 0;
for (int i = 0; i < size; i++) {
if (! o1[o1.length - i - 1].equals(o2[o2.length - i - 1])) break;
++ idx;
}
return idx;
}
/**
* Tries to translate given line that pointed to the text before change to the line that points to the same text after the change.
*
@@ -64,7 +88,7 @@ public class Diff {
* @param line target line before change
* @return translated line if the processing is ok; negative value otherwise
*/
public static int translateLine(@NotNull CharSequence before, @NotNull CharSequence after, int line) {
public static int translateLine(@NotNull CharSequence before, @NotNull CharSequence after, int line) throws FilesTooBigForDiffException {
Change change = buildChanges(before, after);
if (change == null) {
return -1;
@@ -21,8 +21,6 @@ import junit.framework.TestCase;
import java.util.Arrays;
import com.intellij.util.containers.Enumerator;
/**
* @author dyoma
*/
@@ -34,4 +32,10 @@ public class EnumeratorTest extends TestCase {
indecies = enumerator.enumerate(new Object[]{"a", "c", "b"});
assertTrue(Arrays.equals(new int[]{1, 3, 2}, indecies));
}
public void testWithShift() {
Enumerator enumerator = new Enumerator(10, TObjectHashingStrategy.CANONICAL);
int[] indecies = enumerator.enumerate(new Object[]{"1","a", "b", "a", "2"}, 1, 1);
assertTrue(Arrays.equals(new int[]{1, 2, 1}, indecies));
}
}
@@ -27,34 +27,41 @@ public class DiffTest extends TestCase {
private static final Object[] DATA_123 = new Object[]{"1", "2", "3"};
private static final Object[] DATA_AB = new Object[]{"a", "b"};
private static final Object[] DATA_12AB23 = new Object[]{"1", "2", "a", "b", "2", "3"};
private static final Object[] DATA_123_ = new Object[]{"x","y","z","1", "2","3","alpha","beta"};
private static final Object[] DATA_12AB23_ = new Object[]{"x","y","z","1", "2", "a", "b", "2", "3","alpha","beta"};
public void testEqual() {
public void testEqual() throws FilesTooBigForDiffException {
Diff.Change change = Diff.buildChanges(DATA_123, DATA_123);
assertNull(change);
}
public void testCompletelyDifferent() {
public void testCompletelyDifferent() throws FilesTooBigForDiffException {
Diff.Change change = Diff.buildChanges(DATA_AB, DATA_123);
IntLCSTest.checkLastChange(change, 0, 0, 3, 2);
}
public void testSameMiddle() {
public void testSameMiddle() throws FilesTooBigForDiffException {
Diff.Change change = Diff.buildChanges(DATA_123, new Object[]{"a", "2", "b"});
IntLCSTest.checkChange(change, 0, 0, 1, 1);
IntLCSTest.checkLastChange(change.link, 2, 2, 1, 1);
}
public void testOverlap() {
public void testOverlap() throws FilesTooBigForDiffException {
Diff.Change change = Diff.buildChanges(DATA_123, DATA_12AB23);
IntLCSTest.checkLastChange(change, 2, 2, 3, 0); // inserted: AB2
}
public void testEqualUpToOneEnd() {
public void testTrim() throws FilesTooBigForDiffException {
Diff.Change change = Diff.buildChanges(DATA_123_, DATA_12AB23_);
IntLCSTest.checkLastChange(change, 5, 5, 3, 0); // inserted: AB2
}
public void testEqualUpToOneEnd() throws FilesTooBigFirDiffException {
Diff.Change change = Diff.buildChanges(DATA_AB, new Object[]{"a", "b", "1"});
IntLCSTest.checkLastChange(change, 2, 2, 1, 0);
}
public void testEmptyAgainstSmth() {
public void testEmptyAgainstSmth() throws FilesTooBigForDiffException {
Object[] empty = ArrayUtil.EMPTY_OBJECT_ARRAY;
Diff.Change change = Diff.buildChanges(empty, empty);
assertNull(change);
@@ -64,7 +71,7 @@ public class DiffTest extends TestCase {
IntLCSTest.checkLastChange(change, 0, 0, 3, 0);
}
public void testPerfomance() {
public void testPerfomance() throws FilesTooBigForDiffException {
ArrayList first = new ArrayList();
ArrayList second = new ArrayList();
int max = 1000;
@@ -67,7 +67,7 @@ public class IntLCSTest extends TestCase {
assertEquals(expectedNonDiags, intLCS.execute());
Reindexer reindexer = new Reindexer();
reindexer.idInit(first.length, second.length);
Diff.ChangeBuilder builder = new Diff.ChangeBuilder();
Diff.ChangeBuilder builder = new Diff.ChangeBuilder(0);
reindexer.reindex(intLCS.getPaths(), builder);
return builder.getFirstChange();
}
@@ -69,7 +69,7 @@ public class LinkedDiffPathsTest extends TestCase {
private Diff.Change decode(LinkedDiffPaths paths) {
Reindexer reindexer = new Reindexer();
reindexer.idInit(paths.getXSize(), paths.getYSize());
Diff.ChangeBuilder builder = new Diff.ChangeBuilder();
Diff.ChangeBuilder builder = new Diff.ChangeBuilder(0);
reindexer.reindex(paths, builder);
return builder.getFirstChange();
}
@@ -36,38 +36,11 @@ public class RangesBuilder {
public RangesBuilder(List<String> current, List<String> upToDate, int shift, int uShift) {
myRanges = new LinkedList<Range>();
int shiftBefore = 0;
int minSize = Math.min(upToDate.size(), current.size());
for (int i = 0; i < minSize; i++) {
if (upToDate.get(0).equals(current.get(0))) {
upToDate.remove(0);
current.remove(0);
shiftBefore += 1;
}
else {
break;
}
}
minSize = Math.min(upToDate.size(), current.size());
for (int i = 0; i < minSize; i++) {
if (upToDate.get(upToDate.size() - 1).equals(current.get(current.size() - 1))) {
upToDate.remove(upToDate.size() - 1);
current.remove(current.size() - 1);
}
else {
break;
}
}
Diff.Change ch = Diff.buildChanges(ArrayUtil.toStringArray(upToDate), ArrayUtil.toStringArray(current));
while (ch != null) {
Range range = Range.createOn(ch, shift + shiftBefore, uShift + shiftBefore);
Range range = Range.createOn(ch, shift, uShift);
myRanges.add(range);
ch = ch.link;
}