in src/vs/editor/browser/widget/diffEditorWidget.ts [1285:1457]
public getViewZones(): IEditorsZones {
let result: { original: IMyViewZone[]; modified: IMyViewZone[]; } = {
original: [],
modified: []
};
let lineChangeModifiedLength: number = 0;
let lineChangeOriginalLength: number = 0;
let originalEquivalentLineNumber: number = 0;
let modifiedEquivalentLineNumber: number = 0;
let originalEndEquivalentLineNumber: number = 0;
let modifiedEndEquivalentLineNumber: number = 0;
let sortMyViewZones = (a: IMyViewZone, b: IMyViewZone) => {
return a.afterLineNumber - b.afterLineNumber;
};
let addAndCombineIfPossible = (destination: IMyViewZone[], item: IMyViewZone) => {
if (item.domNode === null && destination.length > 0) {
let lastItem = destination[destination.length - 1];
if (lastItem.afterLineNumber === item.afterLineNumber && lastItem.domNode === null) {
lastItem.heightInLines += item.heightInLines;
return;
}
}
destination.push(item);
};
let modifiedForeignVZ = new ForeignViewZonesIterator(this.modifiedForeignVZ);
let originalForeignVZ = new ForeignViewZonesIterator(this.originalForeignVZ);
// In order to include foreign view zones after the last line change, the for loop will iterate once more after the end of the `lineChanges` array
for (let i = 0, length = this.lineChanges.length; i <= length; i++) {
let lineChange = (i < length ? this.lineChanges[i] : null);
if (lineChange !== null) {
originalEquivalentLineNumber = lineChange.originalStartLineNumber + (lineChange.originalEndLineNumber > 0 ? -1 : 0);
modifiedEquivalentLineNumber = lineChange.modifiedStartLineNumber + (lineChange.modifiedEndLineNumber > 0 ? -1 : 0);
lineChangeOriginalLength = (lineChange.originalEndLineNumber > 0 ? (lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1) : 0);
lineChangeModifiedLength = (lineChange.modifiedEndLineNumber > 0 ? (lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1) : 0);
originalEndEquivalentLineNumber = Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber);
modifiedEndEquivalentLineNumber = Math.max(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber);
} else {
// Increase to very large value to get the producing tests of foreign view zones running
originalEquivalentLineNumber += 10000000 + lineChangeOriginalLength;
modifiedEquivalentLineNumber += 10000000 + lineChangeModifiedLength;
originalEndEquivalentLineNumber = originalEquivalentLineNumber;
modifiedEndEquivalentLineNumber = modifiedEquivalentLineNumber;
}
// Each step produces view zones, and after producing them, we try to cancel them out, to avoid empty-empty view zone cases
let stepOriginal: IMyViewZone[] = [];
let stepModified: IMyViewZone[] = [];
// ---------------------------- PRODUCE VIEW ZONES
// [PRODUCE] View zone(s) in original-side due to foreign view zone(s) in modified-side
while (modifiedForeignVZ.current && modifiedForeignVZ.current.afterLineNumber <= modifiedEndEquivalentLineNumber) {
let viewZoneLineNumber: number;
if (modifiedForeignVZ.current.afterLineNumber <= modifiedEquivalentLineNumber) {
viewZoneLineNumber = originalEquivalentLineNumber - modifiedEquivalentLineNumber + modifiedForeignVZ.current.afterLineNumber;
} else {
viewZoneLineNumber = originalEndEquivalentLineNumber;
}
let marginDomNode: HTMLDivElement | null = null;
if (lineChange && lineChange.modifiedStartLineNumber <= modifiedForeignVZ.current.afterLineNumber && modifiedForeignVZ.current.afterLineNumber <= lineChange.modifiedEndLineNumber) {
marginDomNode = this._createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion();
}
stepOriginal.push({
afterLineNumber: viewZoneLineNumber,
heightInLines: modifiedForeignVZ.current.heightInLines,
domNode: null,
marginDomNode: marginDomNode
});
modifiedForeignVZ.advance();
}
// [PRODUCE] View zone(s) in modified-side due to foreign view zone(s) in original-side
while (originalForeignVZ.current && originalForeignVZ.current.afterLineNumber <= originalEndEquivalentLineNumber) {
let viewZoneLineNumber: number;
if (originalForeignVZ.current.afterLineNumber <= originalEquivalentLineNumber) {
viewZoneLineNumber = modifiedEquivalentLineNumber - originalEquivalentLineNumber + originalForeignVZ.current.afterLineNumber;
} else {
viewZoneLineNumber = modifiedEndEquivalentLineNumber;
}
stepModified.push({
afterLineNumber: viewZoneLineNumber,
heightInLines: originalForeignVZ.current.heightInLines,
domNode: null
});
originalForeignVZ.advance();
}
if (lineChange !== null && isChangeOrInsert(lineChange)) {
let r = this._produceOriginalFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength);
if (r) {
stepOriginal.push(r);
}
}
if (lineChange !== null && isChangeOrDelete(lineChange)) {
let r = this._produceModifiedFromDiff(lineChange, lineChangeOriginalLength, lineChangeModifiedLength);
if (r) {
stepModified.push(r);
}
}
// ---------------------------- END PRODUCE VIEW ZONES
// ---------------------------- EMIT MINIMAL VIEW ZONES
// [CANCEL & EMIT] Try to cancel view zones out
let stepOriginalIndex = 0;
let stepModifiedIndex = 0;
stepOriginal = stepOriginal.sort(sortMyViewZones);
stepModified = stepModified.sort(sortMyViewZones);
while (stepOriginalIndex < stepOriginal.length && stepModifiedIndex < stepModified.length) {
let original = stepOriginal[stepOriginalIndex];
let modified = stepModified[stepModifiedIndex];
let originalDelta = original.afterLineNumber - originalEquivalentLineNumber;
let modifiedDelta = modified.afterLineNumber - modifiedEquivalentLineNumber;
if (originalDelta < modifiedDelta) {
addAndCombineIfPossible(result.original, original);
stepOriginalIndex++;
} else if (modifiedDelta < originalDelta) {
addAndCombineIfPossible(result.modified, modified);
stepModifiedIndex++;
} else if (original.shouldNotShrink) {
addAndCombineIfPossible(result.original, original);
stepOriginalIndex++;
} else if (modified.shouldNotShrink) {
addAndCombineIfPossible(result.modified, modified);
stepModifiedIndex++;
} else {
if (original.heightInLines >= modified.heightInLines) {
// modified view zone gets removed
original.heightInLines -= modified.heightInLines;
stepModifiedIndex++;
} else {
// original view zone gets removed
modified.heightInLines -= original.heightInLines;
stepOriginalIndex++;
}
}
}
// [EMIT] Remaining original view zones
while (stepOriginalIndex < stepOriginal.length) {
addAndCombineIfPossible(result.original, stepOriginal[stepOriginalIndex]);
stepOriginalIndex++;
}
// [EMIT] Remaining modified view zones
while (stepModifiedIndex < stepModified.length) {
addAndCombineIfPossible(result.modified, stepModified[stepModifiedIndex]);
stepModifiedIndex++;
}
// ---------------------------- END EMIT MINIMAL VIEW ZONES
}
return {
original: ViewZonesComputer._ensureDomNodes(result.original),
modified: ViewZonesComputer._ensureDomNodes(result.modified),
};
}