diff options
Diffstat (limited to 'polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html')
-rw-r--r-- | polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html | 136 |
1 files changed, 115 insertions, 21 deletions
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html index dd18b65cbd..cc66e3bdff 100644 --- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html +++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder.html @@ -1,4 +1,5 @@ <!-- +@license Copyright (C) 2016 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,7 +25,7 @@ limitations under the License. <dom-module id="gr-diff-builder"> <template> <div class="contentWrapper"> - <content></content> + <slot></slot> </div> <gr-ranged-comment-layer id="rangeLayer" @@ -36,6 +37,7 @@ limitations under the License. id="processor" groups="{{_groups}}"></gr-diff-processor> <gr-reporting id="reporting"></gr-reporting> + <gr-js-api-interface id="jsAPI"></gr-js-api-interface> </template> <script src="../gr-diff/gr-diff-line.js"></script> <script src="../gr-diff/gr-diff-group.js"></script> @@ -44,10 +46,21 @@ limitations under the License. <script src="gr-diff-builder-side-by-side.js"></script> <script src="gr-diff-builder-unified.js"></script> <script src="gr-diff-builder-image.js"></script> + <script src="gr-diff-builder-binary.js"></script> <script> (function() { 'use strict'; + const Defs = {}; + + /** + * @typedef {{ + * number: number, + * leftSide: {boolean} + * }} + */ + Defs.LineOfInterest; + const DiffViewMode = { SIDE_BY_SIDE: 'SIDE_BY_SIDE', UNIFIED: 'UNIFIED_DIFF', @@ -63,6 +76,9 @@ limitations under the License. // syntax highlighting for the entire file. const SYNTAX_MAX_LINE_LENGTH = 500; + // Disable syntax highlighting if the overall diff is too large. + const SYNTAX_MAX_DIFF_LENGTH = 20000; + const TRAILING_WHITESPACE_PATTERN = /\s+$/; Polymer({ @@ -89,12 +105,26 @@ limitations under the License. properties: { diff: Object, + diffPath: String, + changeNum: String, + patchNum: String, viewMode: String, comments: Object, isImageDiff: Boolean, baseImage: Object, revisionImage: Object, projectName: String, + parentIndex: Number, + /** + * @type {Defs.LineOfInterest|null} + */ + lineOfInterest: Object, + + /** + * @type {function(number, booleam, !string)} + */ + createCommentFn: Function, + _builder: Object, _groups: Array, _layers: Array, @@ -111,7 +141,7 @@ limitations under the License. attached() { // Setup annotation layers. - this._layers = [ + const layers = [ this._createTrailingWhitespaceLayer(), this.$.syntaxLayer, this._createIntralineLayer(), @@ -119,6 +149,14 @@ limitations under the License. this.$.rangeLayer, ]; + // Get layers from plugins (if any). + for (const pluginLayer of this.$.jsAPI.getDiffLayers( + this.diffPath, this.changeNum, this.patchNum)) { + layers.push(pluginLayer); + } + + this._layers = layers; + this.async(() => { this._preRenderThread(); }); @@ -135,25 +173,27 @@ limitations under the License. this._builder = this._getDiffBuilder(this.diff, comments, prefs); this.$.processor.context = prefs.context; - this.$.processor.keyLocations = this._getCommentLocations(comments); + this.$.processor.keyLocations = this._getKeyLocations(comments, + this.lineOfInterest); this._clearDiffContent(); this._builder.addColumns(this.diffElement, prefs.font_size); const reporting = this.$.reporting; + const isBinary = !!(this.isImageDiff || this.diff.binary); reporting.time(TimingLabel.TOTAL); reporting.time(TimingLabel.CONTENT); this.dispatchEvent(new CustomEvent('render-start', {bubbles: true})); - return this.$.processor.process(this.diff.content, this.isImageDiff) + return this.$.processor.process(this.diff.content, isBinary) .then(() => { if (this.isImageDiff) { - this._builder.renderDiffImages(); + this._builder.renderDiff(); } this.dispatchEvent(new CustomEvent('render-content', {bubbles: true})); - if (this._anyLineTooLong()) { + if (this._diffTooLargeForSyntax()) { this.$.syntaxLayer.enabled = false; } @@ -219,12 +259,6 @@ limitations under the License. GrDiffBuilder.Side.RIGHT : GrDiffBuilder.Side.LEFT; }, - createCommentThreadGroup(changeNum, patchNum, path, - isOnParent, commentSide) { - return this._builder.createCommentThreadGroup(changeNum, patchNum, - path, isOnParent, commentSide); - }, - emitGroup(group, sectionEl) { this._builder.emitGroup(group, sectionEl); }, @@ -250,26 +284,58 @@ limitations under the License. this.$.syntaxLayer.cancel(); }, + _handlePreferenceError(pref) { + const message = `The value of the '${pref}' user preference is ` + + `invalid. Fix in diff preferences`; + this.dispatchEvent(new CustomEvent('show-alert', { + detail: { + message, + }, bubbles: true})); + throw Error(`Invalid preference value: ${pref}`); + }, + _getDiffBuilder(diff, comments, prefs) { + if (isNaN(prefs.tab_size) || prefs.tab_size <= 0) { + this._handlePreferenceError('tab size'); + return; + } + + if (isNaN(prefs.line_length) || prefs.line_length <= 0) { + this._handlePreferenceError('diff width'); + return; + } + + let builder = null; + const createFn = this.createCommentFn; if (this.isImageDiff) { - return new GrDiffBuilderImage(diff, comments, prefs, - this.projectName, this.diffElement, this.baseImage, - this.revisionImage); + builder = new GrDiffBuilderImage(diff, comments, createFn, prefs, + this.diffElement, this.baseImage, this.revisionImage); + } else if (diff.binary) { + // If the diff is binary, but not an image. + return new GrDiffBuilderBinary(diff, comments, prefs, + this.diffElement); } else if (this.viewMode === DiffViewMode.SIDE_BY_SIDE) { - return new GrDiffBuilderSideBySide(diff, comments, prefs, - this.projectName, this.diffElement, this._layers); + builder = new GrDiffBuilderSideBySide(diff, comments, createFn, + prefs, this.diffElement, this._layers); } else if (this.viewMode === DiffViewMode.UNIFIED) { - return new GrDiffBuilderUnified(diff, comments, prefs, - this.projectName, this.diffElement, this._layers); + builder = new GrDiffBuilderUnified(diff, comments, createFn, prefs, + this.diffElement, this._layers); + } + if (!builder) { + throw Error('Unsupported diff view mode: ' + this.viewMode); } - throw Error('Unsupported diff view mode: ' + this.viewMode); + return builder; }, _clearDiffContent() { this.diffElement.innerHTML = null; }, - _getCommentLocations(comments) { + /** + * @param {!Object} comments + * @param {Defs.LineOfInterest|null} lineOfInterest + */ + _getKeyLocations(comments, lineOfInterest) { const result = { left: {}, right: {}, @@ -283,6 +349,12 @@ limitations under the License. result[side][c.line || GrDiffLine.FILE] = true; } } + + if (lineOfInterest) { + const side = lineOfInterest.leftSide ? 'left' : 'right'; + result[side][lineOfInterest.number] = true; + } + return result; }, @@ -404,10 +476,32 @@ limitations under the License. }, false); }, + _diffTooLargeForSyntax() { + return this._anyLineTooLong() || + this.getDiffLength() > SYNTAX_MAX_DIFF_LENGTH; + }, + setBlame(blame) { if (!this._builder || !blame) { return; } this._builder.setBlame(blame); }, + + /** + * Get the approximate length of the diff as the sum of the maximum + * length of the chunks. + * @return {number} + */ + getDiffLength() { + return this.diff.content.reduce((sum, sec) => { + if (sec.hasOwnProperty('ab')) { + return sum + sec.ab.length; + } else { + return sum + Math.max( + sec.hasOwnProperty('a') ? sec.a.length : 0, + sec.hasOwnProperty('b') ? sec.b.length : 0); + } + }, 0); + }, }); })(); </script> |