diff: simplify LineNumberConvertor

It used to store "Unified <-> (Left, Right)" line mappings
while Left and Right sides can be stored independently.
This commit is contained in:
Aleksey Pivovarov
2017-02-02 18:21:32 +03:00
committed by Aleksey Pivovarov
parent e8f26d8edc
commit dfcf95ecae
8 changed files with 164 additions and 168 deletions
@@ -15,7 +15,6 @@
*/
package com.intellij.diff.tools.fragmented;
import com.intellij.diff.util.Side;
import com.intellij.util.SmartList;
import gnu.trove.TIntFunction;
import org.jetbrains.annotations.NotNull;
@@ -27,54 +26,32 @@ import java.util.TreeMap;
public class LineNumberConvertor {
// Oneside -> Twoside
@NotNull private final TreeMap<Integer, Integer> myFragments1;
@NotNull private final TreeMap<Integer, Integer> myFragments2;
// Twoside -> Oneside
@NotNull private final TreeMap<Integer, Integer> myInvertedFragments1;
@NotNull private final TreeMap<Integer, Integer> myInvertedFragments2;
@NotNull private final Corrector myCorrector = new Corrector();
private LineNumberConvertor(@NotNull TreeMap<Integer, Integer> fragments1,
@NotNull TreeMap<Integer, Integer> fragments2,
@NotNull TreeMap<Integer, Integer> invertedFragments1,
@NotNull TreeMap<Integer, Integer> invertedFragments2) {
@NotNull TreeMap<Integer, Integer> invertedFragments1) {
myFragments1 = fragments1;
myFragments2 = fragments2;
myInvertedFragments1 = invertedFragments1;
myInvertedFragments2 = invertedFragments2;
}
public int convert1(int value) {
return convert(value, Side.LEFT, true, false);
public int convert(int value) {
return convert(value, true, false);
}
public int convert2(int value) {
return convert(value, Side.RIGHT, true, false);
public int convertInv(int value) {
return convert(value, false, false);
}
public int convertInv1(int value) {
return convert(value, Side.LEFT, false, false);
public int convertApproximate(int value) {
return convert(value, true, true);
}
public int convertInv2(int value) {
return convert(value, Side.RIGHT, false, false);
}
public int convertApproximate1(int value) {
return convert(value, Side.LEFT, true, true);
}
public int convertApproximate2(int value) {
return convert(value, Side.RIGHT, true, true);
}
public int convertApproximateInv1(int value) {
return convert(value, Side.LEFT, false, true);
}
public int convertApproximateInv2(int value) {
return convert(value, Side.RIGHT, false, true);
public int convertApproximateInv(int value) {
return convert(value, false, true);
}
//
@@ -82,24 +59,22 @@ public class LineNumberConvertor {
//
@NotNull
public TIntFunction createConvertor1() {
return this::convert1;
public TIntFunction createConvertor() {
return this::convert;
}
@NotNull
public TIntFunction createConvertor2() {
return this::convert2;
public int convert(int value, boolean fromOneside, boolean approximate) {
return myCorrector.convertCorrected(value, fromOneside, approximate);
}
private int convert(int value, @NotNull Side side, boolean fromOneside, boolean approximate) {
return myCorrector.convertCorrected(value, side, fromOneside, approximate);
}
/*
* Both oneside and one of the sides were changed in a same way. We should update converters, because of changed shift.
/**
* Oneside was changed. We should update converters, because of changed shift.
*
* @param synchronous true - twoside were changed in a same way
* false - twoside was not changed
*/
public void handleOnesideChange(int startLine, int endLine, int shift, @NotNull Side masterSide) {
myCorrector.handleOnesideChange(startLine, endLine, shift, masterSide);
public void handleOnesideChange(int startLine, int endLine, int shift, boolean synchronous) {
myCorrector.handleOnesideChange(startLine, endLine, shift, synchronous);
}
@@ -107,9 +82,8 @@ public class LineNumberConvertor {
* @param approximate false: return exact matching between lines, and -1 if it's impossible
* true: return 'good enough' position, even if exact matching is impossible
*/
private int convertRaw(@NotNull Side side, boolean fromOneside, int value, boolean approximate) {
TreeMap<Integer, Integer> fragments = fromOneside ? side.select(myFragments1, myFragments2)
: side.select(myInvertedFragments1, myInvertedFragments2);
private int convertRaw(boolean fromOneside, int value, boolean approximate) {
TreeMap<Integer, Integer> fragments = fromOneside ? myFragments1 : myInvertedFragments1;
if (approximate) {
Map.Entry<Integer, Integer> floor = fragments.floorEntry(value);
@@ -130,12 +104,9 @@ public class LineNumberConvertor {
public static class Builder {
@NotNull private final TreeMap<Integer, Integer> myFragments1 = new TreeMap<>();
@NotNull private final TreeMap<Integer, Integer> myFragments2 = new TreeMap<>();
@NotNull private final TreeMap<Integer, Integer> myInvertedFragments1 = new TreeMap<>();
@NotNull private final TreeMap<Integer, Integer> myInvertedFragments2 = new TreeMap<>();
public void put1(int start, int newStart, int length) {
public void put(int start, int newStart, int length) {
myFragments1.put(start, newStart);
myFragments1.put(start + length, -1);
@@ -143,17 +114,9 @@ public class LineNumberConvertor {
myInvertedFragments1.put(newStart + length, -1);
}
public void put2(int start, int newStart, int length) {
myFragments2.put(start, newStart);
myFragments2.put(start + length, -1);
myInvertedFragments2.put(newStart, start);
myInvertedFragments2.put(newStart + length, -1);
}
@NotNull
public LineNumberConvertor build() {
return new LineNumberConvertor(myFragments1, myFragments2, myInvertedFragments1, myInvertedFragments2);
return new LineNumberConvertor(myFragments1, myInvertedFragments1);
}
}
@@ -204,36 +167,40 @@ public class LineNumberConvertor {
private final List<CorrectedChange> myChanges = new SmartList<>();
@SuppressWarnings("UnnecessaryLocalVariable")
public void handleOnesideChange(int startLine, int endLine, int shift, @NotNull Side masterSide) {
int oldOnesideStart = startLine;
int oldTwosideStart = convert(startLine, masterSide, true, false);
assert oldTwosideStart != -1;
public void handleOnesideChange(int startLine, int endLine, int shift, boolean synchronous) {
int oldLength = endLine - startLine;
int newLength = oldLength + shift;
myChanges.add(new CorrectedChange(oldOnesideStart, oldTwosideStart, oldLength, newLength, masterSide));
}
if (synchronous) {
int oldTwosideStart = convert(startLine, true, false);
assert oldTwosideStart != -1;
public int convertCorrected(int value, @NotNull Side side, boolean fromOneside, boolean approximate) {
if (fromOneside) {
return convertFromOneside(value, side, approximate, myChanges.size() - 1);
myChanges.add(new CorrectedChange(startLine, oldTwosideStart, oldLength, newLength));
}
else {
return convertFromTwoside(value, side, approximate, myChanges.size() - 1);
myChanges.add(new CorrectedChange(startLine, oldLength, newLength));
}
}
private int convertFromTwoside(int value, @NotNull Side side, boolean approximate, int index) {
public int convertCorrected(int value, boolean fromOneside, boolean approximate) {
if (fromOneside) {
return convertFromOneside(value, approximate, myChanges.size() - 1);
}
else {
return convertFromTwoside(value, approximate, myChanges.size() - 1);
}
}
private int convertFromTwoside(int value, boolean approximate, int index) {
if (index < 0) {
return convertRaw(side, false, value, approximate);
return convertRaw(false, value, approximate);
}
CorrectedChange change = myChanges.get(index);
int shift = change.newLength - change.oldLength;
if (change.side != side) { // ?u' -> ?o'
int converted = convertFromTwoside(value, side, approximate, index - 1);
if (!change.synchronous) { // ?u' -> ?o'
int converted = convertFromTwoside(value, approximate, index - 1);
if (converted < change.startOneside) { // Su' -> So'
// Su' == Su; So' == So
// value == Su'; converted == So
@@ -253,26 +220,26 @@ public class LineNumberConvertor {
}
else { // ?m '-> ?o'
if (value < change.startTwoside) { // Sm' -> So'
return convertFromTwoside(value, side, approximate, index - 1);
return convertFromTwoside(value, approximate, index - 1);
}
if (value >= change.startTwoside + change.newLength) { // Em' -> Eo'
// Em' == Em + shift; Eo' == Eo + shift
// value == Em'; converted == Eo
int converted = convertFromTwoside(value - shift, side, approximate, index - 1);
int converted = convertFromTwoside(value - shift, approximate, index - 1);
return append(converted, shift);
}
// Mm' -> Mo'
// Ao == Ao'; Am == Am'; Mo' - Ao' == Mm' - Am'
// convertedStart == Ao; value - change.startOneside == Mm' - Am'
int convertedStart = convertFromTwoside(change.startTwoside, side, approximate, index - 1);
int convertedStart = convertFromTwoside(change.startTwoside, approximate, index - 1);
return append(convertedStart, value - change.startTwoside);
}
}
private int convertFromOneside(int value, @NotNull Side side, boolean approximate, int index) {
private int convertFromOneside(int value, boolean approximate, int index) {
if (index < 0) {
return convertRaw(side, true, value, approximate);
return convertRaw(true, value, approximate);
}
CorrectedChange change = myChanges.get(index);
@@ -281,25 +248,25 @@ public class LineNumberConvertor {
if (value < change.startOneside) { // So' -> Sm', So' -> Su'
// So' == So; Sm' == Sm; Su' == Su
// value = So'
return convertFromOneside(value, side, approximate, index - 1);
return convertFromOneside(value, approximate, index - 1);
}
if (value >= change.startOneside + change.newLength) { // Eo' -> Em', Eo' -> Eu'
// Eo' == Eo + shift; Em' == Em + shift; Eu' == Eu
// value = Eo'
int converted = convertFromOneside(value - shift, side, approximate, index - 1);
return append(converted, side == change.side ? shift : 0);
int converted = convertFromOneside(value - shift, approximate, index - 1);
return append(converted, change.synchronous ? shift : 0);
}
if (side != change.side) { // Mo' -> Mu'
if (!change.synchronous) { // Mo' -> Mu'
if (!approximate) return -1;
// we can't convert Mo' into Mo. And thus get valid Mu/Mu'.
// return: Au'
return convertFromOneside(change.startOneside, side, approximate, index - 1);
return convertFromOneside(change.startOneside, approximate, index - 1);
}
else { // Mo' -> Mm'
// Ao == Ao'; Am == Am'; Mo' - Ao' == Mm' - Am'
// value = Mo'
int convertedStart = convertFromOneside(change.startOneside, side, approximate, index - 1);
int convertedStart = convertFromOneside(change.startOneside, approximate, index - 1);
return append(convertedStart, value - change.startOneside);
}
}
@@ -310,18 +277,29 @@ public class LineNumberConvertor {
}
private static class CorrectedChange {
public final boolean synchronous;
public final int startOneside;
public final int startTwoside;
public final int oldLength;
public final int newLength;
@NotNull public final Side side;
public CorrectedChange(int startOneside, int startTwoside, int oldLength, int newLength, @NotNull Side side) {
public CorrectedChange(int startOneside, int oldLength, int newLength) {
this.synchronous = false;
this.startTwoside = -1;
this.startOneside = startOneside;
this.oldLength = oldLength;
this.newLength = newLength;
}
public CorrectedChange(int startOneside, int startTwoside, int oldLength, int newLength) {
this.synchronous = true;
this.startOneside = startOneside;
this.startTwoside = startTwoside;
this.oldLength = oldLength;
this.newLength = newLength;
this.side = side;
}
}
}
@@ -286,14 +286,15 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
FileType fileType = content2.getContentType() == null ? content1.getContentType() : content2.getContentType();
LineNumberConvertor convertor = builder.getConvertor();
LineNumberConvertor convertor1 = builder.getConvertor1();
LineNumberConvertor convertor2 = builder.getConvertor2();
List<LineRange> changedLines = builder.getChangedLines();
boolean isContentsEqual = builder.isEqual();
CombinedEditorData editorData = new CombinedEditorData(builder.getText(), data.getHighlighter(), data.getRangeHighlighter(), fileType,
convertor.createConvertor1(), convertor.createConvertor2());
convertor1.createConvertor(), convertor2.createConvertor());
return apply(editorData, builder.getBlocks(), convertor, changedLines, isContentsEqual);
return apply(editorData, builder.getBlocks(), convertor1, convertor2, changedLines, isContentsEqual);
}
catch (DiffTooBigException e) {
return () -> {
@@ -360,7 +361,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
@NotNull
private Runnable apply(@NotNull final CombinedEditorData data,
@NotNull final List<ChangedBlock> blocks,
@NotNull final LineNumberConvertor convertor,
@NotNull final LineNumberConvertor convertor1,
@NotNull final LineNumberConvertor convertor2,
@NotNull final List<LineRange> changedLines,
final boolean isContentsEqual) {
return () -> {
@@ -417,7 +419,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
}
myChangedBlockData = new ChangedBlockData(diffChanges, guarderRangeBlocks, convertor, isContentsEqual);
myChangedBlockData = new ChangedBlockData(diffChanges, guarderRangeBlocks, convertor1, convertor2, isContentsEqual);
int newCaretLine = transferLineToOneside(oldCaretLineTwoside.second,
@@ -454,9 +456,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
@CalledInAwt
public int transferLineToOnesideStrict(@NotNull Side side, int line) {
if (myChangedBlockData == null) return -1;
LineNumberConvertor lineConvertor = myChangedBlockData.getLineNumberConvertor();
return side.isLeft() ? lineConvertor.convertInv1(line) : lineConvertor.convertInv2(line);
return myChangedBlockData.getLineNumberConvertor(side).convertInv(line);
}
/*
@@ -465,9 +465,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
@CalledInAwt
public int transferLineFromOnesideStrict(@NotNull Side side, int line) {
if (myChangedBlockData == null) return -1;
LineNumberConvertor lineConvertor = myChangedBlockData.getLineNumberConvertor();
return side.isLeft() ? lineConvertor.convert1(line) : lineConvertor.convert2(line);
return myChangedBlockData.getLineNumberConvertor(side).convert(line);
}
/*
@@ -476,9 +474,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
@CalledInAwt
public int transferLineToOneside(@NotNull Side side, int line) {
if (myChangedBlockData == null) return line;
LineNumberConvertor lineConvertor = myChangedBlockData.getLineNumberConvertor();
return side.isLeft() ? lineConvertor.convertApproximateInv1(line) : lineConvertor.convertApproximateInv2(line);
return myChangedBlockData.getLineNumberConvertor(side).convertApproximateInv(line);
}
/*
@@ -495,22 +491,23 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
return Pair.create(lines, myMasterSide);
}
LineNumberConvertor lineConvertor = myChangedBlockData.getLineNumberConvertor();
LineNumberConvertor lineConvertor1 = myChangedBlockData.getLineNumberConvertor(Side.LEFT);
LineNumberConvertor lineConvertor2 = myChangedBlockData.getLineNumberConvertor(Side.RIGHT);
Side side = myMasterSide;
lines[0] = lineConvertor.convert1(line);
lines[1] = lineConvertor.convert2(line);
lines[0] = lineConvertor1.convert(line);
lines[1] = lineConvertor2.convert(line);
if (lines[0] == -1 && lines[1] == -1) {
lines[0] = lineConvertor.convertApproximate1(line);
lines[1] = lineConvertor.convertApproximate2(line);
lines[0] = lineConvertor1.convertApproximate(line);
lines[1] = lineConvertor2.convertApproximate(line);
}
else if (lines[0] == -1) {
lines[0] = lineConvertor.convertApproximate1(line);
lines[0] = lineConvertor1.convertApproximate(line);
side = Side.RIGHT;
}
else if (lines[1] == -1) {
lines[1] = lineConvertor.convertApproximate2(line);
lines[1] = lineConvertor2.convertApproximate(line);
side = Side.LEFT;
}
@@ -579,8 +576,10 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
change.processChange(line1, line2, shift);
}
LineNumberConvertor lineNumberConvertor = myChangedBlockData.getLineNumberConvertor();
lineNumberConvertor.handleOnesideChange(line1, line2, shift, myMasterSide);
LineNumberConvertor masterConvertor = myChangedBlockData.getLineNumberConvertor(myMasterSide);
LineNumberConvertor slaveConvertor = myChangedBlockData.getLineNumberConvertor(myMasterSide.other());
masterConvertor.handleOnesideChange(line1, line2, shift, true);
slaveConvertor.handleOnesideChange(line1, line2, shift, false);
}
finally {
// TODO: we can avoid marking state out-of-date in some simple cases (like in SimpleDiffViewer)
@@ -1185,16 +1184,19 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
private static class ChangedBlockData {
@NotNull private final List<UnifiedDiffChange> myDiffChanges;
@NotNull private final List<RangeMarker> myGuardedRangeBlocks;
@NotNull private final LineNumberConvertor myLineNumberConvertor;
@NotNull private final LineNumberConvertor myLineNumberConvertor1;
@NotNull private final LineNumberConvertor myLineNumberConvertor2;
private final boolean myIsContentsEqual;
public ChangedBlockData(@NotNull List<UnifiedDiffChange> diffChanges,
@NotNull List<RangeMarker> guarderRangeBlocks,
@NotNull LineNumberConvertor lineNumberConvertor,
@NotNull LineNumberConvertor lineNumberConvertor1,
@NotNull LineNumberConvertor lineNumberConvertor2,
boolean isContentsEqual) {
myDiffChanges = diffChanges;
myGuardedRangeBlocks = guarderRangeBlocks;
myLineNumberConvertor = lineNumberConvertor;
myLineNumberConvertor1 = lineNumberConvertor1;
myLineNumberConvertor2 = lineNumberConvertor2;
myIsContentsEqual = isContentsEqual;
}
@@ -1209,8 +1211,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
}
@NotNull
public LineNumberConvertor getLineNumberConvertor() {
return myLineNumberConvertor;
public LineNumberConvertor getLineNumberConvertor(@NotNull Side side) {
return side.select(myLineNumberConvertor1, myLineNumberConvertor2);
}
public boolean isContentsEqual() {
@@ -35,7 +35,8 @@ class UnifiedFragmentBuilder {
@NotNull private final StringBuilder myBuilder = new StringBuilder();
@NotNull private final List<ChangedBlock> myBlocks = new ArrayList<>();
@NotNull private final List<HighlightRange> myRanges = new ArrayList<>();
@NotNull private final LineNumberConvertor.Builder myConvertor = new LineNumberConvertor.Builder();
@NotNull private final LineNumberConvertor.Builder myConvertor1 = new LineNumberConvertor.Builder();
@NotNull private final LineNumberConvertor.Builder myConvertor2 = new LineNumberConvertor.Builder();
@NotNull private final List<LineRange> myChangedLines = new ArrayList<>();
public UnifiedFragmentBuilder(@NotNull List<LineFragment> fragments,
@@ -151,10 +152,10 @@ class UnifiedFragmentBuilder {
myBuilder.append('\n');
if (startLine1 != -1) {
myConvertor.put1(totalLines, startLine1, lines + 1);
myConvertor1.put(totalLines, startLine1, lines + 1);
}
if (startLine2 != -1) {
myConvertor.put2(totalLines, startLine2, lines + 1);
myConvertor2.put(totalLines, startLine2, lines + 1);
}
totalLines += lines + 1;
@@ -189,8 +190,13 @@ class UnifiedFragmentBuilder {
}
@NotNull
public LineNumberConvertor getConvertor() {
return myConvertor.build();
public LineNumberConvertor getConvertor1() {
return myConvertor1.build();
}
@NotNull
public LineNumberConvertor getConvertor2() {
return myConvertor2.build();
}
@NotNull
@@ -125,42 +125,44 @@ class LineNumberConvertorCorrectorTest : UsefulTestCase() {
}
private class TestBuilder {
private val builder = LineNumberConvertor.Builder()
private val builder1 = LineNumberConvertor.Builder()
private val builder2 = LineNumberConvertor.Builder()
private var maxLength = 0 // search for strict matchings in this boundaries (*2 - just in case)
fun equal(onesideStart: Int, twosideStart: Int, length: Int, side: Side) {
if (side.isLeft) {
builder.put1(onesideStart, twosideStart, length)
builder1.put(onesideStart, twosideStart, length)
}
else {
builder.put2(onesideStart, twosideStart, length)
builder2.put(onesideStart, twosideStart, length)
}
maxLength = Math.max(maxLength, onesideStart + length)
maxLength = Math.max(maxLength, twosideStart + length)
}
fun finish(): Test = Test(builder.build(), maxLength)
fun finish(): Test = Test(builder1.build(), builder2.build(), maxLength)
}
private class Test(val convertor: LineNumberConvertor, var length: Int) {
private class Test(val convertor1: LineNumberConvertor, val convertor2: LineNumberConvertor, var length: Int) {
fun change(onesideLine: Int, oldLength: Int, newLength: Int, side: Side) {
convertor.handleOnesideChange(onesideLine, onesideLine + oldLength, newLength - oldLength, side)
convertor1.handleOnesideChange(onesideLine, onesideLine + oldLength, newLength - oldLength, side == Side.LEFT)
convertor2.handleOnesideChange(onesideLine, onesideLine + oldLength, newLength - oldLength, side == Side.RIGHT)
length = Math.max(length, length + newLength - oldLength)
}
fun checkStrictSymmetrical() {
for (i in 0..length * 2) {
val value1 = convertor.convertInv1(i)
if (value1 != -1) assertEquals(i, convertor.convert1(value1))
val value1 = convertor1.convertInv(i)
if (value1 != -1) assertEquals(i, convertor1.convert(value1))
val value2 = convertor.convertInv2(i)
if (value2 != -1) assertEquals(i, convertor.convert2(value2))
val value2 = convertor2.convertInv(i)
if (value2 != -1) assertEquals(i, convertor2.convert(value2))
val value3 = convertor.convert1(i)
if (value3 != -1) assertEquals(i, convertor.convertInv1(value3))
val value3 = convertor1.convert(i)
if (value3 != -1) assertEquals(i, convertor1.convertInv(value3))
val value4 = convertor.convert2(i)
if (value4 != -1) assertEquals(i, convertor.convertInv2(value4))
val value4 = convertor2.convert(i)
if (value4 != -1) assertEquals(i, convertor2.convertInv(value4))
}
}
@@ -168,8 +170,8 @@ class LineNumberConvertorCorrectorTest : UsefulTestCase() {
var counter1 = 0
var counter2 = 0
for (i in 0..length * 2) {
if (convertor.convert1(i) != -1) counter1++
if (convertor.convert2(i) != -1) counter2++
if (convertor1.convert(i) != -1) counter1++
if (convertor2.convert(i) != -1) counter2++
}
assertEquals(minimumMatched1, counter1)
assertEquals(minimumMatched2, counter2)
@@ -178,12 +180,12 @@ class LineNumberConvertorCorrectorTest : UsefulTestCase() {
@Suppress("unused")
fun printMatchings() {
for (i in 0..length * 2 - 1) {
val value = convertor.convert1(i)
val value = convertor1.convert(i)
if (value != -1) println("L: $i - $value")
}
for (i in 0..length * 2 - 1) {
val value = convertor.convert2(i)
val value = convertor2.convert(i)
if (value != -1) println("R: $i - $value")
}
}
@@ -112,16 +112,16 @@ class LineNumberConvertorTest : UsefulTestCase() {
put(6, 5, 2)
},
{
assertEquals(0, convertor.convertApproximate1(0))
assertEquals(2, convertor.convertApproximate1(1))
assertEquals(3, convertor.convertApproximate1(2))
assertEquals(3, convertor.convertApproximate1(3))
assertEquals(3, convertor.convertApproximate1(4))
assertEquals(3, convertor.convertApproximate1(5))
assertEquals(5, convertor.convertApproximate1(6))
assertEquals(6, convertor.convertApproximate1(7))
assertEquals(7, convertor.convertApproximate1(8))
assertEquals(7, convertor.convertApproximate1(9))
assertEquals(0, convertor.convertApproximate(0))
assertEquals(2, convertor.convertApproximate(1))
assertEquals(3, convertor.convertApproximate(2))
assertEquals(3, convertor.convertApproximate(3))
assertEquals(3, convertor.convertApproximate(4))
assertEquals(3, convertor.convertApproximate(5))
assertEquals(5, convertor.convertApproximate(6))
assertEquals(6, convertor.convertApproximate(7))
assertEquals(7, convertor.convertApproximate(8))
assertEquals(7, convertor.convertApproximate(9))
}
)
}
@@ -141,7 +141,7 @@ class LineNumberConvertorTest : UsefulTestCase() {
private val builder = LineNumberConvertor.Builder()
fun put(left: Int, right: Int, length: Int) {
builder.put1(left, right, length)
builder.put(left, right, length)
}
fun finish(): Test = Test(builder.build())
@@ -150,20 +150,20 @@ class LineNumberConvertorTest : UsefulTestCase() {
private class Test(val convertor: LineNumberConvertor) {
fun checkMatch(left: Int, right: Int, length: Int) {
for (i in 0..length - 1) {
assertEquals(right + i, convertor.convert1(left + i))
assertEquals(left + i, convertor.convertInv1(right + i))
assertEquals(right + i, convertor.convert(left + i))
assertEquals(left + i, convertor.convertInv(right + i))
}
}
fun checkEmpty(start: Int, end: Int) {
for (i in start..end) {
assertEquals(-1, convertor.convert1(i))
assertEquals(-1, convertor.convert(i))
}
}
fun checkEmptyInv(start: Int, end: Int) {
for (i in start..end) {
assertEquals(-1, convertor.convertInv1(i))
assertEquals(-1, convertor.convertInv(i))
}
}
}
@@ -62,7 +62,8 @@ class UnifiedFragmentBuilderAutoTest : DiffTestCase() {
val ignoreWhitespaces = policy !== ComparisonPolicy.DEFAULT
val text = builder.text
val blocks = builder.blocks
val convertor = builder.convertor
val convertor1 = builder.convertor1
val convertor2 = builder.convertor2
val changedLines = builder.changedLines
val ranges = builder.ranges
@@ -80,12 +81,12 @@ class UnifiedFragmentBuilderAutoTest : DiffTestCase() {
val endLine2 = fragment.endLine2
for (i in startLine1 until endLine1) {
val targetLine = convertor.convertInv1(i)
val targetLine = convertor1.convertInv(i)
assertTrue(targetLine != -1)
assertTrue(isLineChanged(targetLine, changedLines))
}
for (i in startLine2 until endLine2) {
val targetLine = convertor.convertInv2(i)
val targetLine = convertor2.convertInv(i)
assertTrue(targetLine != -1)
assertTrue(isLineChanged(targetLine, changedLines))
}
@@ -303,8 +303,9 @@ class ApplyPatchViewer implements DataProvider, Disposable {
Document patchDocument = myPatchEditor.getDocument();
patchDocument.setText(builder.getPatchContent());
LineNumberConvertor convertor = builder.getLineConvertor();
myPatchEditor.getGutterComponentEx().setLineNumberConvertor(convertor.createConvertor1(), convertor.createConvertor2());
LineNumberConvertor convertor1 = builder.getLineConvertor1();
LineNumberConvertor convertor2 = builder.getLineConvertor2();
myPatchEditor.getGutterComponentEx().setLineNumberConvertor(convertor1.createConvertor(), convertor2.createConvertor());
TIntArrayList lines = builder.getSeparatorLines();
for (int i = 0; i < lines.size(); i++) {
@@ -29,7 +29,8 @@ import java.util.List;
class PatchChangeBuilder {
@NotNull private final StringBuilder myBuilder = new StringBuilder();
@NotNull private final List<Hunk> myHunks = new ArrayList<>();
@NotNull private final LineNumberConvertor.Builder myConvertor = new LineNumberConvertor.Builder();
@NotNull private final LineNumberConvertor.Builder myConvertor1 = new LineNumberConvertor.Builder();
@NotNull private final LineNumberConvertor.Builder myConvertor2 = new LineNumberConvertor.Builder();
@NotNull private final TIntArrayList myChangedLines = new TIntArrayList();
private int totalLines = 0;
@@ -63,8 +64,8 @@ class PatchChangeBuilder {
appendLines(hunk.getInsertedLines());
int hunkEnd = totalLines;
myConvertor.put1(deletion, beforeRange.start + contextBefore.size(), insertion - deletion);
myConvertor.put2(insertion, afterRange.start + contextBefore.size(), hunkEnd - insertion);
myConvertor1.put(deletion, beforeRange.start + contextBefore.size(), insertion - deletion);
myConvertor2.put(insertion, afterRange.start + contextBefore.size(), hunkEnd - insertion);
addContext(contextAfter, beforeRange.end - contextAfter.size(), afterRange.end - contextAfter.size());
@@ -79,8 +80,8 @@ class PatchChangeBuilder {
}
private void addContext(@NotNull List<String> context, int beforeLineNumber, int afterLineNumber) {
myConvertor.put1(totalLines, beforeLineNumber, context.size());
myConvertor.put2(totalLines, afterLineNumber, context.size());
myConvertor1.put(totalLines, beforeLineNumber, context.size());
myConvertor2.put(totalLines, afterLineNumber, context.size());
appendLines(context);
}
@@ -112,8 +113,13 @@ class PatchChangeBuilder {
}
@NotNull
public LineNumberConvertor getLineConvertor() {
return myConvertor.build();
public LineNumberConvertor getLineConvertor1() {
return myConvertor1.build();
}
@NotNull
public LineNumberConvertor getLineConvertor2() {
return myConvertor2.build();
}
@NotNull