blob: 1d23009895e8a34927e90e57605e5c300b265040 [file] [log] [blame]
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.prettify.common;
import org.eclipse.jgit.diff.Edit;
import java.util.Iterator;
import java.util.List;
public class EditList {
private final List<Edit> edits;
private final int context;
private final int aSize;
private final int bSize;
public EditList(final List<Edit> edits, final int contextLines,
final int aSize, final int bSize) {
this.edits = edits;
this.context = contextLines;
this.aSize = aSize;
this.bSize = bSize;
}
public List<Edit> getEdits() {
return edits;
}
public Iterable<Hunk> getHunks() {
return new Iterable<Hunk>() {
public Iterator<Hunk> iterator() {
return new Iterator<Hunk>() {
private int curIdx;
public boolean hasNext() {
return curIdx < edits.size();
}
public Hunk next() {
final int c = curIdx;
final int e = findCombinedEnd(c);
curIdx = e + 1;
return new Hunk(c, e);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
private int findCombinedEnd(final int i) {
int end = i + 1;
while (end < edits.size() && (combineA(end) || combineB(end)))
end++;
return end - 1;
}
private boolean combineA(final int i) {
final Edit s = edits.get(i);
final Edit e = edits.get(i - 1);
// + 1 to prevent '... skipping 1 common line ...' messages.
return s.getBeginA() - e.getEndA() <= 2 * context + 1;
}
private boolean combineB(final int i) {
final int s = edits.get(i).getBeginB();
final int e = edits.get(i - 1).getEndB();
// + 1 to prevent '... skipping 1 common line ...' messages.
return s - e <= 2 * context + 1;
}
public class Hunk {
private int curIdx;
private Edit curEdit;
private final int endIdx;
private final Edit endEdit;
private int aCur;
private int bCur;
private final int aEnd;
private final int bEnd;
private Hunk(final int ci, final int ei) {
curIdx = ci;
endIdx = ei;
curEdit = edits.get(curIdx);
endEdit = edits.get(endIdx);
aCur = Math.max(0, curEdit.getBeginA() - context);
bCur = Math.max(0, curEdit.getBeginB() - context);
aEnd = Math.min(aSize, endEdit.getEndA() + context);
bEnd = Math.min(bSize, endEdit.getEndB() + context);
}
public int getCurA() {
return aCur;
}
public int getCurB() {
return bCur;
}
public Edit getCurEdit() {
return curEdit;
}
public int getEndA() {
return aEnd;
}
public int getEndB() {
return bEnd;
}
public void incA() {
aCur++;
}
public void incB() {
bCur++;
}
public void incBoth() {
incA();
incB();
}
public boolean isStartOfFile() {
return aCur == 0 && bCur == 0;
}
public boolean isContextLine() {
return !isModifiedLine();
}
public boolean isDeletedA() {
return curEdit.getBeginA() <= aCur && aCur < curEdit.getEndA();
}
public boolean isInsertedB() {
return curEdit.getBeginB() <= bCur && bCur < curEdit.getEndB();
}
public boolean isModifiedLine() {
return isDeletedA() || isInsertedB();
}
public boolean next() {
if (!in(curEdit)) {
if (curIdx < endIdx) {
curEdit = edits.get(++curIdx);
}
}
return aCur < aEnd || bCur < bEnd;
}
private boolean in(final Edit edit) {
return aCur < edit.getEndA() || bCur < edit.getEndB();
}
}
}