Separates diff processing from diff building
Moves the diff-processing functionality of the gr-diff-builder component into a new gr-diff-processor component which exposes a promise-based interface. This is step one of creating an asynchronous (non-blocking) diff rendering system. As much as possible, this change is a transfer of code (with tests) from one component to another, making it easier to verify that functionality has not changed. Cleanup of the code, and refactoring it into a more-testable form will come with later changes. Feature: Issue 3916 Change-Id: I875b03b20bf953b128cbe3c5001ba1f8eba12c61
This commit is contained in:
@@ -28,9 +28,7 @@
|
|||||||
GrDiffBuilderSideBySide.prototype);
|
GrDiffBuilderSideBySide.prototype);
|
||||||
GrDiffBuilderImage.prototype.constructor = GrDiffBuilderImage;
|
GrDiffBuilderImage.prototype.constructor = GrDiffBuilderImage;
|
||||||
|
|
||||||
GrDiffBuilderImage.prototype.emitDiff = function() {
|
GrDiffBuilderImage.prototype.renderDiffImages = function() {
|
||||||
this.emitGroup(this._groups[0]);
|
|
||||||
|
|
||||||
var section = this._createElement('tbody', 'image-diff');
|
var section = this._createElement('tbody', 'image-diff');
|
||||||
|
|
||||||
this._emitImagePair(section);
|
this._emitImagePair(section);
|
||||||
|
@@ -14,12 +14,14 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../gr-diff-processor/gr-diff-processor.html">
|
||||||
|
|
||||||
<dom-module id="gr-diff-builder">
|
<dom-module id="gr-diff-builder">
|
||||||
<template>
|
<template>
|
||||||
<div class="contentWrapper">
|
<div class="contentWrapper">
|
||||||
<content></content>
|
<content></content>
|
||||||
</div>
|
</div>
|
||||||
|
<gr-diff-processor id="processor"></gr-diff-processor>
|
||||||
</template>
|
</template>
|
||||||
<script src="../gr-diff/gr-diff-line.js"></script>
|
<script src="../gr-diff/gr-diff-line.js"></script>
|
||||||
<script src="../gr-diff/gr-diff-group.js"></script>
|
<script src="../gr-diff/gr-diff-group.js"></script>
|
||||||
@@ -59,7 +61,11 @@ limitations under the License.
|
|||||||
|
|
||||||
render: function(diff, comments, prefs) {
|
render: function(diff, comments, prefs) {
|
||||||
this._builder = this._getDiffBuilder(diff, comments, prefs);
|
this._builder = this._getDiffBuilder(diff, comments, prefs);
|
||||||
this._renderDiff();
|
|
||||||
|
this.$.processor.context = prefs.context;
|
||||||
|
this.$.processor.keyLocations = this._getCommentLocations(comments);
|
||||||
|
this.$.processor.process(diff.content)
|
||||||
|
.then(this._renderDiff.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
getLineElByChild: function(node) {
|
getLineElByChild: function(node) {
|
||||||
@@ -176,7 +182,7 @@ limitations under the License.
|
|||||||
},
|
},
|
||||||
|
|
||||||
showContext: function(newGroups, sectionEl) {
|
showContext: function(newGroups, sectionEl) {
|
||||||
var groups = this._builder._groups;
|
var groups = this._builder.groups;
|
||||||
// TODO(viktard): Polyfill findIndex for IE10.
|
// TODO(viktard): Polyfill findIndex for IE10.
|
||||||
var contextIndex = groups.findIndex(function(group) {
|
var contextIndex = groups.findIndex(function(group) {
|
||||||
return group.element == sectionEl;
|
return group.element == sectionEl;
|
||||||
@@ -207,9 +213,14 @@ limitations under the License.
|
|||||||
throw Error('Unsupported diff view mode: ' + this.viewMode);
|
throw Error('Unsupported diff view mode: ' + this.viewMode);
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderDiff: function() {
|
_renderDiff: function(groups) {
|
||||||
|
this._builder.groups = groups;
|
||||||
|
|
||||||
this._clearDiffContent();
|
this._clearDiffContent();
|
||||||
this.emitDiff();
|
this.emitDiff();
|
||||||
|
if (this.isImageDiff) {
|
||||||
|
this._builder.renderDiffImages();
|
||||||
|
}
|
||||||
this.async(function() {
|
this.async(function() {
|
||||||
this.fire('render');
|
this.fire('render');
|
||||||
}, 1);
|
}, 1);
|
||||||
@@ -218,6 +229,23 @@ limitations under the License.
|
|||||||
_clearDiffContent: function() {
|
_clearDiffContent: function() {
|
||||||
this.diffElement.innerHTML = null;
|
this.diffElement.innerHTML = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_getCommentLocations: function(comments) {
|
||||||
|
var result = {
|
||||||
|
left: {},
|
||||||
|
right: {},
|
||||||
|
};
|
||||||
|
for (var side in comments) {
|
||||||
|
if (side !== GrDiffBuilder.Side.LEFT &&
|
||||||
|
side !== GrDiffBuilder.Side.RIGHT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
comments[side].forEach(function(c) {
|
||||||
|
result[side][c.line || GrDiffLine.FILE] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@@ -22,10 +22,7 @@
|
|||||||
this._comments = comments;
|
this._comments = comments;
|
||||||
this._prefs = prefs;
|
this._prefs = prefs;
|
||||||
this._outputEl = outputEl;
|
this._outputEl = outputEl;
|
||||||
this._groups = [];
|
this.groups = [];
|
||||||
|
|
||||||
this._commentLocations = this._getCommentLocations(comments);
|
|
||||||
this._processContent(diff.content, this._groups, prefs.context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrDiffBuilder.LESS_THAN_CODE = '<'.charCodeAt(0);
|
GrDiffBuilder.LESS_THAN_CODE = '<'.charCodeAt(0);
|
||||||
@@ -63,8 +60,8 @@
|
|||||||
var PARTIAL_CONTEXT_AMOUNT = 10;
|
var PARTIAL_CONTEXT_AMOUNT = 10;
|
||||||
|
|
||||||
GrDiffBuilder.prototype.emitDiff = function() {
|
GrDiffBuilder.prototype.emitDiff = function() {
|
||||||
for (var i = 0; i < this._groups.length; i++) {
|
for (var i = 0; i < this.groups.length; i++) {
|
||||||
this.emitGroup(this._groups[i]);
|
this.emitGroup(this.groups[i]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,8 +76,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
GrDiffBuilder.prototype.renderSection = function(element) {
|
GrDiffBuilder.prototype.renderSection = function(element) {
|
||||||
for (var i = 0; i < this._groups.length; i++) {
|
for (var i = 0; i < this.groups.length; i++) {
|
||||||
var group = this._groups[i];
|
var group = this.groups[i];
|
||||||
if (group.element === element) {
|
if (group.element === element) {
|
||||||
var newElement = this.buildSectionElement(group);
|
var newElement = this.buildSectionElement(group);
|
||||||
group.element.parentElement.replaceChild(newElement, group.element);
|
group.element.parentElement.replaceChild(newElement, group.element);
|
||||||
@@ -93,8 +90,8 @@
|
|||||||
GrDiffBuilder.prototype.getGroupsByLineRange = function(
|
GrDiffBuilder.prototype.getGroupsByLineRange = function(
|
||||||
startLine, endLine, opt_side) {
|
startLine, endLine, opt_side) {
|
||||||
var groups = [];
|
var groups = [];
|
||||||
for (var i = 0; i < this._groups.length; i++) {
|
for (var i = 0; i < this.groups.length; i++) {
|
||||||
var group = this._groups[i];
|
var group = this.groups[i];
|
||||||
if (group.lines.length === 0) {
|
if (group.lines.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -139,196 +136,11 @@
|
|||||||
function(group) { return group.element; });
|
function(group) { return group.element; });
|
||||||
};
|
};
|
||||||
|
|
||||||
GrDiffBuilder.prototype._processContent = function(content, groups, context) {
|
|
||||||
this._appendFileComments(groups);
|
|
||||||
|
|
||||||
var WHOLE_FILE = -1;
|
|
||||||
context = content.length > 1 ? context : WHOLE_FILE;
|
|
||||||
|
|
||||||
var lineNums = {
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
};
|
|
||||||
content = this._splitCommonGroupsWithComments(content, lineNums);
|
|
||||||
for (var i = 0; i < content.length; i++) {
|
|
||||||
var group = content[i];
|
|
||||||
var lines = [];
|
|
||||||
|
|
||||||
if (group[GrDiffBuilder.GroupType.BOTH] !== undefined) {
|
|
||||||
var rows = group[GrDiffBuilder.GroupType.BOTH];
|
|
||||||
this._appendCommonLines(rows, lines, lineNums);
|
|
||||||
|
|
||||||
var hiddenRange = [context, rows.length - context];
|
|
||||||
if (i === 0) {
|
|
||||||
hiddenRange[0] = 0;
|
|
||||||
} else if (i === content.length - 1) {
|
|
||||||
hiddenRange[1] = rows.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context !== WHOLE_FILE && hiddenRange[1] - hiddenRange[0] > 0) {
|
|
||||||
this._insertContextGroups(groups, lines, hiddenRange);
|
|
||||||
} else {
|
|
||||||
groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, lines));
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (group[GrDiffBuilder.GroupType.REMOVED] !== undefined) {
|
|
||||||
var highlights = undefined;
|
|
||||||
if (group[GrDiffBuilder.Highlights.REMOVED] !== undefined) {
|
|
||||||
highlights = this._normalizeIntralineHighlights(
|
|
||||||
group[GrDiffBuilder.GroupType.REMOVED],
|
|
||||||
group[GrDiffBuilder.Highlights.REMOVED]);
|
|
||||||
}
|
|
||||||
this._appendRemovedLines(group[GrDiffBuilder.GroupType.REMOVED], lines,
|
|
||||||
lineNums, highlights);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (group[GrDiffBuilder.GroupType.ADDED] !== undefined) {
|
|
||||||
var highlights = undefined;
|
|
||||||
if (group[GrDiffBuilder.Highlights.ADDED] !== undefined) {
|
|
||||||
highlights = this._normalizeIntralineHighlights(
|
|
||||||
group[GrDiffBuilder.GroupType.ADDED],
|
|
||||||
group[GrDiffBuilder.Highlights.ADDED]);
|
|
||||||
}
|
|
||||||
this._appendAddedLines(group[GrDiffBuilder.GroupType.ADDED], lines,
|
|
||||||
lineNums, highlights);
|
|
||||||
}
|
|
||||||
groups.push(new GrDiffGroup(GrDiffGroup.Type.DELTA, lines));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._appendFileComments = function(groups) {
|
|
||||||
var line = new GrDiffLine(GrDiffLine.Type.BOTH);
|
|
||||||
line.beforeNumber = GrDiffLine.FILE;
|
|
||||||
line.afterNumber = GrDiffLine.FILE;
|
|
||||||
groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, [line]));
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._getCommentLocations = function(comments) {
|
|
||||||
var result = {
|
|
||||||
left: {},
|
|
||||||
right: {},
|
|
||||||
};
|
|
||||||
for (var side in comments) {
|
|
||||||
if (side !== GrDiffBuilder.Side.LEFT &&
|
|
||||||
side !== GrDiffBuilder.Side.RIGHT) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
comments[side].forEach(function(c) {
|
|
||||||
result[side][c.line || GrDiffLine.FILE] = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._commentIsAtLineNum = function(side, lineNum) {
|
GrDiffBuilder.prototype._commentIsAtLineNum = function(side, lineNum) {
|
||||||
return this._commentLocations[side][lineNum] === true;
|
return this._commentLocations[side][lineNum] === true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// In order to show comments out of the bounds of the selected context,
|
// TODO (wyatta): Move this completely into the processor.
|
||||||
// treat them as separate chunks within the model so that the content (and
|
|
||||||
// context surrounding it) renders correctly.
|
|
||||||
GrDiffBuilder.prototype._splitCommonGroupsWithComments = function(content,
|
|
||||||
lineNums) {
|
|
||||||
var result = [];
|
|
||||||
var leftLineNum = lineNums.left;
|
|
||||||
var rightLineNum = lineNums.right;
|
|
||||||
for (var i = 0; i < content.length; i++) {
|
|
||||||
if (!content[i].ab) {
|
|
||||||
result.push(content[i]);
|
|
||||||
if (content[i].a) {
|
|
||||||
leftLineNum += content[i].a.length;
|
|
||||||
}
|
|
||||||
if (content[i].b) {
|
|
||||||
rightLineNum += content[i].b.length;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var chunk = content[i].ab;
|
|
||||||
var currentChunk = {ab: []};
|
|
||||||
for (var j = 0; j < chunk.length; j++) {
|
|
||||||
leftLineNum++;
|
|
||||||
rightLineNum++;
|
|
||||||
if (this._commentIsAtLineNum(GrDiffBuilder.Side.LEFT, leftLineNum) ||
|
|
||||||
this._commentIsAtLineNum(GrDiffBuilder.Side.RIGHT, rightLineNum)) {
|
|
||||||
if (currentChunk.ab && currentChunk.ab.length > 0) {
|
|
||||||
result.push(currentChunk);
|
|
||||||
currentChunk = {ab: []};
|
|
||||||
}
|
|
||||||
result.push({ab: [chunk[j]]});
|
|
||||||
} else {
|
|
||||||
currentChunk.ab.push(chunk[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// != instead of !== because we want to cover both undefined and null.
|
|
||||||
if (currentChunk.ab != null && currentChunk.ab.length > 0) {
|
|
||||||
result.push(currentChunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The `highlights` array consists of a list of <skip length, mark length>
|
|
||||||
// pairs, where the skip length is the number of characters between the
|
|
||||||
// end of the previous edit and the start of this edit, and the mark
|
|
||||||
// length is the number of edited characters following the skip. The start
|
|
||||||
// of the edits is from the beginning of the related diff content lines.
|
|
||||||
//
|
|
||||||
// Note that the implied newline character at the end of each line is
|
|
||||||
// included in the length calculation, and thus it is possible for the
|
|
||||||
// edits to span newlines.
|
|
||||||
//
|
|
||||||
// A line highlight object consists of three fields:
|
|
||||||
// - contentIndex: The index of the diffChunk `content` field (the line
|
|
||||||
// being referred to).
|
|
||||||
// - startIndex: Where the highlight should begin.
|
|
||||||
// - endIndex: (optional) Where the highlight should end. If omitted, the
|
|
||||||
// highlight is meant to be a continuation onto the next line.
|
|
||||||
GrDiffBuilder.prototype._normalizeIntralineHighlights = function(content,
|
|
||||||
highlights) {
|
|
||||||
var contentIndex = 0;
|
|
||||||
var idx = 0;
|
|
||||||
var normalized = [];
|
|
||||||
for (var i = 0; i < highlights.length; i++) {
|
|
||||||
var line = content[contentIndex] + '\n';
|
|
||||||
var hl = highlights[i];
|
|
||||||
var j = 0;
|
|
||||||
while (j < hl[0]) {
|
|
||||||
if (idx === line.length) {
|
|
||||||
idx = 0;
|
|
||||||
line = content[++contentIndex] + '\n';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
var lineHighlight = {
|
|
||||||
contentIndex: contentIndex,
|
|
||||||
startIndex: idx,
|
|
||||||
};
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
while (line && j < hl[1]) {
|
|
||||||
if (idx === line.length) {
|
|
||||||
idx = 0;
|
|
||||||
line = content[++contentIndex] + '\n';
|
|
||||||
normalized.push(lineHighlight);
|
|
||||||
lineHighlight = {
|
|
||||||
contentIndex: contentIndex,
|
|
||||||
startIndex: idx,
|
|
||||||
};
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
lineHighlight.endIndex = idx;
|
|
||||||
normalized.push(lineHighlight);
|
|
||||||
}
|
|
||||||
return normalized;
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._insertContextGroups = function(groups, lines,
|
GrDiffBuilder.prototype._insertContextGroups = function(groups, lines,
|
||||||
hiddenRange) {
|
hiddenRange) {
|
||||||
var linesBeforeCtx = lines.slice(0, hiddenRange[0]);
|
var linesBeforeCtx = lines.slice(0, hiddenRange[0]);
|
||||||
@@ -350,46 +162,6 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
GrDiffBuilder.prototype._appendCommonLines = function(rows, lines, lineNums) {
|
|
||||||
for (var i = 0; i < rows.length; i++) {
|
|
||||||
var line = new GrDiffLine(GrDiffLine.Type.BOTH);
|
|
||||||
line.text = rows[i];
|
|
||||||
line.beforeNumber = ++lineNums.left;
|
|
||||||
line.afterNumber = ++lineNums.right;
|
|
||||||
lines.push(line);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._appendRemovedLines = function(rows, lines, lineNums,
|
|
||||||
opt_highlights) {
|
|
||||||
for (var i = 0; i < rows.length; i++) {
|
|
||||||
var line = new GrDiffLine(GrDiffLine.Type.REMOVE);
|
|
||||||
line.text = rows[i];
|
|
||||||
line.beforeNumber = ++lineNums.left;
|
|
||||||
if (opt_highlights) {
|
|
||||||
line.highlights = opt_highlights.filter(function(hl) {
|
|
||||||
return hl.contentIndex === i;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
lines.push(line);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._appendAddedLines = function(rows, lines, lineNums,
|
|
||||||
opt_highlights) {
|
|
||||||
for (var i = 0; i < rows.length; i++) {
|
|
||||||
var line = new GrDiffLine(GrDiffLine.Type.ADD);
|
|
||||||
line.text = rows[i];
|
|
||||||
line.afterNumber = ++lineNums.right;
|
|
||||||
if (opt_highlights) {
|
|
||||||
line.highlights = opt_highlights.filter(function(hl) {
|
|
||||||
return hl.contentIndex === i;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
lines.push(line);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
GrDiffBuilder.prototype._createContextControl = function(section, line) {
|
GrDiffBuilder.prototype._createContextControl = function(section, line) {
|
||||||
if (!line.contextGroup || !line.contextGroup.lines.length) {
|
if (!line.contextGroup || !line.contextGroup.lines.length) {
|
||||||
return null;
|
return null;
|
||||||
|
@@ -18,11 +18,23 @@ limitations under the License.
|
|||||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||||
<title>gr-diff-builder</title>
|
<title>gr-diff-builder</title>
|
||||||
|
|
||||||
|
<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
|
||||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||||
<script src="../gr-diff/gr-diff-line.js"></script>
|
<script src="../gr-diff/gr-diff-line.js"></script>
|
||||||
<script src="../gr-diff/gr-diff-group.js"></script>
|
<script src="../gr-diff/gr-diff-group.js"></script>
|
||||||
<script src="gr-diff-builder.js"></script>
|
<script src="gr-diff-builder.js"></script>
|
||||||
|
|
||||||
|
<link rel="import" href="gr-diff-builder.html">
|
||||||
|
|
||||||
|
<test-fixture id="basic">
|
||||||
|
<template>
|
||||||
|
<gr-diff-builder>
|
||||||
|
<table id="diffTable"></table>
|
||||||
|
</gr-diff-builder>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
suite('gr-diff-builder tests', function() {
|
suite('gr-diff-builder tests', function() {
|
||||||
var builder;
|
var builder;
|
||||||
@@ -36,205 +48,6 @@ limitations under the License.
|
|||||||
builder = new GrDiffBuilder({content: []}, {left: [], right: []}, prefs);
|
builder = new GrDiffBuilder({content: []}, {left: [], right: []}, prefs);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('process loaded content', function() {
|
|
||||||
var content = [
|
|
||||||
{
|
|
||||||
ab: [
|
|
||||||
'<!DOCTYPE html>',
|
|
||||||
'<meta charset="utf-8">',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
a: [
|
|
||||||
' Welcome ',
|
|
||||||
' to the wooorld of tomorrow!',
|
|
||||||
],
|
|
||||||
b: [
|
|
||||||
' Hello, world!',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ab: [
|
|
||||||
'Leela: This is the only place the ship can’t hear us, so ',
|
|
||||||
'everyone pretend to shower.',
|
|
||||||
'Fry: Same as every day. Got it.',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
];
|
|
||||||
var groups = [];
|
|
||||||
|
|
||||||
builder._processContent(content, groups, -1);
|
|
||||||
|
|
||||||
assert.equal(groups.length, 4);
|
|
||||||
|
|
||||||
var group = groups[0];
|
|
||||||
assert.equal(group.type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(group.lines.length, 1);
|
|
||||||
assert.equal(group.lines[0].text, '');
|
|
||||||
assert.equal(group.lines[0].beforeNumber, GrDiffLine.FILE);
|
|
||||||
assert.equal(group.lines[0].afterNumber, GrDiffLine.FILE);
|
|
||||||
|
|
||||||
group = groups[1];
|
|
||||||
assert.equal(group.type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(group.lines.length, 2);
|
|
||||||
assert.equal(group.lines.length, 2);
|
|
||||||
|
|
||||||
function beforeNumberFn(l) { return l.beforeNumber; }
|
|
||||||
function afterNumberFn(l) { return l.afterNumber; }
|
|
||||||
function textFn(l) { return l.text; }
|
|
||||||
|
|
||||||
assert.deepEqual(group.lines.map(beforeNumberFn), [1, 2]);
|
|
||||||
assert.deepEqual(group.lines.map(afterNumberFn), [1, 2]);
|
|
||||||
assert.deepEqual(group.lines.map(textFn), [
|
|
||||||
'<!DOCTYPE html>',
|
|
||||||
'<meta charset="utf-8">',
|
|
||||||
]);
|
|
||||||
|
|
||||||
group = groups[2];
|
|
||||||
assert.equal(group.type, GrDiffGroup.Type.DELTA);
|
|
||||||
assert.equal(group.lines.length, 3);
|
|
||||||
assert.equal(group.adds.length, 1);
|
|
||||||
assert.equal(group.removes.length, 2);
|
|
||||||
assert.deepEqual(group.removes.map(beforeNumberFn), [3, 4]);
|
|
||||||
assert.deepEqual(group.adds.map(afterNumberFn), [3]);
|
|
||||||
assert.deepEqual(group.removes.map(textFn), [
|
|
||||||
' Welcome ',
|
|
||||||
' to the wooorld of tomorrow!',
|
|
||||||
]);
|
|
||||||
assert.deepEqual(group.adds.map(textFn), [
|
|
||||||
' Hello, world!',
|
|
||||||
]);
|
|
||||||
|
|
||||||
group = groups[3];
|
|
||||||
assert.equal(group.type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(group.lines.length, 3);
|
|
||||||
assert.deepEqual(group.lines.map(beforeNumberFn), [5, 6, 7]);
|
|
||||||
assert.deepEqual(group.lines.map(afterNumberFn), [4, 5, 6]);
|
|
||||||
assert.deepEqual(group.lines.map(textFn), [
|
|
||||||
'Leela: This is the only place the ship can’t hear us, so ',
|
|
||||||
'everyone pretend to shower.',
|
|
||||||
'Fry: Same as every day. Got it.',
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('insert context groups', function() {
|
|
||||||
var content = [
|
|
||||||
{ab: []},
|
|
||||||
{a: ['all work and no play make andybons a dull boy']},
|
|
||||||
{ab: []},
|
|
||||||
{b: ['elgoog elgoog elgoog']},
|
|
||||||
{ab: []},
|
|
||||||
];
|
|
||||||
for (var i = 0; i < 100; i++) {
|
|
||||||
content[0].ab.push('all work and no play make jack a dull boy');
|
|
||||||
content[4].ab.push('all work and no play make jill a dull girl');
|
|
||||||
}
|
|
||||||
for (var i = 0; i < 5; i++) {
|
|
||||||
content[2].ab.push('no tv and no beer make homer go crazy');
|
|
||||||
}
|
|
||||||
var groups = [];
|
|
||||||
var context = 10;
|
|
||||||
|
|
||||||
builder._processContent(content, groups, context);
|
|
||||||
|
|
||||||
assert.equal(groups[0].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[0].lines.length, 1);
|
|
||||||
assert.equal(groups[0].lines[0].text, '');
|
|
||||||
assert.equal(groups[0].lines[0].beforeNumber, GrDiffLine.FILE);
|
|
||||||
assert.equal(groups[0].lines[0].afterNumber, GrDiffLine.FILE);
|
|
||||||
|
|
||||||
assert.equal(groups[1].type, GrDiffGroup.Type.CONTEXT_CONTROL);
|
|
||||||
assert.instanceOf(groups[1].lines[0].contextGroup, GrDiffGroup);
|
|
||||||
assert.equal(groups[1].lines[0].contextGroup.lines.length, 90);
|
|
||||||
groups[1].lines[0].contextGroup.lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[0].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[2].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[2].lines.length, context);
|
|
||||||
groups[2].lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[0].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[3].type, GrDiffGroup.Type.DELTA);
|
|
||||||
assert.equal(groups[3].lines.length, 1);
|
|
||||||
assert.equal(groups[3].removes.length, 1);
|
|
||||||
assert.equal(groups[3].removes[0].text,
|
|
||||||
'all work and no play make andybons a dull boy');
|
|
||||||
|
|
||||||
assert.equal(groups[4].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[4].lines.length, 5);
|
|
||||||
groups[4].lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[2].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[5].type, GrDiffGroup.Type.DELTA);
|
|
||||||
assert.equal(groups[5].lines.length, 1);
|
|
||||||
assert.equal(groups[5].adds.length, 1);
|
|
||||||
assert.equal(groups[5].adds[0].text, 'elgoog elgoog elgoog');
|
|
||||||
|
|
||||||
assert.equal(groups[6].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[6].lines.length, context);
|
|
||||||
groups[6].lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[4].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[7].type, GrDiffGroup.Type.CONTEXT_CONTROL);
|
|
||||||
assert.instanceOf(groups[7].lines[0].contextGroup, GrDiffGroup);
|
|
||||||
assert.equal(groups[7].lines[0].contextGroup.lines.length, 90);
|
|
||||||
groups[7].lines[0].contextGroup.lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[4].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
content = [
|
|
||||||
{a: ['all work and no play make andybons a dull boy']},
|
|
||||||
{ab: []},
|
|
||||||
{b: ['elgoog elgoog elgoog']},
|
|
||||||
];
|
|
||||||
for (var i = 0; i < 50; i++) {
|
|
||||||
content[1].ab.push('no tv and no beer make homer go crazy');
|
|
||||||
}
|
|
||||||
groups = [];
|
|
||||||
|
|
||||||
builder._processContent(content, groups, 10);
|
|
||||||
|
|
||||||
assert.equal(groups[0].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[0].lines.length, 1);
|
|
||||||
assert.equal(groups[0].lines[0].text, '');
|
|
||||||
assert.equal(groups[0].lines[0].beforeNumber, GrDiffLine.FILE);
|
|
||||||
assert.equal(groups[0].lines[0].afterNumber, GrDiffLine.FILE);
|
|
||||||
|
|
||||||
assert.equal(groups[1].type, GrDiffGroup.Type.DELTA);
|
|
||||||
assert.equal(groups[1].lines.length, 1);
|
|
||||||
assert.equal(groups[1].removes.length, 1);
|
|
||||||
assert.equal(groups[1].removes[0].text,
|
|
||||||
'all work and no play make andybons a dull boy');
|
|
||||||
|
|
||||||
assert.equal(groups[2].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[2].lines.length, context);
|
|
||||||
groups[2].lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[1].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[3].type, GrDiffGroup.Type.CONTEXT_CONTROL);
|
|
||||||
assert.instanceOf(groups[3].lines[0].contextGroup, GrDiffGroup);
|
|
||||||
assert.equal(groups[3].lines[0].contextGroup.lines.length, 30);
|
|
||||||
groups[3].lines[0].contextGroup.lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[1].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[4].type, GrDiffGroup.Type.BOTH);
|
|
||||||
assert.equal(groups[4].lines.length, context);
|
|
||||||
groups[4].lines.forEach(function(l) {
|
|
||||||
assert.equal(l.text, content[1].ab[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
assert.equal(groups[5].type, GrDiffGroup.Type.DELTA);
|
|
||||||
assert.equal(groups[5].lines.length, 1);
|
|
||||||
assert.equal(groups[5].adds.length, 1);
|
|
||||||
assert.equal(groups[5].adds[0].text, 'elgoog elgoog elgoog');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('context control buttons', function() {
|
test('context control buttons', function() {
|
||||||
var section = {};
|
var section = {};
|
||||||
var line = {contextGroup: {lines: []}};
|
var line = {contextGroup: {lines: []}};
|
||||||
@@ -412,153 +225,11 @@ limitations under the License.
|
|||||||
[{id: 'l3', line: 3}, {id: 'r5', line: 5}]);
|
[{id: 'l3', line: 3}, {id: 'r5', line: 5}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('break up common diff chunks', function() {
|
|
||||||
builder._commentLocations = {
|
|
||||||
left: {1: true},
|
|
||||||
right: {10: true},
|
|
||||||
};
|
|
||||||
var lineNums = {
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
};
|
|
||||||
var content = [
|
|
||||||
{
|
|
||||||
ab: [
|
|
||||||
'Copyright (C) 2015 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.',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
var result = builder._splitCommonGroupsWithComments(content, lineNums);
|
|
||||||
assert.deepEqual(result, [
|
|
||||||
{
|
|
||||||
ab: ['Copyright (C) 2015 The Android Open Source Project'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ab: [
|
|
||||||
'',
|
|
||||||
'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, ',
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ab: ['software distributed under the License is distributed on an '],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ab: [
|
|
||||||
'"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.',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('intraline normalization', function() {
|
|
||||||
// The content and highlights are in the format returned by the Gerrit
|
|
||||||
// REST API.
|
|
||||||
var content = [
|
|
||||||
' <section class="summary">',
|
|
||||||
' <gr-linked-text content="' +
|
|
||||||
'[[_computeCurrentRevisionMessage(change)]]"></gr-linked-text>',
|
|
||||||
' </section>',
|
|
||||||
];
|
|
||||||
var highlights = [
|
|
||||||
[31, 34], [42, 26]
|
|
||||||
];
|
|
||||||
var results = GrDiffBuilder.prototype._normalizeIntralineHighlights(
|
|
||||||
content, highlights);
|
|
||||||
assert.deepEqual(results, [
|
|
||||||
{
|
|
||||||
contentIndex: 0,
|
|
||||||
startIndex: 31,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 1,
|
|
||||||
startIndex: 0,
|
|
||||||
endIndex: 33,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 1,
|
|
||||||
startIndex: 75,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 2,
|
|
||||||
startIndex: 0,
|
|
||||||
endIndex: 6,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
content = [
|
|
||||||
' this._path = value.path;',
|
|
||||||
'',
|
|
||||||
' // When navigating away from the page, there is a ' +
|
|
||||||
'possibility that the',
|
|
||||||
' // patch number is no longer a part of the URL ' +
|
|
||||||
'(say when navigating to',
|
|
||||||
' // the top-level change info view) and therefore ' +
|
|
||||||
'undefined in `params`.',
|
|
||||||
' if (!this._patchRange.patchNum) {',
|
|
||||||
];
|
|
||||||
highlights = [
|
|
||||||
[14, 17],
|
|
||||||
[11, 70],
|
|
||||||
[12, 67],
|
|
||||||
[12, 67],
|
|
||||||
[14, 29],
|
|
||||||
];
|
|
||||||
results = GrDiffBuilder.prototype._normalizeIntralineHighlights(content,
|
|
||||||
highlights);
|
|
||||||
assert.deepEqual(results, [
|
|
||||||
{
|
|
||||||
contentIndex: 0,
|
|
||||||
startIndex: 14,
|
|
||||||
endIndex: 31,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 2,
|
|
||||||
startIndex: 8,
|
|
||||||
endIndex: 78,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 3,
|
|
||||||
startIndex: 11,
|
|
||||||
endIndex: 78,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 4,
|
|
||||||
startIndex: 11,
|
|
||||||
endIndex: 78,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
contentIndex: 5,
|
|
||||||
startIndex: 12,
|
|
||||||
endIndex: 41,
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
suite('rendering', function() {
|
suite('rendering', function() {
|
||||||
var content;
|
var content;
|
||||||
var outputEl;
|
var outputEl;
|
||||||
|
|
||||||
setup(function() {
|
setup(function(done) {
|
||||||
var prefs = {
|
var prefs = {
|
||||||
line_length: 10,
|
line_length: 10,
|
||||||
show_tabs: true,
|
show_tabs: true,
|
||||||
@@ -577,32 +248,38 @@ limitations under the License.
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
outputEl = document.createElement('out');
|
element = fixture('basic');
|
||||||
builder =
|
outputEl = element.queryEffectiveChildren('#diffTable');
|
||||||
new GrDiffBuilder(
|
element.addEventListener('render', function() {
|
||||||
{content: content}, {left: [], right: []}, prefs, outputEl);
|
done();
|
||||||
builder.buildSectionElement = function(group) {
|
});
|
||||||
var section = document.createElement('stub');
|
sinon.stub(element, '_getDiffBuilder', function() {
|
||||||
section.textContent = group.lines.reduce(function(acc, line) {
|
var builder = new GrDiffBuilder(
|
||||||
return acc + line.text;
|
{content: content}, {left: [], right: []}, prefs, outputEl);
|
||||||
}, '');
|
builder.buildSectionElement = function(group) {
|
||||||
return section;
|
var section = document.createElement('stub');
|
||||||
};
|
section.textContent = group.lines.reduce(function(acc, line) {
|
||||||
builder.emitDiff();
|
return acc + line.text;
|
||||||
|
}, '');
|
||||||
|
return section;
|
||||||
|
};
|
||||||
|
return builder;
|
||||||
|
});
|
||||||
|
element.render({ content: content }, {left: [], right: []}, prefs);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renderSection', function() {
|
test('renderSection', function() {
|
||||||
var section = outputEl.querySelector('stub:nth-of-type(2)');
|
var section = outputEl.querySelector('stub:nth-of-type(2)');
|
||||||
var prevInnerHTML = section.innerHTML;
|
var prevInnerHTML = section.innerHTML;
|
||||||
section.innerHTML = 'wiped';
|
section.innerHTML = 'wiped';
|
||||||
builder.renderSection(section);
|
element._builder.renderSection(section);
|
||||||
section = outputEl.querySelector('stub:nth-of-type(2)');
|
section = outputEl.querySelector('stub:nth-of-type(2)');
|
||||||
assert.equal(section.innerHTML, prevInnerHTML);
|
assert.equal(section.innerHTML, prevInnerHTML);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('getSectionsByLineRange one line', function() {
|
test('getSectionsByLineRange one line', function() {
|
||||||
var section = outputEl.querySelector('stub:nth-of-type(2)');
|
var section = outputEl.querySelector('stub:nth-of-type(2)');
|
||||||
var sections = builder.getSectionsByLineRange(1, 1, 'left');
|
var sections = element._builder.getSectionsByLineRange(1, 1, 'left');
|
||||||
assert.equal(sections.length, 1);
|
assert.equal(sections.length, 1);
|
||||||
assert.strictEqual(sections[0], section);
|
assert.strictEqual(sections[0], section);
|
||||||
});
|
});
|
||||||
@@ -612,7 +289,7 @@ limitations under the License.
|
|||||||
outputEl.querySelector('stub:nth-of-type(2)'),
|
outputEl.querySelector('stub:nth-of-type(2)'),
|
||||||
outputEl.querySelector('stub:nth-of-type(3)'),
|
outputEl.querySelector('stub:nth-of-type(3)'),
|
||||||
];
|
];
|
||||||
var sections = builder.getSectionsByLineRange(1, 2, 'left');
|
var sections = element._builder.getSectionsByLineRange(1, 2, 'left');
|
||||||
assert.equal(sections.length, 2);
|
assert.equal(sections.length, 2);
|
||||||
assert.strictEqual(sections[0], section[0]);
|
assert.strictEqual(sections[0], section[0]);
|
||||||
assert.strictEqual(sections[1], section[1]);
|
assert.strictEqual(sections[1], section[1]);
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2016 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
|
||||||
|
<dom-module id="gr-diff-processor">
|
||||||
|
<script src="../gr-diff/gr-diff-line.js"></script>
|
||||||
|
<script src="../gr-diff/gr-diff-group.js"></script>
|
||||||
|
<script src="gr-diff-processor.js"></script>
|
||||||
|
</dom-module>
|
@@ -0,0 +1,303 @@
|
|||||||
|
// Copyright (C) 2016 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.
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var WHOLE_FILE = -1;
|
||||||
|
|
||||||
|
var DiffSide = {
|
||||||
|
LEFT: 'left',
|
||||||
|
RIGHT: 'right',
|
||||||
|
};
|
||||||
|
|
||||||
|
var DiffGroupType = {
|
||||||
|
ADDED: 'b',
|
||||||
|
BOTH: 'ab',
|
||||||
|
REMOVED: 'a',
|
||||||
|
};
|
||||||
|
|
||||||
|
var DiffHighlights = {
|
||||||
|
ADDED: 'edit_b',
|
||||||
|
REMOVED: 'edit_a',
|
||||||
|
};
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'gr-diff-processor',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of context around collapsed groups.
|
||||||
|
*/
|
||||||
|
context: Number,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of groups output by the processor.
|
||||||
|
*/
|
||||||
|
groups: {
|
||||||
|
type: Array,
|
||||||
|
notify: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locations that should not be collapsed, including the locations of
|
||||||
|
* comments.
|
||||||
|
*/
|
||||||
|
keyLocations: {
|
||||||
|
type: Object,
|
||||||
|
value: function() { return {left: {}, right: {}}; },
|
||||||
|
},
|
||||||
|
|
||||||
|
_content: Object,
|
||||||
|
},
|
||||||
|
|
||||||
|
process: function(content) {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
var groups = [];
|
||||||
|
this._processContent(content, groups, this.context);
|
||||||
|
this.groups = groups;
|
||||||
|
resolve(groups);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
|
_processContent: function(content, groups, context) {
|
||||||
|
this._appendFileComments(groups);
|
||||||
|
|
||||||
|
context = content.length > 1 ? context : WHOLE_FILE;
|
||||||
|
|
||||||
|
var lineNums = {
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
};
|
||||||
|
content = this._splitCommonGroupsWithComments(content, lineNums);
|
||||||
|
for (var i = 0; i < content.length; i++) {
|
||||||
|
var group = content[i];
|
||||||
|
var lines = [];
|
||||||
|
|
||||||
|
if (group[DiffGroupType.BOTH] !== undefined) {
|
||||||
|
var rows = group[DiffGroupType.BOTH];
|
||||||
|
this._appendCommonLines(rows, lines, lineNums);
|
||||||
|
|
||||||
|
var hiddenRange = [context, rows.length - context];
|
||||||
|
if (i === 0) {
|
||||||
|
hiddenRange[0] = 0;
|
||||||
|
} else if (i === content.length - 1) {
|
||||||
|
hiddenRange[1] = rows.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context !== WHOLE_FILE && hiddenRange[1] - hiddenRange[0] > 0) {
|
||||||
|
this._insertContextGroups(groups, lines, hiddenRange);
|
||||||
|
} else {
|
||||||
|
groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, lines));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group[DiffGroupType.REMOVED] !== undefined) {
|
||||||
|
var highlights = undefined;
|
||||||
|
if (group[DiffHighlights.REMOVED] !== undefined) {
|
||||||
|
highlights = this._normalizeIntralineHighlights(
|
||||||
|
group[DiffGroupType.REMOVED],
|
||||||
|
group[DiffHighlights.REMOVED]);
|
||||||
|
}
|
||||||
|
this._appendRemovedLines(group[DiffGroupType.REMOVED], lines,
|
||||||
|
lineNums, highlights);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group[DiffGroupType.ADDED] !== undefined) {
|
||||||
|
var highlights = undefined;
|
||||||
|
if (group[DiffHighlights.ADDED] !== undefined) {
|
||||||
|
highlights = this._normalizeIntralineHighlights(
|
||||||
|
group[DiffGroupType.ADDED],
|
||||||
|
group[DiffHighlights.ADDED]);
|
||||||
|
}
|
||||||
|
this._appendAddedLines(group[DiffGroupType.ADDED], lines,
|
||||||
|
lineNums, highlights);
|
||||||
|
}
|
||||||
|
groups.push(new GrDiffGroup(GrDiffGroup.Type.DELTA, lines));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendFileComments: function(groups) {
|
||||||
|
var line = new GrDiffLine(GrDiffLine.Type.BOTH);
|
||||||
|
line.beforeNumber = GrDiffLine.FILE;
|
||||||
|
line.afterNumber = GrDiffLine.FILE;
|
||||||
|
groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, [line]));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In order to show comments out of the bounds of the selected context,
|
||||||
|
* treat them as separate chunks within the model so that the content (and
|
||||||
|
* context surrounding it) renders correctly.
|
||||||
|
*/
|
||||||
|
_splitCommonGroupsWithComments: function(content, lineNums) {
|
||||||
|
var result = [];
|
||||||
|
var leftLineNum = lineNums.left;
|
||||||
|
var rightLineNum = lineNums.right;
|
||||||
|
for (var i = 0; i < content.length; i++) {
|
||||||
|
if (!content[i].ab) {
|
||||||
|
result.push(content[i]);
|
||||||
|
if (content[i].a) {
|
||||||
|
leftLineNum += content[i].a.length;
|
||||||
|
}
|
||||||
|
if (content[i].b) {
|
||||||
|
rightLineNum += content[i].b.length;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var chunk = content[i].ab;
|
||||||
|
var currentChunk = {ab: []};
|
||||||
|
for (var j = 0; j < chunk.length; j++) {
|
||||||
|
leftLineNum++;
|
||||||
|
rightLineNum++;
|
||||||
|
|
||||||
|
if (this.keyLocations[DiffSide.LEFT][leftLineNum] ||
|
||||||
|
this.keyLocations[DiffSide.RIGHT][rightLineNum]) {
|
||||||
|
if (currentChunk.ab && currentChunk.ab.length > 0) {
|
||||||
|
result.push(currentChunk);
|
||||||
|
currentChunk = {ab: []};
|
||||||
|
}
|
||||||
|
result.push({ab: [chunk[j]]});
|
||||||
|
} else {
|
||||||
|
currentChunk.ab.push(chunk[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// != instead of !== because we want to cover both undefined and null.
|
||||||
|
if (currentChunk.ab != null && currentChunk.ab.length > 0) {
|
||||||
|
result.push(currentChunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendCommonLines: function(rows, lines, lineNums) {
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
var line = new GrDiffLine(GrDiffLine.Type.BOTH);
|
||||||
|
line.text = rows[i];
|
||||||
|
line.beforeNumber = ++lineNums.left;
|
||||||
|
line.afterNumber = ++lineNums.right;
|
||||||
|
lines.push(line);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_insertContextGroups: function(groups, lines, hiddenRange) {
|
||||||
|
var linesBeforeCtx = lines.slice(0, hiddenRange[0]);
|
||||||
|
var hiddenLines = lines.slice(hiddenRange[0], hiddenRange[1]);
|
||||||
|
var linesAfterCtx = lines.slice(hiddenRange[1]);
|
||||||
|
|
||||||
|
if (linesBeforeCtx.length > 0) {
|
||||||
|
groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, linesBeforeCtx));
|
||||||
|
}
|
||||||
|
|
||||||
|
var ctxLine = new GrDiffLine(GrDiffLine.Type.CONTEXT_CONTROL);
|
||||||
|
ctxLine.contextGroup =
|
||||||
|
new GrDiffGroup(GrDiffGroup.Type.BOTH, hiddenLines);
|
||||||
|
groups.push(new GrDiffGroup(GrDiffGroup.Type.CONTEXT_CONTROL,
|
||||||
|
[ctxLine]));
|
||||||
|
|
||||||
|
if (linesAfterCtx.length > 0) {
|
||||||
|
groups.push(new GrDiffGroup(GrDiffGroup.Type.BOTH, linesAfterCtx));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `highlights` array consists of a list of <skip length, mark length>
|
||||||
|
* pairs, where the skip length is the number of characters between the
|
||||||
|
* end of the previous edit and the start of this edit, and the mark
|
||||||
|
* length is the number of edited characters following the skip. The start
|
||||||
|
* of the edits is from the beginning of the related diff content lines.
|
||||||
|
*
|
||||||
|
* Note that the implied newline character at the end of each line is
|
||||||
|
* included in the length calculation, and thus it is possible for the
|
||||||
|
* edits to span newlines.
|
||||||
|
*
|
||||||
|
* A line highlight object consists of three fields:
|
||||||
|
* - contentIndex: The index of the diffChunk `content` field (the line
|
||||||
|
* being referred to).
|
||||||
|
* - startIndex: Where the highlight should begin.
|
||||||
|
* - endIndex: (optional) Where the highlight should end. If omitted, the
|
||||||
|
* highlight is meant to be a continuation onto the next line.
|
||||||
|
*/
|
||||||
|
_normalizeIntralineHighlights: function(content, highlights) {
|
||||||
|
var contentIndex = 0;
|
||||||
|
var idx = 0;
|
||||||
|
var normalized = [];
|
||||||
|
for (var i = 0; i < highlights.length; i++) {
|
||||||
|
var line = content[contentIndex] + '\n';
|
||||||
|
var hl = highlights[i];
|
||||||
|
var j = 0;
|
||||||
|
while (j < hl[0]) {
|
||||||
|
if (idx === line.length) {
|
||||||
|
idx = 0;
|
||||||
|
line = content[++contentIndex] + '\n';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
var lineHighlight = {
|
||||||
|
contentIndex: contentIndex,
|
||||||
|
startIndex: idx,
|
||||||
|
};
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
while (line && j < hl[1]) {
|
||||||
|
if (idx === line.length) {
|
||||||
|
idx = 0;
|
||||||
|
line = content[++contentIndex] + '\n';
|
||||||
|
normalized.push(lineHighlight);
|
||||||
|
lineHighlight = {
|
||||||
|
contentIndex: contentIndex,
|
||||||
|
startIndex: idx,
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
lineHighlight.endIndex = idx;
|
||||||
|
normalized.push(lineHighlight);
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendRemovedLines: function(rows, lines, lineNums, opt_highlights) {
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
var line = new GrDiffLine(GrDiffLine.Type.REMOVE);
|
||||||
|
line.text = rows[i];
|
||||||
|
line.beforeNumber = ++lineNums.left;
|
||||||
|
if (opt_highlights) {
|
||||||
|
line.highlights = opt_highlights.filter(function(hl) {
|
||||||
|
return hl.contentIndex === i;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lines.push(line);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_appendAddedLines: function(rows, lines, lineNums, opt_highlights) {
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
var line = new GrDiffLine(GrDiffLine.Type.ADD);
|
||||||
|
line.text = rows[i];
|
||||||
|
line.afterNumber = ++lineNums.right;
|
||||||
|
if (opt_highlights) {
|
||||||
|
line.highlights = opt_highlights.filter(function(hl) {
|
||||||
|
return hl.contentIndex === i;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lines.push(line);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})();
|
@@ -0,0 +1,406 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2016 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||||
|
<title>gr-diff-processor test</title>
|
||||||
|
|
||||||
|
<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
|
||||||
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||||
|
<link rel="import" href="gr-diff-processor.html">
|
||||||
|
|
||||||
|
<test-fixture id="basic">
|
||||||
|
<template>
|
||||||
|
<gr-diff-processor></gr-diff-processor>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
suite('gr-diff-processor tests', function() {
|
||||||
|
var element;
|
||||||
|
|
||||||
|
suite('not logged in', function() {
|
||||||
|
|
||||||
|
setup(function() {
|
||||||
|
element = fixture('basic');
|
||||||
|
|
||||||
|
element.context = 4;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('process loaded content', function(done) {
|
||||||
|
var content = [
|
||||||
|
{
|
||||||
|
ab: [
|
||||||
|
'<!DOCTYPE html>',
|
||||||
|
'<meta charset="utf-8">',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a: [
|
||||||
|
' Welcome ',
|
||||||
|
' to the wooorld of tomorrow!',
|
||||||
|
],
|
||||||
|
b: [
|
||||||
|
' Hello, world!',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ab: [
|
||||||
|
'Leela: This is the only place the ship can’t hear us, so ',
|
||||||
|
'everyone pretend to shower.',
|
||||||
|
'Fry: Same as every day. Got it.',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
element.process(content).then(function() {
|
||||||
|
var groups = element.groups;
|
||||||
|
|
||||||
|
assert.equal(groups.length, 4);
|
||||||
|
|
||||||
|
var group = groups[0];
|
||||||
|
assert.equal(group.type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(group.lines.length, 1);
|
||||||
|
assert.equal(group.lines[0].text, '');
|
||||||
|
assert.equal(group.lines[0].beforeNumber, GrDiffLine.FILE);
|
||||||
|
assert.equal(group.lines[0].afterNumber, GrDiffLine.FILE);
|
||||||
|
|
||||||
|
group = groups[1];
|
||||||
|
assert.equal(group.type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(group.lines.length, 2);
|
||||||
|
assert.equal(group.lines.length, 2);
|
||||||
|
|
||||||
|
function beforeNumberFn(l) { return l.beforeNumber; }
|
||||||
|
function afterNumberFn(l) { return l.afterNumber; }
|
||||||
|
function textFn(l) { return l.text; }
|
||||||
|
|
||||||
|
assert.deepEqual(group.lines.map(beforeNumberFn), [1, 2]);
|
||||||
|
assert.deepEqual(group.lines.map(afterNumberFn), [1, 2]);
|
||||||
|
assert.deepEqual(group.lines.map(textFn), [
|
||||||
|
'<!DOCTYPE html>',
|
||||||
|
'<meta charset="utf-8">',
|
||||||
|
]);
|
||||||
|
|
||||||
|
group = groups[2];
|
||||||
|
assert.equal(group.type, GrDiffGroup.Type.DELTA);
|
||||||
|
assert.equal(group.lines.length, 3);
|
||||||
|
assert.equal(group.adds.length, 1);
|
||||||
|
assert.equal(group.removes.length, 2);
|
||||||
|
assert.deepEqual(group.removes.map(beforeNumberFn), [3, 4]);
|
||||||
|
assert.deepEqual(group.adds.map(afterNumberFn), [3]);
|
||||||
|
assert.deepEqual(group.removes.map(textFn), [
|
||||||
|
' Welcome ',
|
||||||
|
' to the wooorld of tomorrow!',
|
||||||
|
]);
|
||||||
|
assert.deepEqual(group.adds.map(textFn), [
|
||||||
|
' Hello, world!',
|
||||||
|
]);
|
||||||
|
|
||||||
|
group = groups[3];
|
||||||
|
assert.equal(group.type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(group.lines.length, 3);
|
||||||
|
assert.deepEqual(group.lines.map(beforeNumberFn), [5, 6, 7]);
|
||||||
|
assert.deepEqual(group.lines.map(afterNumberFn), [4, 5, 6]);
|
||||||
|
assert.deepEqual(group.lines.map(textFn), [
|
||||||
|
'Leela: This is the only place the ship can’t hear us, so ',
|
||||||
|
'everyone pretend to shower.',
|
||||||
|
'Fry: Same as every day. Got it.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('insert context groups', function(done) {
|
||||||
|
var content = [
|
||||||
|
{ab: []},
|
||||||
|
{a: ['all work and no play make andybons a dull boy']},
|
||||||
|
{ab: []},
|
||||||
|
{b: ['elgoog elgoog elgoog']},
|
||||||
|
{ab: []},
|
||||||
|
];
|
||||||
|
for (var i = 0; i < 100; i++) {
|
||||||
|
content[0].ab.push('all work and no play make jack a dull boy');
|
||||||
|
content[4].ab.push('all work and no play make jill a dull girl');
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 5; i++) {
|
||||||
|
content[2].ab.push('no tv and no beer make homer go crazy');
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = 10;
|
||||||
|
element.context = context;
|
||||||
|
|
||||||
|
element.process(content).then(function() {
|
||||||
|
var groups = element.groups;
|
||||||
|
|
||||||
|
assert.equal(groups[0].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[0].lines.length, 1);
|
||||||
|
assert.equal(groups[0].lines[0].text, '');
|
||||||
|
assert.equal(groups[0].lines[0].beforeNumber, GrDiffLine.FILE);
|
||||||
|
assert.equal(groups[0].lines[0].afterNumber, GrDiffLine.FILE);
|
||||||
|
|
||||||
|
assert.equal(groups[1].type, GrDiffGroup.Type.CONTEXT_CONTROL);
|
||||||
|
assert.instanceOf(groups[1].lines[0].contextGroup, GrDiffGroup);
|
||||||
|
assert.equal(groups[1].lines[0].contextGroup.lines.length, 90);
|
||||||
|
groups[1].lines[0].contextGroup.lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[0].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[2].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[2].lines.length, context);
|
||||||
|
groups[2].lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[0].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[3].type, GrDiffGroup.Type.DELTA);
|
||||||
|
assert.equal(groups[3].lines.length, 1);
|
||||||
|
assert.equal(groups[3].removes.length, 1);
|
||||||
|
assert.equal(groups[3].removes[0].text,
|
||||||
|
'all work and no play make andybons a dull boy');
|
||||||
|
|
||||||
|
assert.equal(groups[4].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[4].lines.length, 5);
|
||||||
|
groups[4].lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[2].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[5].type, GrDiffGroup.Type.DELTA);
|
||||||
|
assert.equal(groups[5].lines.length, 1);
|
||||||
|
assert.equal(groups[5].adds.length, 1);
|
||||||
|
assert.equal(groups[5].adds[0].text, 'elgoog elgoog elgoog');
|
||||||
|
|
||||||
|
assert.equal(groups[6].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[6].lines.length, context);
|
||||||
|
groups[6].lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[4].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[7].type, GrDiffGroup.Type.CONTEXT_CONTROL);
|
||||||
|
assert.instanceOf(groups[7].lines[0].contextGroup, GrDiffGroup);
|
||||||
|
assert.equal(groups[7].lines[0].contextGroup.lines.length, 90);
|
||||||
|
groups[7].lines[0].contextGroup.lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[4].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('insert context groups', function(done) {
|
||||||
|
content = [
|
||||||
|
{a: ['all work and no play make andybons a dull boy']},
|
||||||
|
{ab: []},
|
||||||
|
{b: ['elgoog elgoog elgoog']},
|
||||||
|
];
|
||||||
|
for (var i = 0; i < 50; i++) {
|
||||||
|
content[1].ab.push('no tv and no beer make homer go crazy');
|
||||||
|
}
|
||||||
|
|
||||||
|
var context = 10;
|
||||||
|
element.context = context;
|
||||||
|
|
||||||
|
element.process(content).then(function() {
|
||||||
|
var groups = element.groups;
|
||||||
|
|
||||||
|
assert.equal(groups[0].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[0].lines.length, 1);
|
||||||
|
assert.equal(groups[0].lines[0].text, '');
|
||||||
|
assert.equal(groups[0].lines[0].beforeNumber, GrDiffLine.FILE);
|
||||||
|
assert.equal(groups[0].lines[0].afterNumber, GrDiffLine.FILE);
|
||||||
|
|
||||||
|
assert.equal(groups[1].type, GrDiffGroup.Type.DELTA);
|
||||||
|
assert.equal(groups[1].lines.length, 1);
|
||||||
|
assert.equal(groups[1].removes.length, 1);
|
||||||
|
assert.equal(groups[1].removes[0].text,
|
||||||
|
'all work and no play make andybons a dull boy');
|
||||||
|
|
||||||
|
assert.equal(groups[2].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[2].lines.length, context);
|
||||||
|
groups[2].lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[1].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[3].type, GrDiffGroup.Type.CONTEXT_CONTROL);
|
||||||
|
assert.instanceOf(groups[3].lines[0].contextGroup, GrDiffGroup);
|
||||||
|
assert.equal(groups[3].lines[0].contextGroup.lines.length, 30);
|
||||||
|
groups[3].lines[0].contextGroup.lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[1].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[4].type, GrDiffGroup.Type.BOTH);
|
||||||
|
assert.equal(groups[4].lines.length, context);
|
||||||
|
groups[4].lines.forEach(function(l) {
|
||||||
|
assert.equal(l.text, content[1].ab[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(groups[5].type, GrDiffGroup.Type.DELTA);
|
||||||
|
assert.equal(groups[5].lines.length, 1);
|
||||||
|
assert.equal(groups[5].adds.length, 1);
|
||||||
|
assert.equal(groups[5].adds[0].text, 'elgoog elgoog elgoog');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('break up common diff chunks', function() {
|
||||||
|
element.keyLocations = {
|
||||||
|
left: {1: true},
|
||||||
|
right: {10: true},
|
||||||
|
};
|
||||||
|
var lineNums = {left: 0, right: 0};
|
||||||
|
|
||||||
|
var content = [
|
||||||
|
{
|
||||||
|
ab: [
|
||||||
|
'Copyright (C) 2015 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.',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var result = element._splitCommonGroupsWithComments(content, lineNums);
|
||||||
|
assert.deepEqual(result, [
|
||||||
|
{
|
||||||
|
ab: ['Copyright (C) 2015 The Android Open Source Project'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ab: [
|
||||||
|
'',
|
||||||
|
'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, ',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ab: [
|
||||||
|
'software distributed under the License is distributed on an '],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ab: [
|
||||||
|
'"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.',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('intraline normalization', function() {
|
||||||
|
// The content and highlights are in the format returned by the Gerrit
|
||||||
|
// REST API.
|
||||||
|
var content = [
|
||||||
|
' <section class="summary">',
|
||||||
|
' <gr-linked-text content="' +
|
||||||
|
'[[_computeCurrentRevisionMessage(change)]]"></gr-linked-text>',
|
||||||
|
' </section>',
|
||||||
|
];
|
||||||
|
var highlights = [
|
||||||
|
[31, 34], [42, 26]
|
||||||
|
];
|
||||||
|
|
||||||
|
var results = element._normalizeIntralineHighlights(content,
|
||||||
|
highlights);
|
||||||
|
assert.deepEqual(results, [
|
||||||
|
{
|
||||||
|
contentIndex: 0,
|
||||||
|
startIndex: 31,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 1,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: 33,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 1,
|
||||||
|
startIndex: 75,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 2,
|
||||||
|
startIndex: 0,
|
||||||
|
endIndex: 6,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
content = [
|
||||||
|
' this._path = value.path;',
|
||||||
|
'',
|
||||||
|
' // When navigating away from the page, there is a ' +
|
||||||
|
'possibility that the',
|
||||||
|
' // patch number is no longer a part of the URL ' +
|
||||||
|
'(say when navigating to',
|
||||||
|
' // the top-level change info view) and therefore ' +
|
||||||
|
'undefined in `params`.',
|
||||||
|
' if (!this._patchRange.patchNum) {',
|
||||||
|
];
|
||||||
|
highlights = [
|
||||||
|
[14, 17],
|
||||||
|
[11, 70],
|
||||||
|
[12, 67],
|
||||||
|
[12, 67],
|
||||||
|
[14, 29],
|
||||||
|
];
|
||||||
|
results = element._normalizeIntralineHighlights(content, highlights);
|
||||||
|
assert.deepEqual(results, [
|
||||||
|
{
|
||||||
|
contentIndex: 0,
|
||||||
|
startIndex: 14,
|
||||||
|
endIndex: 31,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 2,
|
||||||
|
startIndex: 8,
|
||||||
|
endIndex: 78,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 3,
|
||||||
|
startIndex: 11,
|
||||||
|
endIndex: 78,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 4,
|
||||||
|
startIndex: 11,
|
||||||
|
endIndex: 78,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contentIndex: 5,
|
||||||
|
startIndex: 12,
|
||||||
|
endIndex: 41,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@@ -49,6 +49,7 @@ limitations under the License.
|
|||||||
'diff/gr-diff-cursor/gr-diff-cursor_test.html',
|
'diff/gr-diff-cursor/gr-diff-cursor_test.html',
|
||||||
'diff/gr-diff-highlight/gr-diff-highlight_test.html',
|
'diff/gr-diff-highlight/gr-diff-highlight_test.html',
|
||||||
'diff/gr-diff-preferences/gr-diff-preferences_test.html',
|
'diff/gr-diff-preferences/gr-diff-preferences_test.html',
|
||||||
|
'diff/gr-diff-processor/gr-diff-processor_test.html',
|
||||||
'diff/gr-diff-selection/gr-diff-selection_test.html',
|
'diff/gr-diff-selection/gr-diff-selection_test.html',
|
||||||
'diff/gr-diff-view/gr-diff-view_test.html',
|
'diff/gr-diff-view/gr-diff-view_test.html',
|
||||||
'diff/gr-diff/gr-diff-group_test.html',
|
'diff/gr-diff/gr-diff-group_test.html',
|
||||||
|
Reference in New Issue
Block a user