Merge "Fix missing comments for renamed files"

This commit is contained in:
Tao Zhou
2020-04-01 15:23:23 +00:00
committed by Gerrit Code Review
5 changed files with 160 additions and 74 deletions

View File

@@ -69,6 +69,31 @@ const FileStatus = {
U: 'Unchanged',
};
/**
* Type for FileInfo
*
* This should match with the type returned from `files` API plus
* additional info like `__path`.
*
* @typedef {Object} FileInfo
* @property {string} __path
* @property {?string} old_path
* @property {number} size
* @property {number} size_delta - fallback to 0 if not present in api
* @property {number} lines_deleted - fallback to 0 if not present in api
* @property {number} lines_inserted - fallback to 0 if not present in api
*/
/**
* Type for FileData
*
* This contains minimal info required about the file to get comments for
*
* @typedef {Object} FileData
* @property {string} path
* @property {?string} oldPath
*/
/**
* @appliesMixin Gerrit.AsyncForeachMixin
* @appliesMixin Gerrit.DomUtilMixin
@@ -133,6 +158,8 @@ class GrFileList extends mixinBehaviors( [
notify: true,
},
_filesByPath: Object,
/** @type {!Array<FileInfo>} */
_files: {
type: Array,
observer: '_filesChanged',
@@ -184,7 +211,8 @@ class GrFileList extends mixinBehaviors( [
*/
_reportinShownFilesIncrement: Number,
_expandedFilePaths: {
/** @type {!Array<FileData>} */
_expandedFiles: {
type: Array,
value() { return []; },
},
@@ -230,7 +258,7 @@ class GrFileList extends mixinBehaviors( [
static get observers() {
return [
'_expandedPathsChanged(_expandedFilePaths.splices)',
'_expandedFilesChanged(_expandedFiles.splices)',
'_computeFiles(_filesByPath, changeComments, patchRange, _reviewed, ' +
'_loading)',
];
@@ -409,27 +437,27 @@ class GrFileList extends mixinBehaviors( [
return this.$.restAPI.getPreferences();
}
_togglePathExpanded(path) {
_toggleFileExpanded(file) {
// Is the path in the list of expanded diffs? IF so remove it, otherwise
// add it to the list.
const pathIndex = this._expandedFilePaths.indexOf(path);
const pathIndex = this._expandedFiles.findIndex(f => f.path === file.path);
if (pathIndex === -1) {
this.push('_expandedFilePaths', path);
this.push('_expandedFiles', file);
} else {
this.splice('_expandedFilePaths', pathIndex, 1);
this.splice('_expandedFiles', pathIndex, 1);
}
}
_togglePathExpandedByIndex(index) {
this._togglePathExpanded(this._files[index].__path);
_toggleFileExpandedByIndex(index) {
this._toggleFileExpanded(this._computeFileData(this._files[index]));
}
_updateDiffPreferences() {
if (!this.diffs.length) { return; }
// Re-render all expanded diffs sequentially.
this.$.reporting.time(EXPAND_ALL_TIMING_LABEL);
this._renderInOrder(this._expandedFilePaths, this.diffs,
this._expandedFilePaths.length);
this._renderInOrder(this._expandedFiles, this.diffs,
this._expandedFiles.length);
}
_forEachDiff(fn) {
@@ -444,23 +472,23 @@ class GrFileList extends mixinBehaviors( [
// Find the list of paths that are in the file list, but not in the
// expanded list.
const newPaths = [];
const newFiles = [];
let path;
for (let i = 0; i < this._shownFiles.length; i++) {
path = this._shownFiles[i].__path;
if (!this._expandedFilePaths.includes(path)) {
newPaths.push(path);
if (!this._expandedFiles.some(f => f.path === path)) {
newFiles.push(this._computeFileData(this._shownFiles[i]));
}
}
this.splice(...['_expandedFilePaths', 0, 0].concat(newPaths));
this.splice(...['_expandedFiles', 0, 0].concat(newFiles));
}
collapseAllDiffs() {
this._showInlineDiffs = false;
this._expandedFilePaths = [];
this._expandedFiles = [];
this.filesExpanded = this._computeExpandedFiles(
this._expandedFilePaths.length, this._files.length);
this._expandedFiles.length, this._files.length);
this.$.diffCursor.handleDiffUpdate();
}
@@ -607,7 +635,7 @@ class GrFileList extends mixinBehaviors( [
* The closure compiler doesn't realize this.specialFilePathCompare is
* valid.
*
* @suppress {checkTypes}
* @returns {!Array<FileInfo>}
*/
_normalizeChangeFilesResponse(response) {
if (!response) { return []; }
@@ -618,6 +646,7 @@ class GrFileList extends mixinBehaviors( [
info.__path = paths[i];
info.lines_inserted = info.lines_inserted || 0;
info.lines_deleted = info.lines_deleted || 0;
info.size_delta = info.size_delta || 0;
files.push(info);
}
return files;
@@ -634,7 +663,13 @@ class GrFileList extends mixinBehaviors( [
row = row.parentElement;
}
const path = row.dataset.path;
// No action needed for item without a valid file
if (!row.dataset.file) {
return;
}
const file = JSON.parse(row.dataset.file);
const path = file.path;
// Handle checkbox mark as reviewed.
if (e.target.classList.contains('markReviewed')) {
e.preventDefault();
@@ -650,7 +685,23 @@ class GrFileList extends mixinBehaviors( [
if (this.descendedFromClass(e.target, 'editFileControls')) { return; }
e.preventDefault();
this._togglePathExpanded(path);
this._toggleFileExpanded(file);
}
/**
* Generates file data from file info object.
*
* @param {FileInfo} file
* @returns {FileData}
*/
_computeFileData(file) {
const fileData = {
path: file.__path,
};
if (file.old_path) {
fileData.oldPath = file.old_path;
}
return fileData;
}
_handleLeftPane(e) {
@@ -677,7 +728,7 @@ class GrFileList extends mixinBehaviors( [
this.$.fileCursor.index === -1) { return; }
e.preventDefault();
this._togglePathExpandedByIndex(this.$.fileCursor.index);
this._toggleFileExpandedByIndex(this.$.fileCursor.index);
}
_handleToggleAllInlineDiffs(e) {
@@ -1051,7 +1102,7 @@ class GrFileList extends mixinBehaviors( [
}
_isFileExpanded(path, expandedFilesRecord) {
return expandedFilesRecord.base.includes(path);
return expandedFilesRecord.base.some(f => f.path === path);
}
_onLineSelected(e, detail) {
@@ -1076,20 +1127,20 @@ class GrFileList extends mixinBehaviors( [
*
* @param {!Array} record The splice record in the expanded paths list.
*/
_expandedPathsChanged(record) {
_expandedFilesChanged(record) {
// Clear content for any diffs that are not open so if they get re-opened
// the stale content does not flash before it is cleared and reloaded.
const collapsedDiffs = this.diffs.filter(diff =>
this._expandedFilePaths.indexOf(diff.path) === -1);
this._expandedFiles.findIndex(f => f.path === diff.path) === -1);
this._clearCollapsedDiffs(collapsedDiffs);
if (!record) { return; } // Happens after "Collapse all" clicked.
this.filesExpanded = this._computeExpandedFiles(
this._expandedFilePaths.length, this._files.length);
this._expandedFiles.length, this._files.length);
// Find the paths introduced by the new index splices:
const newPaths = record.indexSplices
const newFiles = record.indexSplices
.map(splice => splice.object.slice(
splice.index, splice.index + splice.addedCount))
.reduce((acc, paths) => acc.concat(paths), []);
@@ -1099,8 +1150,8 @@ class GrFileList extends mixinBehaviors( [
this.$.reporting.time(EXPAND_ALL_TIMING_LABEL);
if (newPaths.length) {
this._renderInOrder(newPaths, this.diffs, newPaths.length);
if (newFiles.length) {
this._renderInOrder(newFiles, this.diffs, newFiles.length);
}
this._updateDiffCursor();
@@ -1119,18 +1170,19 @@ class GrFileList extends mixinBehaviors( [
* for each path in order, awaiting the previous render to complete before
* continung.
*
* @param {!Array<string>} paths
* @param {!Array<FileData>} files
* @param {!NodeList<!Object>} diffElements (GrDiffHostElement)
* @param {number} initialCount The total number of paths in the pass. This
* is used to generate log messages.
* @return {!Promise}
*/
_renderInOrder(paths, diffElements, initialCount) {
_renderInOrder(files, diffElements, initialCount) {
let iter = 0;
return (new Promise(resolve => {
this.fire('reload-drafts', {resolve});
})).then(() => this.asyncForeach(paths, (path, cancel) => {
})).then(() => this.asyncForeach(files, (file, cancel) => {
const path = file.path;
this._cancelForEachDiff = cancel;
iter++;
@@ -1141,8 +1193,8 @@ class GrFileList extends mixinBehaviors( [
console.warn(`Did not find <gr-diff-host> element for ${path}`);
return Promise.resolve();
}
diffElem.comments = this.changeComments.getCommentsBySideForPath(
path, this.patchRange, this.projectConfig);
diffElem.comments = this.changeComments.getCommentsBySideForFile(
file, this.patchRange, this.projectConfig);
const promises = [diffElem.reload()];
if (this._loggedIn && !this.diffPrefs.manual_review) {
promises.push(this._reviewFile(path, true));
@@ -1188,7 +1240,7 @@ class GrFileList extends mixinBehaviors( [
reloadCommentsForThreadWithRootId(rootId, path) {
// Don't bother continuing if we already know that the path that contains
// the updated comment thread is not expanded.
if (!this._expandedFilePaths.includes(path)) { return; }
if (!this._expandedFiles.some(f => f.path === path)) { return; }
const diff = this.diffs.find(d => d.path === path);
const threadEl = diff.getThreadEls().find(t => t.rootId === rootId);

View File

@@ -296,7 +296,7 @@ export const htmlTemplate = html`
<template is="dom-repeat" items="[[_shownFiles]]" id="files" as="file" initial-count="[[fileListIncrement]]" target-framerate="1">
[[_reportRenderedRow(index)]]
<div class="stickyArea">
<div class\$="file-row row [[_computePathClass(file.__path, _expandedFilePaths.*)]]" data-path\$="[[file.__path]]" tabindex="-1">
<div class\$="file-row row [[_computePathClass(file.__path, _expandedFiles.*)]]" data-file\$="[[_computeFileData(file)]]" tabindex="-1">
<div class\$="[[_computeClass('status', file.__path)]]" tabindex="0" title\$="[[_computeFileStatusLabel(file.status)]]" aria-label\$="[[_computeFileStatusLabel(file.status)]]">
[[_computeFileStatus(file.status)]]
</div>
@@ -378,14 +378,14 @@ export const htmlTemplate = html`
</div>
<div class="show-hide">
<label class="show-hide" data-path\$="[[file.__path]]" data-expand="true">
<input type="checkbox" class="show-hide" checked\$="[[_isFileExpanded(file.__path, _expandedFilePaths.*)]]" data-path\$="[[file.__path]]" data-expand="true">
<iron-icon id="icon" icon="[[_computeShowHideIcon(file.__path, _expandedFilePaths.*)]]">
<input type="checkbox" class="show-hide" checked\$="[[_isFileExpanded(file.__path, _expandedFiles.*)]]" data-path\$="[[file.__path]]" data-expand="true">
<iron-icon id="icon" icon="[[_computeShowHideIcon(file.__path, _expandedFiles.*)]]">
</iron-icon>
</label>
</div>
</div>
<template is="dom-if" if="[[_isFileExpanded(file.__path, _expandedFilePaths.*)]]">
<gr-diff-host no-auto-render="" show-load-failure="" display-line="[[_displayLine]]" hidden="[[!_isFileExpanded(file.__path, _expandedFilePaths.*)]]" change-num="[[changeNum]]" patch-range="[[patchRange]]" path="[[file.__path]]" prefs="[[diffPrefs]]" project-name="[[change.project]]" on-line-selected="_onLineSelected" no-render-on-prefs-change="" view-mode="[[diffViewMode]]"></gr-diff-host>
<template is="dom-if" if="[[_isFileExpanded(file.__path, _expandedFiles.*)]]">
<gr-diff-host no-auto-render="" show-load-failure="" display-line="[[_displayLine]]" hidden="[[!_isFileExpanded(file.__path, _expandedFiles.*)]]" change-num="[[changeNum]]" patch-range="[[patchRange]]" path="[[file.__path]]" prefs="[[diffPrefs]]" project-name="[[change.project]]" on-line-selected="_onLineSelected" no-render-on-prefs-change="" view-mode="[[diffViewMode]]"></gr-diff-host>
</template>
</div>
</template>

View File

@@ -671,47 +671,50 @@ suite('gr-file-list tests', () => {
test('i key shows/hides selected inline diff', () => {
const paths = Object.keys(element._filesByPath);
sandbox.stub(element, '_expandedPathsChanged');
sandbox.stub(element, '_expandedFilesChanged');
flushAsynchronousOperations();
const files = dom(element.root).querySelectorAll('.file-row');
element.$.fileCursor.stops = files;
element.$.fileCursor.setCursorAtIndex(0);
assert.equal(element.diffs.length, 0);
assert.equal(element._expandedFilePaths.length, 0);
assert.equal(element._expandedFiles.length, 0);
MockInteractions.keyUpOn(element, 73, null, 'i');
flushAsynchronousOperations();
assert.equal(element.diffs.length, 1);
assert.equal(element.diffs[0].path, paths[0]);
assert.equal(element._expandedFilePaths.length, 1);
assert.equal(element._expandedFilePaths[0], paths[0]);
assert.equal(element._expandedFiles.length, 1);
assert.equal(element._expandedFiles[0].path, paths[0]);
MockInteractions.keyUpOn(element, 73, null, 'i');
flushAsynchronousOperations();
assert.equal(element.diffs.length, 0);
assert.equal(element._expandedFilePaths.length, 0);
assert.equal(element._expandedFiles.length, 0);
element.$.fileCursor.setCursorAtIndex(1);
MockInteractions.keyUpOn(element, 73, null, 'i');
flushAsynchronousOperations();
assert.equal(element.diffs.length, 1);
assert.equal(element.diffs[0].path, paths[1]);
assert.equal(element._expandedFilePaths.length, 1);
assert.equal(element._expandedFilePaths[0], paths[1]);
assert.equal(element._expandedFiles.length, 1);
assert.equal(element._expandedFiles[0].path, paths[1]);
MockInteractions.keyUpOn(element, 73, 'shift', 'i');
flushAsynchronousOperations();
assert.equal(element.diffs.length, paths.length);
assert.equal(element._expandedFilePaths.length, paths.length);
assert.equal(element._expandedFiles.length, paths.length);
for (const index in element.diffs) {
if (!element.diffs.hasOwnProperty(index)) { continue; }
assert.include(element._expandedFilePaths, element.diffs[index].path);
assert.isTrue(
element._expandedFiles
.some(f => f.path === element.diffs[index].path)
);
}
MockInteractions.keyUpOn(element, 73, 'shift', 'i');
flushAsynchronousOperations();
assert.equal(element.diffs.length, 0);
assert.equal(element._expandedFilePaths.length, 0);
assert.equal(element._expandedFiles.length, 0);
});
test('r key toggles reviewed flag', () => {
@@ -741,7 +744,7 @@ suite('gr-file-list tests', () => {
sandbox.stub(element, 'modifierPressed').returns(false);
const openCursorStub = sandbox.stub(element, '_openCursorFile');
const openSelectedStub = sandbox.stub(element, '_openSelectedFile');
const expandStub = sandbox.stub(element, '_togglePathExpanded');
const expandStub = sandbox.stub(element, '_toggleFileExpanded');
interact = function(opt_payload) {
openCursorStub.reset();
@@ -880,12 +883,12 @@ suite('gr-file-list tests', () => {
const clickSpy = sandbox.spy(element, '_handleFileListClick');
const reviewStub = sandbox.stub(element, '_reviewFile');
const toggleExpandSpy = sandbox.spy(element, '_togglePathExpanded');
const toggleExpandSpy = sandbox.spy(element, '_toggleFileExpanded');
const row = dom(element.root)
.querySelector('.row[data-path="f1.txt"]');
.querySelector(`.row[data-file='{"path":"f1.txt"}']`);
// Click on the expand button, resulting in _togglePathExpanded being
// Click on the expand button, resulting in _toggleFileExpanded being
// called and not resulting in a call to _reviewFile.
row.querySelector('div.show-hide').click();
assert.isTrue(clickSpy.calledOnce);
@@ -893,7 +896,7 @@ suite('gr-file-list tests', () => {
assert.isFalse(reviewStub.called);
// Click inside the diff. This should result in no additional calls to
// _togglePathExpanded or _reviewFile.
// _toggleFileExpanded or _reviewFile.
dom(element.root).querySelector('gr-diff-host')
.click();
assert.isTrue(clickSpy.calledTwice);
@@ -901,7 +904,7 @@ suite('gr-file-list tests', () => {
assert.isFalse(reviewStub.called);
// Click the reviewed checkbox, resulting in a call to _reviewFile, but
// no additional call to _togglePathExpanded.
// no additional call to _toggleFileExpanded.
row.querySelector('.markReviewed').click();
assert.isTrue(clickSpy.calledThrice);
assert.isTrue(toggleExpandSpy.calledOnce);
@@ -922,7 +925,7 @@ suite('gr-file-list tests', () => {
element.editMode = true;
flushAsynchronousOperations();
const clickSpy = sandbox.spy(element, '_handleFileListClick');
const toggleExpandSpy = sandbox.spy(element, '_togglePathExpanded');
const toggleExpandSpy = sandbox.spy(element, '_toggleFileExpanded');
// Tap the edit controls. Should be ignored by _handleFileListClick.
MockInteractions.tap(element.shadowRoot
@@ -962,7 +965,7 @@ suite('gr-file-list tests', () => {
patchNum: '2',
};
element.$.fileCursor.setCursorAtIndex(0);
sandbox.stub(element, '_expandedPathsChanged');
sandbox.stub(element, '_expandedFilesChanged');
flushAsynchronousOperations();
const fileRows =
dom(element.root).querySelectorAll('.row:not(.header-row)');
@@ -974,7 +977,9 @@ suite('gr-file-list tests', () => {
assert.isNotOk(showHideCheck.checked);
MockInteractions.tap(showHideLabel);
assert.isOk(showHideCheck.checked);
assert.notEqual(element._expandedFilePaths.indexOf('myfile.txt'), -1);
assert.notEqual(
element._expandedFiles.findIndex(f => f.path === 'myfile.txt'),
-1);
});
test('diff mode correctly toggles the diffs', () => {
@@ -1020,14 +1025,14 @@ suite('gr-file-list tests', () => {
basePatchNum: 'PARENT',
patchNum: '2',
};
sandbox.stub(element, '_expandedPathsChanged');
sandbox.stub(element, '_expandedFilesChanged');
flushAsynchronousOperations();
const commitMsgFile = dom(element.root)
.querySelectorAll('.row:not(.header-row) a.pathLink')[0];
// Remove href attribute so the app doesn't route to a diff view
commitMsgFile.removeAttribute('href');
const togglePathSpy = sandbox.spy(element, '_togglePathExpanded');
const togglePathSpy = sandbox.spy(element, '_toggleFileExpanded');
MockInteractions.tap(commitMsgFile);
flushAsynchronousOperations();
@@ -1039,7 +1044,7 @@ suite('gr-file-list tests', () => {
'none');
});
test('_togglePathExpanded', () => {
test('_toggleFileExpanded', () => {
const path = 'path/to/my/file.txt';
element._filesByPath = {[path]: {}};
const renderSpy = sandbox.spy(element, '_renderInOrder');
@@ -1047,22 +1052,22 @@ suite('gr-file-list tests', () => {
assert.equal(element.shadowRoot
.querySelector('iron-icon').icon, 'gr-icons:expand-more');
assert.equal(element._expandedFilePaths.length, 0);
element._togglePathExpanded(path);
assert.equal(element._expandedFiles.length, 0);
element._toggleFileExpanded({path});
flushAsynchronousOperations();
assert.equal(collapseStub.lastCall.args[0].length, 0);
assert.equal(element.shadowRoot
.querySelector('iron-icon').icon, 'gr-icons:expand-less');
assert.equal(renderSpy.callCount, 1);
assert.include(element._expandedFilePaths, path);
element._togglePathExpanded(path);
assert.isTrue(element._expandedFiles.some(f => f.path === path));
element._toggleFileExpanded({path});
flushAsynchronousOperations();
assert.equal(element.shadowRoot
.querySelector('iron-icon').icon, 'gr-icons:expand-more');
assert.equal(renderSpy.callCount, 1);
assert.notInclude(element._expandedFilePaths, path);
assert.isFalse(element._expandedFiles.some(f => f.path === path));
assert.equal(collapseStub.lastCall.args[0].length, 1);
});
@@ -1081,13 +1086,13 @@ suite('gr-file-list tests', () => {
element.collapseAllDiffs();
flushAsynchronousOperations();
assert.equal(element._expandedFilePaths.length, 0);
assert.equal(element._expandedFiles.length, 0);
assert.isFalse(element._showInlineDiffs);
assert.isTrue(cursorUpdateStub.calledTwice);
assert.equal(collapseStub.lastCall.args[0].length, 1);
});
test('_expandedPathsChanged', done => {
test('_expandedFilesChanged', done => {
sandbox.stub(element, '_reviewFile');
const path = 'path/to/my/file.txt';
const diffs = [{
@@ -1105,7 +1110,7 @@ suite('gr-file-list tests', () => {
sinon.stub(element, 'diffs', {
get() { return diffs; },
});
element.push('_expandedFilePaths', path);
element.push('_expandedFiles', {path});
});
test('_clearCollapsedDiffs', () => {
@@ -1126,11 +1131,11 @@ suite('gr-file-list tests', () => {
flushAsynchronousOperations();
assert.equal(element.filesExpanded,
GrFileListConstants.FilesExpandedState.NONE);
element.push('_expandedFilePaths', 'baz.bar');
element.push('_expandedFiles', {path: 'baz.bar'});
flushAsynchronousOperations();
assert.equal(element.filesExpanded,
GrFileListConstants.FilesExpandedState.SOME);
element.push('_expandedFilePaths', 'foo.bar');
element.push('_expandedFiles', {path: 'foo.bar'});
flushAsynchronousOperations();
assert.equal(element.filesExpanded,
GrFileListConstants.FilesExpandedState.ALL);
@@ -1169,7 +1174,9 @@ suite('gr-file-list tests', () => {
return Promise.resolve();
},
}];
element._renderInOrder(['p2', 'p1', 'p0'], diffs, 3)
element._renderInOrder([
{path: 'p2'}, {path: 'p1'}, {path: 'p0'},
], diffs, 3)
.then(() => {
assert.isFalse(reviewStub.called);
assert.isTrue(loadCommentSpy.called);
@@ -1206,7 +1213,9 @@ suite('gr-file-list tests', () => {
return Promise.resolve();
},
}];
element._renderInOrder(['p2', 'p1', 'p0'], diffs, 3)
element._renderInOrder([
{path: 'p2'}, {path: 'p1'}, {path: 'p0'},
], diffs, 3)
.then(() => {
assert.equal(reviewStub.callCount, 3);
done();
@@ -1223,10 +1232,10 @@ suite('gr-file-list tests', () => {
reload() { return Promise.resolve(); },
}];
return element._renderInOrder(['p'], diffs, 1).then(() => {
return element._renderInOrder([{path: 'p'}], diffs, 1).then(() => {
assert.isFalse(reviewStub.called);
delete element.diffPrefs.manual_review;
return element._renderInOrder(['p'], diffs, 1).then(() => {
return element._renderInOrder([{path: 'p'}], diffs, 1).then(() => {
assert.isTrue(reviewStub.called);
assert.isTrue(reviewStub.calledWithExactly('p', true));
});

View File

@@ -342,6 +342,7 @@ class ChangeComments {
comments.left = comments.left.concat(commentsForOldPath.left);
comments.right = comments.right.concat(commentsForOldPath.right);
}
return comments;
}
/**

View File

@@ -258,6 +258,8 @@ class GrDiffView extends mixinBehaviors( [
'_getProjectConfig(_change.project)',
'_getFiles(_changeNum, _patchRange.*, _changeComments)',
'_setReviewedObserver(_loggedIn, params.*, _prefs)',
'_recomputeComments(_files.changeFilesByPath,' +
'_path, _patchRange, _projectConfig)',
];
}
@@ -1112,6 +1114,28 @@ class GrDiffView extends mixinBehaviors( [
});
}
_recomputeComments(files, path, patchRange, projectConfig) {
// Polymer 2: check for undefined
if ([
files,
path,
patchRange,
projectConfig,
].some(arg => arg === undefined)) {
return undefined;
}
const file = files[path];
if (file && file.old_path) {
this._commentsForDiff = this._changeComments.getCommentsBySideForFile(
{path, oldPath: file.old_path},
patchRange,
projectConfig);
this.$.diffHost.comments = this._commentsForDiff;
}
}
_getPaths(patchRange) {
return this._changeComments.getPaths(patchRange);
}