SideBySide2: Fix failure to load from "ISE EditIterator out of bounds"
Intraline edit information can include a negative delta on the B
side of an edit, for example:
{
a: [...],
b: [...],
edit_a: [[4, 11], [14, 12]]
edit_b: [[4, 66], [37, 41], [-2, 1]]
}
In the edit_a or edit_b block the list pairs are the number of
characters to advance since the last position. -2 encodes the edit
iterator has to go back 2 positions to return the correct value.
This situation arose from an intraline edit list of:
REPLACE( 4-15, 4- 70),
REPLACE(29-41,107-148),
INSERT (62-62,146-147)
The EditList is sorted by the beginA values, where 29 < 62. This
forced the final INSERT to sort in the edit_b list after the REPLACE
at 107. Since 146 < 148 the final edit_b entry was encoded with a
negative delta (148 - 146 = -2).
Update the UI code to accept a negative delta in the iterator. There
are already many /diff responses with negative delta that will be
cached by browsers for 7 days.
There may be other issues with the intraline diff algorithm that
allows it to create this final INSERT span within the REPLACE
span, but the code is essentially unchanged for many years in
Gerrit Code Review. Handle the corner case for now in the UI while
the server code is investigated further.
Change-Id: Ibec0fc845356af7c02f25acac23c4e709f7c3a34
This commit is contained in:
committed by
David Pursehouse
parent
22daa1e5e2
commit
52c73b831d
@@ -22,8 +22,8 @@ import net.codemirror.lib.LineCharacter;
|
|||||||
class EditIterator {
|
class EditIterator {
|
||||||
private final JsArrayString lines;
|
private final JsArrayString lines;
|
||||||
private final int startLine;
|
private final int startLine;
|
||||||
private int currLineIndex;
|
private int line;
|
||||||
private int currLineOffset;
|
private int pos;
|
||||||
|
|
||||||
EditIterator(JsArrayString lineArray, int start) {
|
EditIterator(JsArrayString lineArray, int start) {
|
||||||
lines = lineArray;
|
lines = lineArray;
|
||||||
@@ -31,27 +31,44 @@ class EditIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LineCharacter advance(int numOfChar) {
|
LineCharacter advance(int numOfChar) {
|
||||||
while (currLineIndex < lines.length()) {
|
numOfChar = adjustForNegativeDelta(numOfChar);
|
||||||
int lengthWithNewline =
|
|
||||||
lines.get(currLineIndex).length() - currLineOffset + 1;
|
while (line < lines.length()) {
|
||||||
if (numOfChar < lengthWithNewline) {
|
int len = lines.get(line).length() - pos + 1; // + 1 for LF
|
||||||
|
if (numOfChar < len) {
|
||||||
LineCharacter at = LineCharacter.create(
|
LineCharacter at = LineCharacter.create(
|
||||||
startLine + currLineIndex,
|
startLine + line,
|
||||||
numOfChar + currLineOffset);
|
numOfChar + pos);
|
||||||
currLineOffset += numOfChar;
|
pos += numOfChar;
|
||||||
return at;
|
return at;
|
||||||
}
|
}
|
||||||
numOfChar -= lengthWithNewline;
|
|
||||||
advanceLine();
|
numOfChar -= len;
|
||||||
|
line++;
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
if (numOfChar == 0) {
|
if (numOfChar == 0) {
|
||||||
return LineCharacter.create(startLine + currLineIndex, 0);
|
return LineCharacter.create(startLine + line, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("EditIterator index out of bound");
|
|
||||||
|
throw new IllegalStateException("EditIterator index out of bounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void advanceLine() {
|
private int adjustForNegativeDelta(int n) {
|
||||||
currLineIndex++;
|
while (n < 0) {
|
||||||
currLineOffset = 0;
|
if (-n <= pos) {
|
||||||
|
pos += n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n += pos;
|
||||||
|
line--;
|
||||||
|
if (line < 0) {
|
||||||
|
throw new IllegalStateException("EditIterator index out of bounds");
|
||||||
|
}
|
||||||
|
pos = lines.get(line).length() + 1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ public class EditIteratorTest extends GwtTest {
|
|||||||
lines.push("3rd");
|
lines.push("3rd");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNegativeAdvance() {
|
||||||
|
EditIterator i = new EditIterator(lines, 0);
|
||||||
|
assertLineChsEqual(LineCharacter.create(1, 1), i.advance(5));
|
||||||
|
assertLineChsEqual(LineCharacter.create(0, 3), i.advance(-2));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoAdvance() {
|
public void testNoAdvance() {
|
||||||
EditIterator iter = new EditIterator(lines, 0);
|
EditIterator iter = new EditIterator(lines, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user