mirror of
https://github.com/microsoft/vscode.git
synced 2026-06-01 21:24:50 +01:00
Shift diff up to get to boundaries (#30087)
This commit is contained in:
@@ -799,7 +799,7 @@ export class LcsDiff {
|
||||
do {
|
||||
mergedDiffs = false;
|
||||
|
||||
// Shift all the changes first
|
||||
// Shift all the changes down first
|
||||
for (let i = 0; i < changes.length; i++) {
|
||||
const change = changes[i];
|
||||
const originalStop = (i < changes.length - 1) ? changes[i + 1].originalStart : this.OriginalSequence.getLength();
|
||||
@@ -834,9 +834,105 @@ export class LcsDiff {
|
||||
changes = result;
|
||||
} while (mergedDiffs);
|
||||
|
||||
// Shift changes back up until we hit empty or whitespace-only lines
|
||||
for (let i = changes.length - 1; i >= 0; i--) {
|
||||
const change = changes[i];
|
||||
|
||||
let originalStop = 0;
|
||||
let modifiedStop = 0;
|
||||
if (i > 0) {
|
||||
const prevChange = changes[i - 1];
|
||||
if (prevChange.originalLength > 0) {
|
||||
originalStop = prevChange.originalStart + prevChange.originalLength;
|
||||
}
|
||||
if (prevChange.modifiedLength > 0) {
|
||||
modifiedStop = prevChange.modifiedStart + prevChange.modifiedLength;
|
||||
}
|
||||
}
|
||||
|
||||
const checkOriginal = change.originalLength > 0;
|
||||
const checkModified = change.modifiedLength > 0;
|
||||
|
||||
let bestDelta = 0;
|
||||
let bestScore = this._boundaryScore(change.originalStart, change.originalLength, change.modifiedStart, change.modifiedLength);
|
||||
|
||||
for (let delta = 1; ; delta++) {
|
||||
let originalStart = change.originalStart - delta;
|
||||
let modifiedStart = change.modifiedStart - delta;
|
||||
|
||||
if (originalStart < originalStop || modifiedStart < modifiedStart) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkOriginal && !this.OriginalElementsAreEqual(originalStart, originalStart + change.originalLength)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkModified && !this.ModifiedElementsAreEqual(modifiedStart, modifiedStart + change.modifiedLength)) {
|
||||
break;
|
||||
}
|
||||
|
||||
let score = this._boundaryScore(originalStart, change.originalLength, modifiedStart, change.modifiedLength);
|
||||
|
||||
if (score > bestScore) {
|
||||
bestScore = score;
|
||||
bestDelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
change.originalStart -= bestDelta;
|
||||
change.modifiedStart -= bestDelta;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
private _OriginalIsBoundary(index: number): boolean {
|
||||
if (index <= 0 || index >= this.OriginalSequence.getLength() - 1) {
|
||||
return true;
|
||||
}
|
||||
return /^\s*$/.test(this.OriginalSequence.getElementHash(index));
|
||||
}
|
||||
|
||||
private _OriginalRegionIsBoundary(originalStart: number, originalLength: number): boolean {
|
||||
if (this._OriginalIsBoundary(originalStart) || this._OriginalIsBoundary(originalStart - 1)) {
|
||||
return true;
|
||||
}
|
||||
if (originalLength > 0) {
|
||||
let originalEnd = originalStart + originalLength;
|
||||
if (this._OriginalIsBoundary(originalEnd - 1) || this._OriginalIsBoundary(originalEnd)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _ModifiedIsBoundary(index: number): boolean {
|
||||
if (index <= 0 || index >= this.ModifiedSequence.getLength() - 1) {
|
||||
return true;
|
||||
}
|
||||
return /^\s*$/.test(this.ModifiedSequence.getElementHash(index));
|
||||
}
|
||||
|
||||
private _ModifiedRegionIsBoundary(modifiedStart: number, modifiedLength: number): boolean {
|
||||
if (this._ModifiedIsBoundary(modifiedStart) || this._ModifiedIsBoundary(modifiedStart - 1)) {
|
||||
return true;
|
||||
}
|
||||
if (modifiedLength > 0) {
|
||||
let modifiedEnd = modifiedStart + modifiedLength;
|
||||
if (this._ModifiedIsBoundary(modifiedEnd - 1) || this._ModifiedIsBoundary(modifiedEnd)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _boundaryScore(originalStart: number, originalLength: number, modifiedStart: number, modifiedLength: number): number {
|
||||
let originalScore = (this._OriginalRegionIsBoundary(originalStart, originalLength) ? 1 : 0);
|
||||
let modifiedScore = (this._ModifiedRegionIsBoundary(modifiedStart, modifiedLength) ? 1 : 0);
|
||||
return (originalScore + modifiedScore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the two input DiffChange lists and returns the resulting
|
||||
* list.
|
||||
|
||||
@@ -539,4 +539,42 @@ suite('Editor Diff - DiffComputer', () => {
|
||||
];
|
||||
assertDiff(original, modified, expected, false, true);
|
||||
});
|
||||
|
||||
test('pretty diff 3', () => {
|
||||
var original = [
|
||||
'class A {',
|
||||
' /**',
|
||||
' * m1',
|
||||
' */',
|
||||
' method1() {}',
|
||||
'',
|
||||
' /**',
|
||||
' * m3',
|
||||
' */',
|
||||
' method3() {}',
|
||||
'}',
|
||||
];
|
||||
var modified = [
|
||||
'class A {',
|
||||
' /**',
|
||||
' * m1',
|
||||
' */',
|
||||
' method1() {}',
|
||||
'',
|
||||
' /**',
|
||||
' * m2',
|
||||
' */',
|
||||
' method2() {}',
|
||||
'',
|
||||
' /**',
|
||||
' * m3',
|
||||
' */',
|
||||
' method3() {}',
|
||||
'}',
|
||||
];
|
||||
var expected = [
|
||||
createLineInsertion(7, 11, 6)
|
||||
];
|
||||
assertDiff(original, modified, expected, false, true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user