Annotation updates

Change-Id: I146f76b9dcc1a92e18acec01481ad280fb431868
This commit is contained in:
Becky Siegel 2017-08-11 16:32:47 -07:00
parent ffd3eb03e7
commit 8d92d53db5
77 changed files with 537 additions and 194 deletions
polygerrit-ui/app
behaviors
elements
admin
gr-admin-view
gr-create-pointer-dialog
gr-create-project-dialog
gr-group
gr-plugin-list
gr-project-detail-list
gr-project
change-list
gr-change-list-item
gr-change-list-view
gr-change-list
gr-dashboard-view
change
gr-account-list
gr-change-actions
gr-change-metadata
gr-change-view
gr-comment-list
gr-confirm-rebase-dialog
gr-download-dialog
gr-file-list
gr-label-score-row
gr-label-scores
gr-message
gr-related-changes-list
gr-reply-dialog
core
gr-account-dropdown
gr-error-manager
gr-main-header
gr-navigation
diff
gr-comment-api
gr-diff-builder
gr-diff-comment-thread
gr-diff-comment
gr-diff-cursor
gr-diff-highlight
gr-diff-preferences
gr-diff-processor
gr-diff-selection
gr-diff-view
gr-diff
gr-patch-range-select
gr-ranged-comment-layer
gr-syntax-layer
gr-app.js
plugins/gr-plugin-host
settings
gr-account-info
gr-email-editor
gr-http-password
gr-registration-dialog
gr-settings-view
gr-ssh-editor
shared
gr-account-label
gr-autocomplete-dropdown
gr-autocomplete
gr-change-star
gr-cursor-manager
gr-download-commands
gr-editable-label
gr-formatted-text
gr-rest-api-interface
gr-storage
gr-textarea
scripts

@ -22,6 +22,7 @@ limitations under the License.
/** @polymerBehavior Gerrit.BaseUrlBehavior */
Gerrit.BaseUrlBehavior = {
/** @return {string} */
getBaseUrl() {
return window.CANONICAL_PATH || '';
},

@ -22,7 +22,7 @@ limitations under the License.
<script src="../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../test/common-test-setup.html"/>
<script>
/** @type {String} */
/** @type {string} */
window.CANONICAL_PATH = '/r';
</script>
<link rel="import" href="base-url-behavior.html">

@ -32,7 +32,7 @@ limitations under the License.
* Get the docs base URL from either the server config or by probing.
* @param {Object} config The server config.
* @param {!Object} restApi A REST API instance
* @return {!Promise<String>} A promise that resolves with the docs base
* @return {!Promise<string>} A promise that resolves with the docs base
* URL.
*/
getDocsBaseUrl(config, restApi) {

@ -40,6 +40,7 @@ limitations under the License.
/**
* Returns the complement to the given column array
* @param {Array} columns
* @return {!Array}
*/
getComplementColumns(columns) {
return this.columnNames.filter(column => {
@ -47,6 +48,11 @@ limitations under the License.
});
},
/**
* @param {string} columnToCheck
* @param {!Array} columnsToDisplay
* @return {boolean}
*/
isColumnHidden(columnToCheck, columnsToDisplay) {
return !columnsToDisplay.includes(columnToCheck);
},

@ -35,11 +35,19 @@ limitations under the License.
return this.getBaseUrl() + path + this.encodeURL(item, true);
},
/**
* @param {Object} params
* @return {string}
*/
getFilterValue(params) {
if (!params) { return null; }
return params.filter || null;
if (!params) { return ''; }
return params.filter || '';
},
/**
* @param {Object} params
* @return {number}
*/
getOffsetValue(params) {
if (params && params.offset) {
return params.offset;

@ -39,7 +39,9 @@ limitations under the License.
* this function checks for patchNum equality.
*
* @param {string|number} a
* @param {string|number} b
* @param {string|number|undefined} b Undefined sometimes because
* computeLatestPatchNum can return undefined.
* @return {boolean}
*/
patchNumEquals(a, b) {
return a + '' === b + '';
@ -180,6 +182,7 @@ limitations under the License.
return patchNums;
},
/** @return {number|undefined} */
computeLatestPatchNum(allPatchSets) {
if (!allPatchSets || !allPatchSets.length) { return undefined; }
if (allPatchSets[allPatchSets.length - 1].num ===

@ -20,6 +20,11 @@ limitations under the License.
window.Gerrit = window.Gerrit || {};
/** @polymerBehavior Gerrit.PathListBehavior */
Gerrit.PathListBehavior = {
/**
* @param {string} a
* @param {string} b
* @return {number}
*/
specialFilePathCompare(a, b) {
// The commit message always goes first.
const COMMIT_MESSAGE_PATH = '/COMMIT_MSG';

@ -33,7 +33,7 @@
return 'ontouchstart' in document.documentElement;
},
},
_tooltip: Element,
_tooltip: Object,
_titleText: String,
_hasSetupTooltipListeners: {
type: Boolean,

@ -22,6 +22,8 @@ limitations under the License.
// Must be declared outside behavior implementation to be accessed inside
// behavior functions.
/** @return {!Object} */
const getKeyboardEvent = function(e) {
e = Polymer.dom(e.detail ? e.detail.keyboardEvent : e);
// When e is a keyboardEvent, e.event is not null.
@ -55,6 +57,7 @@ limitations under the License.
},
// Alias for getKeyboardEvent.
/** @return {!Object} */
getKeyboardEvent(e) {
return getKeyboardEvent(e);
},

@ -101,6 +101,9 @@ limitations under the License.
return v.toString(16);
},
/**
* @return {string}
*/
changeBaseURL(changeNum, patchNum) {
let v = this.getBaseUrl() + '/changes/' + changeNum;
if (patchNum) {

@ -22,7 +22,7 @@ limitations under the License.
<script src="../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../test/common-test-setup.html"/>
<script>
/** @type {String} */
/** @type {string} */
window.CANONICAL_PATH = '/r';
</script>

@ -40,6 +40,7 @@
is: 'gr-admin-view',
properties: {
/** @type {?} */
params: Object,
path: String,
adminView: String,
@ -126,7 +127,7 @@
linkCopy.subsection = {
name: this._groupName,
view: 'gr-group',
url: `/admin/groups/${this.encodeURL(this._groupId, true)}`,
url: `/admin/groups/${this.encodeURL(this._groupId + '', true)}`,
children: [],
};
if (this._groupOwner) {
@ -135,8 +136,8 @@
name: 'Audit Log',
detailType: 'audit-log',
view: 'gr-group-audit-log',
url: `/admin/groups/${this.encodeURL(this._groupId, true)}` +
',audit-log',
url: '/admin/groups/' +
`${this.encodeURL(this._groupId + '', true)},audit-log`,
}
);
}
@ -198,6 +199,11 @@
return this._computeRelativeURL(link.url);
},
/**
* @param {string} itemView
* @param {Object} params
* @param {string=} opt_detailType
*/
_computeSelectedClass(itemView, params, opt_detailType) {
if (params.detailType && params.detailType !== opt_detailType) {
return '';

@ -68,7 +68,7 @@
page.show(this._computeItemUrl(this.itemDetail));
}
});
} else if (this.itemDetail === DETAIL_TYPES.tag) {
} else if (this.itemDetail === DETAIL_TYPES.tags) {
return this.$.restAPI.createProjectTag(this.projectName,
this._itemName, {revision: USE_HEAD})
.then(itemRegistered => {

@ -25,12 +25,13 @@
value: false,
},
/** @type {?} */
_projectConfig: {
type: Object,
value: () => { return {}; },
},
_projectCreated: {
type: Object,
type: Boolean,
value: false,
},

@ -61,6 +61,7 @@
value: false,
observer: '_loggedInChanged',
},
/** @type {?} */
_groupConfig: Object,
_groupName: Object,
_groupOwner: {

@ -28,7 +28,10 @@
/**
* Offset of currently visible query results.
*/
_offset: Number,
_offset: {
type: Number,
value: 0,
},
_path: {
type: String,
readOnly: true,
@ -51,7 +54,10 @@
type: Boolean,
value: true,
},
_filter: String,
_filter: {
type: String,
value: '',
},
},
behaviors: [

@ -73,6 +73,8 @@
_filter: String,
_refName: String,
_hasNewItemName: Boolean,
_isEditing: Boolean,
_revisedRef: String,
},
behaviors: [

@ -67,6 +67,7 @@
value: false,
observer: '_loggedInChanged',
},
/** @type {?} */
_projectConfig: Object,
_readOnly: {
type: Boolean,

@ -22,6 +22,8 @@
labelNames: {
type: Array,
},
/** @type {?} */
change: Object,
changeURL: {
type: String,
@ -31,6 +33,7 @@
type: Boolean,
value: false,
},
showNumber: Boolean,
},
behaviors: [

@ -54,6 +54,11 @@
/**
* State persisted across restamps of the element.
*
* Need sub-property declaration since it is used in template before
* assignment.
* @type {{ selectedChangeIndex: (number|undefined) }}
*
*/
viewState: {
type: Object,

@ -99,7 +99,6 @@ limitations under the License.
needs-review$="[[_computeItemNeedsReview(account, change, showReviewedState)]]"
change="[[change]]"
visible-change-table-columns="[[visibleChangeTableColumns]]"
show-number="[[showNumber]]"
show-star="[[showStar]]"
label-names="[[labelNames]]"></gr-change-list-item>
</template>

@ -86,6 +86,7 @@
value() { return document.body; },
},
changeTableColumns: Array,
visibleChangeTableColumns: Array,
},
behaviors: [

@ -49,6 +49,7 @@
type: Object,
value() { return {}; },
},
/** @type {{ selectedChangeIndex: number }} */
viewState: Object,
params: {
type: Object,

@ -34,6 +34,9 @@
change: Object,
filter: Function,
placeholder: String,
/**
* Needed for template checking since value is initially set to null.
* @type {?Object} */
pendingConfirmation: {
type: Object,
value: null,

@ -18,7 +18,7 @@
const ERR_COMMIT_EMPTY = 'The commit message cant be empty.';
const ERR_REVISION_ACTIONS = 'Couldnt load revision actions.';
/**
* @enum {number}
* @enum {string}
*/
const LabelStatus = {
/**
@ -44,6 +44,7 @@
* project owner or site administrator.
*/
IMPOSSIBLE: 'IMPOSSIBLE',
OPTIONAL: 'OPTIONAL',
};
// TODO(davido): Add the rest of the change actions.
@ -139,6 +140,7 @@
*/
properties: {
/** @type {{ branch: string, project: string }} */
change: Object,
actions: {
type: Object,
@ -169,6 +171,7 @@
type: String,
value: '',
},
/** @type {?} */
revisionActions: {
type: Object,
value() { return {}; },
@ -180,7 +183,7 @@
},
_actionLoadingMessage: {
type: String,
value: null,
value: '',
},
_allActionValues: {
type: Array,
@ -417,7 +420,7 @@
this.hidden = this._keyCount(actionsChangeRecord) === 0 &&
this._keyCount(revisionActionsChangeRecord) === 0 &&
additionalActions.length === 0;
this._actionLoadingMessage = null;
this._actionLoadingMessage = '';
this._disabledMenuActions = [];
const revisionActions = revisionActionsChangeRecord.base || {};
@ -449,7 +452,7 @@
* Get highest score for last missing permitted label for current change.
* Returns null if no labels permitted or more than one label missing.
*
* @return {{label: string, score: string}}
* @return {{label: string, score: string}|null}
*/
_getTopMissingApproval() {
if (!this.change ||
@ -668,9 +671,8 @@
},
/**
* Returns true if hasParent is defined (can be either true or false).
* returns false otherwise.
* @return {boolean} hasParent
* _hasKnownChainState set to true true if hasParent is defined (can be
* either true or false). set to false otherwise.
*/
_computeChainState(hasParent) {
this._hasKnownChainState = true;
@ -778,7 +780,7 @@
if (this._getActionOverflowIndex(type, key) !== -1) {
this.push('_disabledMenuActions', key === '/' ? 'delete' : key);
return function() {
this._actionLoadingMessage = null;
this._actionLoadingMessage = '';
this._disabledMenuActions = [];
}.bind(this);
}
@ -788,12 +790,18 @@
buttonEl.setAttribute('loading', true);
buttonEl.disabled = true;
return function() {
this._actionLoadingMessage = null;
this._actionLoadingMessage = '';
buttonEl.removeAttribute('loading');
buttonEl.disabled = false;
}.bind(this);
},
/**
* @param {string} endpoint
* @param {!Object|undefined} action
* @param {boolean} revAction
* @param {!Object|string=} opt_payload
*/
_fireAction(endpoint, action, revAction, opt_payload) {
const cleanupFn =
this._setLoadingOnButtonWithKey(action.__type, action.__key);
@ -861,6 +869,14 @@
});
},
/**
* @param {string} method
* @param {string|!Object|undefined} payload
* @param {string} actionEndpoint
* @param {boolean} revisionAction
* @param {?Function} cleanupFn
* @param {?Function=} opt_errorFn
*/
_send(method, payload, actionEndpoint, revisionAction, cleanupFn,
opt_errorFn) {
return this.fetchIsLatestKnown(this.change, this.$.restAPI)
@ -918,19 +934,19 @@
/**
* Merge sources of change actions into a single ordered array of action
* values.
* @param {splices} changeActionsRecord
* @param {splices} revisionActionsRecord
* @param {splices} primariesRecord
* @param {splices} additionalActionsRecord
* @param {Object} change The change object.
* @return {Array}
* @param {!Array} changeActionsRecord
* @param {!Array} revisionActionsRecord
* @param {!Array} primariesRecord
* @param {!Array} additionalActionsRecord
* @param {!Object} change The change object.
* @return {!Array}
*/
_computeAllActions(changeActionsRecord, revisionActionsRecord,
primariesRecord, additionalActionsRecord, change) {
const revisionActionValues = this._getActionValues(revisionActionsRecord,
primariesRecord, additionalActionsRecord, ActionType.REVISION);
const changeActionValues = this._getActionValues(changeActionsRecord,
primariesRecord, additionalActionsRecord, ActionType.CHANGE, change);
primariesRecord, additionalActionsRecord, ActionType.CHANGE);
const quickApprove = this._getQuickApproveAction();
if (quickApprove) {
changeActionValues.unshift(quickApprove);

@ -34,9 +34,13 @@
*/
properties: {
/** @type {?} */
change: Object,
commitInfo: Object,
mutable: Boolean,
/**
* @type {{ note_db_enabled: string }}
*/
serverConfig: Object,
_topicReadOnly: {
type: Boolean,
@ -235,6 +239,13 @@
return false;
},
/**
* Closure annotation for Polymer.prototype.splice is off.
* For now, supressing annotations.
*
* TODO(beckysiegel) submit Polymer PR
*
* @suppress {checkTypes} */
_onDeleteVote(e) {
e.preventDefault();
const target = Polymer.dom(e).rootTarget;

@ -68,6 +68,7 @@
type: Object,
observer: '_paramsChanged',
},
/** @type {?} */
viewState: {
type: Object,
notify: true,
@ -80,6 +81,7 @@
type: Object,
value() { return document.body; },
},
/** @type {?} */
_serverConfig: {
type: Object,
observer: '_startUpdateCheckTimer',
@ -99,10 +101,12 @@
computed: '_computeCanStartReview(_loggedIn, _change, _account)',
},
_comments: Object,
/** @type {?} */
_change: {
type: Object,
observer: '_changeChanged',
},
/** @type {?} */
_commitInfo: Object,
_files: Object,
_changeNum: String,
@ -119,6 +123,7 @@
computed: '_computeHideEditCommitMessage(_loggedIn, ' +
'_editingCommitMessage, _change)',
},
/** @type {?string} */
_latestCommitMessage: {
type: String,
value: '',
@ -129,6 +134,7 @@
computed:
'_computeChangeIdCommitMessageError(_latestCommitMessage, _change)',
},
/** @type {?} */
_patchRange: {
type: Object,
observer: '_updateSelected',
@ -147,6 +153,7 @@
value: false,
},
_loading: Boolean,
/** @type {?} */
_projectConfig: Object,
_rebaseOnCurrent: Boolean,
_replyButtonLabel: {
@ -180,6 +187,7 @@
type: Boolean,
value: true,
},
/** @type {?number} */
_updateCheckTimerHandle: Number,
_sortedRevisions: Array,
_editLoaded: {
@ -715,7 +723,7 @@
const t = labels[labelName];
if (!t) { return result; }
const approvals = t.all || [];
for (label of approvals) {
for (const label of approvals) {
if (label.value && label.value != labels[labelName].default_value) {
let labelClassName;
let labelValPrefix = '';
@ -853,6 +861,9 @@
});
},
/**
* @param {string=} opt_section
*/
_openReplyDialog(opt_section) {
this.$.replyOverlay.open().then(() => {
this.$.replyOverlay.setFocusStops(this.$.replyDialog.getFocusStops());
@ -946,7 +957,10 @@
this._latestCommitMessage = null;
}
const lineHeight = getComputedStyle(this).lineHeight;
this._lineHeight = lineHeight.slice(0, lineHeight.length - 2);
// Slice returns a number as a string, convert to an int.
this._lineHeight =
parseInt(lineHeight.slice(0, lineHeight.length - 2), 10);
this._change = change;
if (!this._patchRange || !this._patchRange.patchNum ||
@ -1122,9 +1136,9 @@
/**
* @param {Object} revisions The revisions object keyed by revision hashes
* @param {Object} patchSet A revision already fetched from {revisions}
* @return {string} the SHA hash corresponding to the revision.
* @param {!Object} revisions The revisions object keyed by revision hashes
* @param {?Object} patchSet A revision already fetched from {revisions}
* @return {string|undefined} the SHA hash corresponding to the revision.
*/
_getPatchsetHash(revisions, patchSet) {
for (const rev in revisions) {
@ -1304,7 +1318,9 @@
},
_cancelUpdateCheckTimer() {
this.cancelAsync(this._updateCheckTimerHandle);
if (this._updateCheckTimerHandle) {
this.cancelAsync(this._updateCheckTimerHandle);
}
this._updateCheckTimerHandle = null;
},

@ -32,6 +32,8 @@
patchNum: Number,
commentLinks: Object,
projectName: String,
/** @type {?} */
projectConfig: Object,
},
_computeFilesFromComments(comments) {

@ -30,6 +30,10 @@
*/
properties: {
/**
* Weird API usage requires this to be String or Null. Add this so
* the closure compiler doesn't complain.
* @type {?string} */
base: String,
branch: String,
hasParent: Boolean,
@ -62,7 +66,7 @@
this.fire('cancel', null, {bubbles: false});
},
_handleRebaseOnOther(e) {
_handleRebaseOnOther() {
this.$.parentInput.focus();
},
@ -73,15 +77,15 @@
* rebased on top of the target branch. Leaving out the base implies that it
* should be rebased on top of its current parent.
*/
_handleRebaseOnTip(e) {
_handleRebaseOnTip() {
this.base = '';
},
_handleRebaseOnParent(e) {
_handleRebaseOnParent() {
this.base = null;
},
_handleEnterChangeNumberTap(e) {
_handleEnterChangeNumberTap() {
this.$.rebaseOnOtherInput.checked = true;
},

@ -24,8 +24,10 @@
*/
properties: {
/** @type {{ revisions: Array }} */
change: Object,
patchNum: String,
/** @type {?} */
config: Object,
_schemes: {
@ -82,28 +84,55 @@
return commands;
},
/**
* @param {!Object} change
* @param {number|string} patchNum
*
* @return {string}
*/
_computeZipDownloadLink(change, patchNum) {
return this._computeDownloadLink(change, patchNum, true);
},
/**
* @param {!Object} change
* @param {number|string} patchNum
*
* @return {string}
*/
_computeZipDownloadFilename(change, patchNum) {
return this._computeDownloadFilename(change, patchNum, true);
},
_computeDownloadLink(change, patchNum, zip) {
/**
* @param {!Object} change
* @param {number|string} patchNum
* @param {boolean=} opt_zip
*
* @return {string} Not sure why there was a mismatch
*/
_computeDownloadLink(change, patchNum, opt_zip) {
return this.changeBaseURL(change._number, patchNum) + '/patch?' +
(zip ? 'zip' : 'download');
(opt_zip ? 'zip' : 'download');
},
_computeDownloadFilename(change, patchNum, zip) {
let shortRev;
/**
* @param {!Object} change
* @param {number|string} patchNum
* @param {boolean=} opt_zip
*
* @return {string}
*/
_computeDownloadFilename(change, patchNum, opt_zip) {
let shortRev = '';
for (const rev in change.revisions) {
if (this.patchNumEquals(change.revisions[rev]._number, patchNum)) {
shortRev = rev.substr(0, 7);
break;
}
}
return shortRev + '.diff.' + (zip ? 'zip' : 'base64');
return shortRev + '.diff.' + (opt_zip ? 'zip' : 'base64');
},
_computeArchiveDownloadLink(change, patchNum, format) {

@ -35,6 +35,7 @@
is: 'gr-file-list',
properties: {
/** @type {?} */
patchRange: {
type: Object,
observer: '_updateSelected',
@ -54,6 +55,7 @@
type: Object,
value() { return document.body; },
},
/** @type {?} */
change: Object,
diffViewMode: {
type: String,
@ -80,6 +82,7 @@
notify: true,
observer: '_updateDiffPreferences',
},
/** @type {?} */
_userPrefs: Object,
_localPrefs: Object,
_showInlineDiffs: Boolean,
@ -87,6 +90,7 @@
type: Number,
notify: true,
},
/** @type {?} */
_patchChange: {
type: Object,
computed: '_calculatePatchChange(_files)',
@ -283,7 +287,7 @@
}
},
_expandAllDiffs(e) {
_expandAllDiffs() {
this._showInlineDiffs = true;
// Find the list of paths that are in the file list, but not in the
@ -300,7 +304,7 @@
this.splice(...['_expandedFilePaths', 0, 0].concat(newPaths));
},
_collapseAllDiffs(e) {
_collapseAllDiffs() {
this._showInlineDiffs = false;
this._expandedFilePaths = [];
this.$.diffCursor.handleDiffUpdate();
@ -330,6 +334,12 @@
});
},
/**
* @param {!Array} comments
* @param {number} patchNum
* @param {string} path
* @param {string=} opt_noun
*/
_computeCountString(comments, patchNum, path, opt_noun) {
if (!comments) { return ''; }
@ -345,8 +355,8 @@
* Computes a string counting the number of unresolved comment threads in a
* given file and path.
*
* @param {Object} comments
* @param {Object} drafts
* @param {!Object} comments
* @param {!Object} drafts
* @param {number} patchNum
* @param {string} path
* @return {string}
@ -642,6 +652,9 @@
diff.patchRange.patchNum, this.patchRange.basePatchNum);
},
/**
* @param {number=} opt_index
*/
_openSelectedFile(opt_index) {
if (opt_index != null) {
this.$.fileCursor.setCursorAtIndex(opt_index);
@ -816,7 +829,7 @@
*
* Use side-by-side if there is no view mode or preferences.
*
* @return {String}
* @return {string}
*/
_getDiffViewMode(diffViewMode, userPrefs) {
if (diffViewMode) {
@ -858,7 +871,7 @@
* entries in the expanded list, then render each diff corresponding in
* order by waiting for the previous diff to finish before starting the next
* one.
* @param {splice} record The splice record in the expanded paths list.
* @param {!Array} record The splice record in the expanded paths list.
*/
_expandedPathsChanged(record) {
if (!record) { return; }
@ -890,9 +903,9 @@
* Given an array of paths and a NodeList of diff elements, render the diff
* for each path in order, awaiting the previous render to complete before
* continung.
* @param {!Array<!String>} paths
* @param {!NodeList<!GrDiffElement>} diffElements
* @param {Number} initialCount The total number of paths in the pass. This
* @param {!Array<string>} paths
* @param {!NodeList<!Object>} diffElements (GrDiffElement)
* @param {number} initialCount The total number of paths in the pass. This
* is used to generate log messages.
* @return {!Promise}
*/
@ -918,9 +931,9 @@
/**
* In the given NodeList of diff elements, find the diff for the given path.
* @param {!String} path
* @param {!NodeList<!GrDiffElement>} diffElements
* @return {!GrDiffElement}
* @param {string} path
* @param {!NodeList<!Object>} diffElements (GrDiffElement)
* @return {!Object|undefined} (GrDiffElement)
*/
_findDiffByPath(path, diffElements) {
for (let i = 0; i < diffElements.length; i++) {
@ -941,13 +954,13 @@
* Update the loading class for the file list rows. The update is inside a
* debouncer so that the file list doesn't flash gray when the API requests
* are reasonably fast.
* @param {string} loading
* @param {boolean} loading
*/
_loadingChanged(loading) {
this.debounce('loading-change', () => {
// Only show set the loading if there have been files loaded to show. In
// this way, the gray loading style is not shown on initial loads.
this.classList.toggle('loading', loading && this._files.length);
this.classList.toggle('loading', loading && !!this._files.length);
}, LOADING_DEBOUNCE_INTERVAL);
},

@ -17,6 +17,9 @@
Polymer({
is: 'gr-label-score-row',
properties: {
/**
* @type {{ name: string }}
*/
label: Object,
labels: Object,
name: {
@ -54,12 +57,12 @@
_computeBlankItems(permittedLabels, label, side) {
if (!permittedLabels || !permittedLabels[label]) { return []; }
const startPosition = this.labelValues[parseInt(
permittedLabels[label][0])];
permittedLabels[label][0], 10)];
if (side === 'start') {
return new Array(startPosition);
}
const endPosition = this.labelValues[parseInt(
permittedLabels[label][permittedLabels[label].length - 1])];
permittedLabels[label][permittedLabels[label].length - 1], 10)];
return new Array(Object.keys(this.labelValues).length - endPosition - 1);
},

@ -25,6 +25,7 @@
type: Object,
observer: '_computeColumns',
},
/** @type {?} */
change: Object,
_labelValues: Object,
},

@ -39,6 +39,7 @@
properties: {
changeNum: Number,
/** @type {?} */
message: Object,
author: {
type: Object,
@ -79,6 +80,10 @@
observer: '_projectNameChanged',
},
_commentLinks: Object,
/**
* @type {{ commentlinks: Array }}
*/
projectConfig: Object,
// Computed property needed to trigger Polymer value observing.
_expanded: {
type: Object,

@ -22,6 +22,7 @@
hasParent: {
type: Boolean,
notify: true,
value: false,
},
patchNum: String,
parentChange: Object,
@ -39,6 +40,7 @@
computed: '_computeConnectedRevisions(change, patchNum, ' +
'_relatedResponse.changes)',
},
/** @type {?} */
_relatedResponse: {
type: Object,
value() { return {changes: []}; },
@ -124,9 +126,9 @@
* Determines whether or not the given change has a parent change. If there
* is a relation chain, and the change id is not the last item of the
* relation chain, there is a parent.
* @param {Number} currentChangeId
* @param {Array} relatedChanges
* @return {Boolean}
* @param {number} currentChangeId
* @param {!Array} relatedChanges
* @return {boolean}
*/
_calculateHasParent(currentChangeId, relatedChanges) {
return relatedChanges.length > 0 &&

@ -74,6 +74,9 @@
*/
properties: {
/**
* @type {{ _number: number, removable_reviewers: Array }}
*/
change: Object,
patchNum: String,
canBeStarted: {
@ -95,12 +98,14 @@
value: '',
},
diffDrafts: Object,
/** @type {!Function} */
filterReviewerSuggestion: {
type: Function,
value() {
return this._filterReviewerSuggestionGenerator(false);
},
},
/** @type {!Function} */
filterCCSuggestion: {
type: Function,
value() {
@ -108,7 +113,13 @@
},
},
permittedLabels: Object,
/**
* @type {{ note_db_enabled: boolean }}
*/
serverConfig: Object,
/**
* @type {{ commentlinks: Array }}
*/
projectConfig: Object,
knownLatestState: String,
underReview: {
@ -118,6 +129,7 @@
_account: Object,
_ccs: Array,
/** @type {?Object} */
_ccPendingConfirmation: {
type: Object,
observer: '_reviewerPendingConfirmationUpdated',
@ -127,12 +139,14 @@
computed: '_computeMessagePlaceholder(canBeStarted)',
},
_owner: Object,
/** @type {?} */
_pendingConfirmationDetails: Object,
_includeComments: {
type: Boolean,
value: true,
},
_reviewers: Array,
/** @type {?Object} */
_reviewerPendingConfirmation: {
type: Object,
observer: '_reviewerPendingConfirmationUpdated',
@ -296,8 +310,8 @@
* Resets the state of the _reviewersPendingRemove object, and removes
* accounts if necessary.
*
* @param {Boolean} isCancel true if the action is a cancel.
* @param {Object} opt_accountIdsTransferred map of account IDs that must
* @param {boolean} isCancel true if the action is a cancel.
* @param {Object=} opt_accountIdsTransferred map of account IDs that must
* not be removed, because they have been readded in another state.
*/
_purgeReviewersPendingRemove(isCancel, opt_accountIdsTransferred) {
@ -322,8 +336,11 @@
* Removes an account from the change, both on the backend and the client.
* Does nothing if the account is a pending addition.
*
* @param {Object} account
* @param {ReviewerTypes} type
* @param {!Object} account
* @param {string} type
*
* * TODO(beckysiegel) submit Polymer PR
* @suppress {checkTypes}
*/
_removeAccount(account, type) {
if (account._pendingAdd) { return; }
@ -605,8 +622,8 @@
* Generates a function to filter out reviewer/CC entries. When isCCs is
* truthy, the function filters out entries that already exist in this._ccs.
* When falsy, the function filters entries that exist in this._reviewers.
* @param {Boolean} isCCs
* @return {Function}
* @param {boolean} isCCs
* @return {!Function}
*/
_filterReviewerSuggestionGenerator(isCCs) {
return suggestion => {

@ -47,7 +47,7 @@
if (cfg && cfg.auth && cfg.auth.switch_account_url) {
this._switchAccountUrl = cfg.auth.switch_account_url;
} else {
this._switchAccountUrl = null;
this._switchAccountUrl = '';
}
this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
});

@ -36,7 +36,9 @@
*/
knownAccountId: Number,
_alertElement: Element,
/** @type {?Object} */
_alertElement: Object,
/** @type {?number} */
_hideAlertHandle: Number,
_refreshingCredentials: {
type: Boolean,
@ -116,12 +118,18 @@
return this.$.restAPI.getLoggedIn();
},
/**
* @param {string} text
* @param {?string=} opt_actionText
* @param {?Function=} opt_actionCallback
* @param {?boolean=} opt_dismissOnNavigation
*/
_showAlert(text, opt_actionText, opt_actionCallback,
dismissOnNavigation) {
opt_dismissOnNavigation) {
if (this._alertElement) { return; }
this._clearHideAlertHandle();
if (dismissOnNavigation) {
if (opt_dismissOnNavigation) {
// Persist alert until navigation.
this.listen(document, 'location-change', '_hideAlert');
} else {

@ -72,6 +72,7 @@
notify: true,
},
/** @type {?Object} */
_account: Object,
_adminLinks: {
type: Array,
@ -125,11 +126,12 @@
},
_handleLocationChange(e) {
if (this.getBaseUrl()) {
const baseUrl = this.getBaseUrl();
if (baseUrl) {
// Strip the canonical path from the path since needing canonical in
// the path is uneeded and breaks the url.
this._loginURL = this.getBaseUrl() + '/login/' + encodeURIComponent(
'/' + window.location.pathname.substring(this.getBaseUrl().length) +
this._loginURL = baseUrl + '/login/' + encodeURIComponent(
'/' + window.location.pathname.substring(baseUrl.length) +
window.location.search +
window.location.hash);
} else {

@ -85,6 +85,10 @@ limitations under the License.
*/
_upgradeUrl: uninitialized,
/**
* @param {number=} patchNum
* @param {number|string=} basePatchNum
*/
_checkPatchRange(patchNum, basePatchNum) {
if (basePatchNum && !patchNum) {
throw new Error('Cannot use base patch number without patch number.');
@ -195,7 +199,6 @@ limitations under the License.
* @param {number=} opt_patchNum
* @param {number|string=} opt_basePatchNum The string 'PARENT' can be
* used for none.
* @return {string}
*/
navigateToChange(change, opt_patchNum, opt_basePatchNum) {
this._navigate(this.getUrlForChange(change, opt_patchNum,
@ -203,8 +206,8 @@ limitations under the License.
},
/**
* @param {!Object} change The change object.
* @param {!string} path The file path.
* @param {{ _number: number, project: string }} change The change object.
* @param {string} path The file path.
* @param {number=} opt_patchNum
* @param {number|string=} opt_basePatchNum The string 'PARENT' can be
* used for none.
@ -247,7 +250,7 @@ limitations under the License.
/**
* @param {!Object} change The change object.
* @param {!string} path The file path.
* @param {string} path The file path.
* @param {number=} opt_patchNum
* @param {number|string=} opt_basePatchNum The string 'PARENT' can be
* used for none.
@ -270,7 +273,7 @@ limitations under the License.
/**
* Navigate to an arbitrary relative URL.
* @param {!string} relativeUrl
* @param {string} relativeUrl
*/
navigateToRelativeUrl(relativeUrl) {
if (!relativeUrl.startsWith('/')) {

@ -20,9 +20,13 @@
is: 'gr-comment-api',
properties: {
/** @type {number} */
_changeNum: Number,
/** @type {!Object|undefined} */
_comments: Object,
/** @type {!Object|undefined} */
_drafts: Object,
/** @type {!Object|undefined} */
_robotComments: Object,
},
@ -35,7 +39,7 @@
* number. The returned promise resolves when the comments have loaded, but
* does not yield the comment data.
*
* @param {!number} changeNum
* @param {number} changeNum
* @return {!Promise}
*/
loadAll(changeNum) {
@ -91,7 +95,7 @@
* @param {!string} path
* @param {!Object} patchRange The patch-range object containing patchNum
* and basePatchNum properties to represent the range.
* @param {Object} opt_projectConfig Optional project config object to
* @param {Object=} opt_projectConfig Optional project config object to
* include in the meta sub-object.
* @return {Object}
*/
@ -160,7 +164,7 @@
* Whether the given comment should be included in the given patch range.
* @param {!Object} comment
* @param {!Object} range
* @return {boolean}
* @return {boolean|undefined}
*/
_isInPatchRange(comment, range) {
return this._isInBaseOfPatchRange(comment, range) ||

@ -393,7 +393,7 @@ limitations under the License.
},
/**
* @return {Boolean} whether any of the lines in _groups are longer
* @return {boolean} whether any of the lines in _groups are longer
* than SYNTAX_MAX_LINE_LENGTH.
*/
_anyLineTooLong() {

@ -153,12 +153,12 @@
/**
* Find line elements or line objects by a range of line numbers and a side.
*
* @param {Number} start The first line number
* @param {Number} end The last line number
* @param {String} opt_side The side of the range. Either 'left' or 'right'.
* @param {Array<GrDiffLine>} out_lines The output list of line objects. Use
* @param {number} start The first line number
* @param {number} end The last line number
* @param {string} opt_side The side of the range. Either 'left' or 'right'.
* @param {!Array<GrDiffLine>} out_lines The output list of line objects. Use
* null if not desired.
* @param {Array<HTMLElement>} out_elements The output list of line elements.
* @param {!Array<HTMLElement>} out_elements The output list of line elements.
* Use null if not desired.
*/
GrDiffBuilder.prototype.findLinesByRange = function(start, end, opt_side,
@ -443,7 +443,7 @@
/**
* Returns the text length after normalizing unicode and tabs.
* @return {Number} The normalized length of the text.
* @return {number} The normalized length of the text.
*/
GrDiffBuilder.prototype._textLength = function(text, tabSize) {
text = text.replace(REGEX_ASTRAL_SYMBOL, '_');
@ -536,9 +536,9 @@
* elements in place of tab characters. In each case tab elements are given
* the width needed to reach the next tab-stop.
*
* @param {String} A line of text potentially containing tab characters.
* @param {Number} The width for tabs.
* @return {String} An HTML string potentially containing tab elements.
* @param {string} A line of text potentially containing tab characters.
* @param {number} The width for tabs.
* @return {string} An HTML string potentially containing tab elements.
*/
GrDiffBuilder.prototype._addTabWrappers = function(line, tabSize) {
if (!line.length) { return ''; }
@ -600,7 +600,7 @@
* Finds the next DIV.contentText element following the given element, and on
* the same side. Will only search within a group.
* @param {HTMLElement} content
* @param {String} side Either 'left' or 'right'
* @param {string} side Either 'left' or 'right'
* @return {HTMLElement}
*/
GrDiffBuilder.prototype._getNextContentOnSide = function(content, side) {
@ -610,8 +610,8 @@
/**
* Determines whether the given group is either totally an addition or totally
* a removal.
* @param {GrDiffGroup} group
* @return {Boolean}
* @param {!Object} group (GrDiffGroup)
* @return {boolean}
*/
GrDiffBuilder.prototype._isTotal = function(group) {
return group.type === GrDiffGroup.Type.DELTA &&

@ -213,6 +213,9 @@
return !!comment.__draft;
},
/**
* @param {boolean=} opt_quote
*/
_processCommentReply(opt_quote) {
const comment = this._lastComment;
let quoteStr;
@ -273,6 +276,10 @@
return d;
},
/**
* @param {number=} opt_lineNum
* @param {!Object=} opt_range
*/
_newDraft(opt_lineNum, opt_range) {
const d = {
__draft: true,

@ -53,6 +53,7 @@
properties: {
changeNum: String,
/** @type {?} */
comment: {
type: Object,
notify: true,
@ -88,6 +89,7 @@
value: true,
observer: '_toggleCollapseClass',
},
/** @type {?} */
projectConfig: Object,
robotButtonDisabled: Boolean,
_isAdmin: {
@ -215,6 +217,11 @@
}
},
/**
* @param {!Object=} opt_mixin
*
* @return {!Object}
*/
_getEventPayload(opt_mixin) {
return Object.assign({}, opt_mixin, {
comment: this.comment,

@ -43,6 +43,7 @@
type: String,
value: DiffSides.RIGHT,
},
/** @type {!HTMLElement|undefined} */
diffRow: {
type: Object,
notify: true,
@ -61,6 +62,8 @@
* If set, the cursor will attempt to move to the line number (instead of
* the first chunk) the next time the diff renders. It is set back to null
* when used.
*
* @type (?number)
*/
initialLineNumber: {
type: Number,
@ -147,6 +150,11 @@
this._fixSide();
},
/**
* @param {number} number
* @param {string} side
* @param {string=} opt_path
*/
moveToLineNumber(number, side, opt_path) {
const row = this._findRowByNumberAndFile(number, side, opt_path);
if (row) {
@ -157,7 +165,7 @@
/**
* Get the line number element targeted by the cursor row and side.
* @return {DOMElement}
* @return {?Element|undefined}
*/
getTargetLineElement() {
let lineElSelector = '.lineNum';
@ -221,7 +229,7 @@
* Get a short address for the location of the cursor. Such as '123' for
* line 123 of the revision, or 'b321' for line 321 of the base patch.
* Returns an empty string if an address is not available.
* @return {String}
* @return {string}
*/
getAddress() {
if (!this.diffRow) { return ''; }

@ -28,8 +28,8 @@
/**
* The DOM API textContent.length calculation is broken when the text
* contains Unicode. See https://mathiasbynens.be/notes/javascript-unicode .
* @param {Text} A text node.
* @return {Number} The length of the text.
* @param {!Text} node text node.
* @return {number} The length of the text.
*/
getLength(node) {
return this.getStringLength(node.textContent);

@ -20,6 +20,11 @@
properties: {
comments: Object,
loggedIn: Boolean,
/**
* querySelector can return null, so needs to be nullable.
*
* @type {?HTMLElement}
* */
_cachedDiffBuilder: Object,
isAttached: Boolean,
},
@ -99,7 +104,7 @@
* Merges multiple ranges, accounts for triple click, accounts for
* syntax highligh, convert native DOM Range objects to Gerrit concepts
* (line, side, etc).
* @return {{
* @return {({
* start: {
* node: Node,
* side: string,
@ -112,7 +117,7 @@
* line: Number,
* column: Number
* }
* }}
* })|null|!Object}
*/
_getNormalizedRange() {
const selection = window.getSelection();
@ -134,6 +139,7 @@
/**
* Normalize a specific DOM Range.
* @return {!Object} fixed normalized range
*/
_normalizeRange(domRange) {
const range = GrRangeNormalizer.normalize(domRange);
@ -195,12 +201,12 @@
*
* @param {Node} node td.content child
* @param {number} offset offset within node
* @return {{
* @return {({
* node: Node,
* side: string,
* line: Number,
* column: Number
* }}
* }|undefined)}
*/
_normalizeSelectionSide(node, offset) {
let column;
@ -251,6 +257,7 @@
return;
}
const domRange = window.getSelection().getRangeAt(0);
/** @type {?} */
const start = normalizedRange.start;
if (!start) {
return;
@ -280,7 +287,9 @@
if (start.line === end.line) {
actionBox.placeAbove(domRange);
} else if (start.node instanceof Text) {
actionBox.placeAbove(start.node.splitText(start.column));
if (start.column) {
actionBox.placeAbove(start.node.splitText(start.column));
}
start.node.parentElement.normalize(); // Undo splitText from above.
} else if (start.node.classList.contains('content') &&
start.node.firstChild) {
@ -325,7 +334,7 @@
* Traverse Element from right to left, call callback for each node.
* Stops if callback returns true.
*
* @param {!Node} startNode
* @param {!Element} startNode
* @param {function(Node):boolean} callback
* @param {Object=} opt_flags If flags.left is true, traverse left.
*/
@ -350,7 +359,7 @@
* Get length of a node. If the node is a content node, then only give the
* length of its .contentText child.
*
* @param {!Node} node
* @param {?Element} node this is sometimes passed as null.
* @return {number}
*/
_getLength(node) {

@ -27,8 +27,8 @@
* highlighting, the containers are remapped to the .contentText divs that
* contain the entire line of code.
*
* @param {Object} range - the standard DOM selector range.
* @return {Object} A modified version of the range that correctly accounts
* @param {!Object} range - the standard DOM selector range.
* @return {!Object} A modified version of the range that correctly accounts
* for syntax highlighting.
*/
normalize(range) {
@ -94,8 +94,8 @@
/**
* The DOM API textContent.length calculation is broken when the text
* contains Unicode. See https://mathiasbynens.be/notes/javascript-unicode .
* @param {Text} A text node.
* @return {Number} The length of the text.
* @param {text} node A text node.
* @return {number} The length of the text.
*/
_getLength(node) {
return node.textContent.replace(REGEX_ASTRAL_SYMBOL, '_').length;

@ -32,6 +32,7 @@
reflectToAttribute: true,
},
/** @type {?} */
_newPrefs: Object,
_newLocalPrefs: Object,
},

@ -77,6 +77,7 @@
value: 64,
},
/** @type {number|undefined} */
_nextStepHandle: Number,
_isScrolling: Boolean,
},
@ -225,14 +226,14 @@
/**
* Take rows of a shared diff section and produce an array of corresponding
* (potentially collapsed) groups.
* @param {Array<String>} rows
* @param {Number} context
* @param {Number} startLineNumLeft
* @param {Number} startLineNumRight
* @param {String} opt_sectionEnd String representing whether this is the
* @param {!Array<string>} rows
* @param {number} context
* @param {number} startLineNumLeft
* @param {number} startLineNumRight
* @param {?string=} opt_sectionEnd String representing whether this is the
* first section or the last section or neither. Use the values 'first',
* 'last' and null respectively.
* @return {Array<GrDiffGroup>}
* @return {!Array<!Object>} Array of GrDiffGroup
*/
_sharedGroupsFromRows(rows, context, startLineNumLeft,
startLineNumRight, opt_sectionEnd) {
@ -288,11 +289,11 @@
/**
* Take the rows of a delta diff section and produce the corresponding
* group.
* @param {Array<String>} rowsAdded
* @param {Array<String>} rowsRemoved
* @param {Number} startLineNumLeft
* @param {Number} startLineNumRight
* @return {GrDiffGroup}
* @param {!Array<string>} rowsAdded
* @param {!Array<string>} rowsRemoved
* @param {number} startLineNumLeft
* @param {number} startLineNumRight
* @return {!Object} (Gr-Diff-Group)
*/
_deltaGroupFromRows(rowsAdded, rowsRemoved, startLineNumLeft,
startLineNumRight, highlights) {
@ -309,7 +310,7 @@
},
/**
* @return {Array<GrDiffLine>}
* @return {!Array<!Object>} Array of GrDiffLines
*/
_deltaLinesFromRows(lineType, rows, startLineNum,
opt_highlights) {
@ -348,8 +349,8 @@
* 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.
* @param {Object} content The diff content object.
* @return {Object} A new diff content object with regions split up.
* @param {?} content The diff content object. (has to be iterable)
* @return {!Object} A new diff content object with regions split up.
*/
_splitCommonGroupsWithComments(content) {
const result = [];
@ -492,7 +493,7 @@
* If a group is an addition or a removal, break it down into smaller groups
* of that type using the MAX_GROUP_SIZE. If the group is a shared section
* or a delta it is returned as the single element of the result array.
* @param {!Object} A raw chunk from a diff response.
* @param {!Object} group A raw chunk from a diff response.
* @return {!Array<!Array<!Object>>}
*/
_breakdownGroup(group) {

@ -31,6 +31,7 @@
properties: {
diff: Object,
/** @type {?Object} */
_cachedDiffBuilder: Object,
_linesCache: {
type: Object,
@ -144,14 +145,14 @@
* true, it returns only the text of comments within the selection.
* Otherwise it returns the text of the selected diff region.
*
* @param {!string} The side that is selected.
* @param {boolean} Whether or not a comment is selected.
* @param {!string} side The side that is selected.
* @param {boolean} commentSelected Whether or not a comment is selected.
* @return {string} The selected text.
*/
_getSelectedText(side, commentSelected) {
const sel = window.getSelection();
if (sel.rangeCount != 1) {
return; // No multi-select support yet.
return ''; // No multi-select support yet.
}
if (commentSelected) {
return this._getCommentLines(sel, side);
@ -170,10 +171,10 @@
/**
* Query the diff object for the selected lines.
*
* @param {int} startLineNum
* @param {int} startOffset
* @param {int} endLineNum
* @param {int} endOffset
* @param {number} startLineNum
* @param {number} startOffset
* @param {number} endLineNum
* @param {number} endOffset
* @param {!string} side The side that is currently selected.
* @return {string} The selected diff text.
*/
@ -192,7 +193,7 @@
* Query the diff object for the lines from a particular side.
*
* @param {!string} side The side that is currently selected.
* @return {Array.string} An array of strings indexed by line number.
* @return {!Array<string>} An array of strings indexed by line number.
*/
_getDiffLines(side) {
if (this._linesCache[side]) {
@ -254,9 +255,9 @@
* of the text content within that selection.
* Using a domNode that isn't in the selection returns an empty string.
*
* @param {Element} domNode The root DOM node.
* @param {Selection} sel The selection.
* @param {Range} range The normalized selection range.
* @param {!Node} domNode The root DOM node.
* @param {!Selection} sel The selection.
* @param {!Range} range The normalized selection range.
* @return {string} The text within the selection.
*/
_getTextContentForRange(domNode, sel, range) {

@ -55,6 +55,9 @@
type: Object,
value() { return document.body; },
},
/**
* @type {{ diffMode: (string|undefined) }}
*/
changeViewState: {
type: Object,
notify: true,
@ -63,6 +66,13 @@
},
_patchRange: Object,
/**
* @type {{
* subject: string,
* project: string,
* revisions: string,
* }}
*/
_change: Object,
_changeNum: String,
_diff: Object,
@ -400,7 +410,7 @@
/**
* @param {?string} path The path of the current file being shown.
* @param {Array.<string>} fileList The list of files in this change and
* @param {!Array<string>} fileList The list of files in this change and
* patch range.
* @param {number} direction Either 1 (next file) or -1 (prev file).
* @param {(number|boolean)} opt_noUp Whether to return to the change view
@ -433,12 +443,12 @@
* * null - When no navigation is possible for the given direction.
*
* @param {?string} path The path of the current file being shown.
* @param {Array.<string>} fileList The list of files in this change and
* @param {!Array<string>} fileList The list of files in this change and
* patch range.
* @param {number} direction Either 1 (next file) or -1 (prev file).
* @param {(number|boolean)} opt_noUp Whether to return to the change view
* @param {?number|boolean=} opt_noUp Whether to return to the change view
* when advancing the file goes outside the bounds of fileList.
* @return {Object}
* @return {?Object}
*/
_getNavLinkPath(path, fileList, direction, opt_noUp) {
if (!path || fileList.length === 0) { return null; }
@ -589,6 +599,10 @@
* When the latest patch of the change is selected (and there is no base
* patch) then the patch range need not appear in the URL. Return a patch
* range object with undefined values when a range is not needed.
*
* @param {!Object} patchRange
* @param {!Object} revisions
* @return {!Object}
*/
_getChangeUrlRange(patchRange, revisions) {
let patchNum = undefined;
@ -702,7 +716,7 @@
*
* Use side-by-side if the user is not logged in.
*
* @return {String}
* @return {string}
*/
_getDiffViewMode() {
if (this.changeViewState.diffMode) {
@ -721,7 +735,7 @@
_onLineSelected(e, detail) {
this.$.cursor.moveToLineNumber(detail.number, detail.side);
history.replaceState(null, null, '#' + this.$.cursor.getAddress());
history.replaceState(null, '', '#' + this.$.cursor.getAddress());
},
_computeDownloadLink(changeNum, patchRange, path) {

@ -106,7 +106,9 @@
type: String,
value: '',
},
/** @type {?Object} */
_baseImage: Object,
/** @type {?Object} */
_revisionImage: Object,
/**
@ -114,6 +116,8 @@
* been bypassed. If the value is null, then the safety has not been
* bypassed. If the value is a number, then that number represents the
* context preference to use when rendering the bypassed diff.
*
* @type (number|null)
*/
_safetyBypass: {
type: Number,
@ -147,6 +151,7 @@
}
},
/** @return {!Promise} */
reload() {
this.$.diffBuilder.cancel();
this._safetyBypass = null;
@ -168,6 +173,7 @@
});
},
/** @return {!Array<!HTMLElement>} */
getCursorStops() {
if (this.hidden && this.noAutoRender) {
return [];
@ -176,6 +182,7 @@
return Polymer.dom(this.root).querySelectorAll('.diff-row');
},
/** @return {boolean} */
isRangeSelected() {
return this.$.highlights.isRangeSelected();
},
@ -184,15 +191,18 @@
this.toggleClass('no-left');
},
/** @return {boolean}} */
_canRender() {
return this.changeNum && this.patchRange && this.path &&
return !!this.changeNum && !!this.patchRange && !!this.path &&
!this.noAutoRender;
},
/** @return {!Array<!HTMLElement>} */
_getCommentThreads() {
return Polymer.dom(this.root).querySelectorAll('gr-diff-comment-thread');
},
/** @return {string} */
_computeContainerClass(loggedIn, viewMode, displayLine) {
const classes = ['diffContainer'];
switch (viewMode) {
@ -263,7 +273,7 @@
const side = e.detail.side;
const lineNum = range.endLine;
const lineEl = this.$.diffBuilder.getLineElByNumber(lineNum, side);
this._isValidElForComment(el).then(valid => {
this._isValidElForComment(lineEl).then(valid => {
if (!valid) { return; }
this._createComment(lineEl, lineNum, side, range);
@ -288,6 +298,12 @@
});
},
/**
* @param {!Object} lineEl
* @param {number=} opt_lineNum
* @param {string=} opt_side
* @param {!Object=} opt_range
*/
_createComment(lineEl, opt_lineNum, opt_side, opt_range) {
const contentText = this.$.diffBuilder.getContentByLineEl(lineEl);
const contentEl = contentText.parentElement;
@ -309,14 +325,21 @@
return contentEl.querySelector('gr-diff-comment-thread-group');
},
/**
* @param {!Object} contentEl
* @param {number} patchNum
* @param {string} commentSide
* @param {boolean} isOnParent
* @param {!Object=} opt_range
*/
_getOrCreateThreadAtLineRange(contentEl, patchNum, commentSide,
isOnParent, range) {
const rangeToCheck = range ?
isOnParent, opt_range) {
const rangeToCheck = opt_range ?
'range-' +
range.startLine + '-' +
range.startChar + '-' +
range.endLine + '-' +
range.endChar + '-' +
opt_range.startLine + '-' +
opt_range.startChar + '-' +
opt_range.endLine + '-' +
opt_range.endChar + '-' +
commentSide : 'line-' + commentSide;
// Check if thread group exists.
@ -338,6 +361,7 @@
return threadEl;
},
/** @return {number} */
_getPatchNumByLineAndContent(lineEl, contentEl) {
let patchNum = this.patchRange.patchNum;
if ((lineEl.classList.contains(DiffSide.LEFT) ||
@ -348,6 +372,7 @@
return patchNum;
},
/** @return {boolean} */
_getIsParentCommentByLineAndContent(lineEl, contentEl) {
let isOnParent = false;
if ((lineEl.classList.contains(DiffSide.LEFT) ||
@ -358,6 +383,7 @@
return isOnParent;
},
/** @return {string} */
_getCommentSideByLineAndContent(lineEl, contentEl) {
let side = 'right';
if (lineEl.classList.contains(DiffSide.LEFT) ||
@ -374,7 +400,7 @@
_handleCommentDiscard(e) {
const comment = e.detail.comment;
this._removeComment(comment, e.detail.patchNum);
this._removeComment(comment);
},
_removeComment(comment) {
@ -389,6 +415,12 @@
this.set(['comments', side, idx], comment);
},
/**
* Closure annotation for Polymer.prototype.push is off. Submitted PR:
* https://github.com/Polymer/polymer/pull/4776
* but for not supressing annotations.
*
* @suppress {checkTypes} */
_handleCommentUpdate(e) {
const comment = e.detail.comment;
const side = e.detail.comment.__commentSide;
@ -413,6 +445,7 @@
}
},
/** @return {number} */
_findCommentIndex(comment, side) {
if (!comment.id || !this.comments[side]) {
return -1;
@ -422,6 +455,7 @@
});
},
/** @return {number} */
_findDraftIndex(comment, side) {
if (!comment.__draftID || !this.comments[side]) {
return -1;
@ -517,6 +551,7 @@
this.fire('page-error', {response});
},
/** @return {!Promise<!Object>} */
_getDiff() {
return this.$.restAPI.getDiff(
this.changeNum,
@ -532,10 +567,12 @@
});
},
/** @return {!Promise} */
_getLoggedIn() {
return this.$.restAPI.getLoggedIn();
},
/** @return {boolean} */
_computeIsImageDiff() {
if (!this._diff) { return false; }
@ -547,6 +584,7 @@
return this._diff.binary && (isA || isB);
},
/** @return {!Promise} */
_loadDiffAssets() {
if (this.isImageDiff) {
return this._getImages().then(images => {
@ -560,6 +598,7 @@
}
},
/** @return {!Promise} */
_getImages() {
return this.$.restAPI.getImagesForDiff(this.changeNum, this._diff,
this.patchRange);
@ -572,6 +611,7 @@
}
},
/** @return {!Array} */
_computeDiffHeaderItems(diffInfoRecord) {
const diffInfo = diffInfoRecord.base;
if (!diffInfo || !diffInfo.diff_header || diffInfo.binary) { return []; }
@ -583,6 +623,7 @@
});
},
/** @return {boolean} */
_computeDiffHeaderHidden(items) {
return items.length === 0;
},
@ -591,7 +632,7 @@
* The number of lines in the diff. For delta chunks that are different
* sizes on the left and the right, the longer side is used.
* @param {!Object} diff
* @return {Number}
* @return {number}
*/
_diffLength(diff) {
return diff.content.reduce((sum, sec) => {
@ -616,6 +657,7 @@
this._renderDiffTable();
},
/** @return {string} */
_computeWarningClass(showWarning) {
return showWarning ? 'warn' : '';
},

@ -23,6 +23,7 @@
properties: {
availablePatches: Array,
changeNum: String,
/** @type {{ meta_a: !Array, meta_b: !Array}} */
filesWeblinks: Object,
path: String,
patchRange: {

@ -43,9 +43,9 @@
/**
* Layer method to add annotations to a line.
* @param {HTMLElement} el The DIV.contentText element to apply the
* @param {!HTMLElement} el The DIV.contentText element to apply the
* annotation to.
* @param {GrDiffLine} line The line object.
* @param {!Object} line The line object. (GrDiffLine)
*/
annotate(el, line) {
let ranges = [];
@ -79,9 +79,9 @@
/**
* Notify Layer listeners of changes to annotations.
* @param {Number} start The line where the update starts.
* @param {Number} end The line where the update ends.
* @param {String} side The side of the update. ('left' or 'right')
* @param {number} start The line where the update starts.
* @param {number} end The line where the update ends.
* @param {string} side The side of the update. ('left' or 'right')
*/
_notifyUpdateRange(start, end, side) {
for (const listener of this._listeners) {
@ -133,8 +133,9 @@
* Take a list of comments and return a sparse list mapping line numbers to
* partial ranges. Uses an end-character-index of -1 to indicate the end of
* the line.
* @param {Array<Object>} commentList The list of comments.
* @return {Object} The sparse list.
* @param {?} commentList The list of comments.
* Getting this param to match closure requirements caused problems.
* @return {!Object} The sparse list.
*/
_computeCommentMap(commentList) {
const result = {};

@ -114,6 +114,7 @@
type: Array,
value() { return []; },
},
/** @type {?number} */
_processHandle: Number,
_hljs: Object,
},
@ -126,7 +127,7 @@
* Annotation layer method to add syntax annotations to the given element
* for the given line.
* @param {!HTMLElement} el
* @param {!GrDiffLine} line
* @param {!Object} line (GrDiffLine)
*/
annotate(el, line) {
if (!this.enabled) { return; }

@ -31,6 +31,9 @@
*/
properties: {
/**
* @type {{ query: string, view: string }}
*/
params: Object,
keyEventTarget: {
type: Object,
@ -41,6 +44,9 @@
type: Object,
observer: '_accountChanged',
},
/**
* @type {{ plugin: Object }}
*/
_serverConfig: Object,
_version: String,
_showChangeListView: Boolean,
@ -50,7 +56,9 @@
_showSettingsView: Boolean,
_showAdminView: Boolean,
_showCLAView: Boolean,
/** @type {?} */
_viewState: Object,
/** @type {?} */
_lastError: Object,
_lastSearchPage: String,
_path: String,

@ -41,6 +41,12 @@
this._importHtmlPlugins(htmlPlugins);
},
/**
* @suppress {checkTypes}
* States that it expects no more than 3 parameters, but that's not true.
* @todo (beckysiegel) check Polymer annotations and submit change.
*/
_importHtmlPlugins(plugins) {
for (const url of plugins) {
this.importHref(

@ -51,6 +51,7 @@
type: Boolean,
value: false,
},
/** @type {?} */
_account: Object,
_serverConfig: Object,
},

@ -29,6 +29,7 @@
type: Array,
value() { return []; },
},
/** @type {?string} */
_newPreferred: {
type: String,
value: null,
@ -61,7 +62,7 @@
},
_handleDeleteButton(e) {
const index = parseInt(e.target.getAttribute('data-index'));
const index = parseInt(e.target.getAttribute('data-index'), 10);
const email = this._emails[index];
this.push('_emailsToRemove', email);
this.splice('_emails', index, 1);

@ -50,7 +50,7 @@
},
_generatedPasswordOverlayClosed() {
this._generatedPassword = null;
this._generatedPassword = '';
},
});
})();

@ -30,6 +30,7 @@
*/
properties: {
/** @type {?} */
_account: Object,
_saving: Boolean,
},

@ -56,8 +56,10 @@
},
_accountNameMutable: Boolean,
_accountInfoChanged: Boolean,
/** @type {?} */
_diffPrefs: Object,
_changeTableColumnsNotDisplayed: Array,
/** @type {?} */
_localPrefs: {
type: Object,
value() { return {}; },
@ -107,8 +109,11 @@
type: String,
value: null,
},
/** @type {?} */
_serverConfig: Object,
/** @type {?string} */
_docsBaseUrl: String,
_emailsChanged: Boolean,
/**
* For testing purposes.

@ -24,6 +24,7 @@
notify: true,
},
_keys: Array,
/** @type {?} */
_keyToView: Object,
_newKey: {
type: String,

@ -18,6 +18,9 @@
is: 'gr-account-label',
properties: {
/**
* @type {{ name: string, status: string }}
*/
account: Object,
avatarImageSize: {
type: Number,

@ -102,13 +102,13 @@
}
},
cursorDown(e) {
cursorDown() {
if (!this.hidden) {
this.$.cursor.next();
}
},
cursorUp(e) {
cursorUp() {
if (!this.hidden) {
this.$.cursor.previous();
}

@ -48,7 +48,7 @@
* suggestion entry. The "value" property will be emitted if that
* suggestion is selected.
*
* @type {function(String): Promise<Array<Object>>}
* @type {function(string): Promise<?>}
*/
query: {
type: Function,
@ -95,7 +95,7 @@
value: false,
},
value: Object,
value: String,
/**
* Multi mode appends autocompleted entries to the value.
@ -115,6 +115,7 @@
value: false,
},
/** @type {?} */
_suggestions: {
type: Array,
value() { return []; },
@ -170,7 +171,7 @@
/**
* Set the text of the input without triggering the suggestion dropdown.
* @param {String} text The new text for the input.
* @param {string} text The new text for the input.
*/
setText(text) {
this._disableSuggestions = true;
@ -270,6 +271,9 @@
}
},
/**
* @param {boolean=} opt_tabComplete
*/
_handleInputCommit(opt_tabComplete) {
this._selected = this.$.suggestions.getCursorTarget();
this._commit(opt_tabComplete);
@ -308,11 +312,11 @@
/**
* Commits the suggestion, optionally firing the commit event.
*
* @param {Boolean} silent Allows for silent committing of an autocomplete
* suggestion in order to handle cases like tab-to-complete without
* firing the commit event.
* @param {boolean=} opt_silent Allows for silent committing of an
* autocomplete suggestion in order to handle cases like tab-to-complete
* without firing the commit event.
*/
_commit(silent) {
_commit(opt_silent) {
// Allow values that are not in suggestion list iff suggestions are empty.
if (this._suggestions.length > 0) {
this._updateValue(this._selected, this._suggestions);
@ -334,7 +338,7 @@
}
this._suggestions = [];
if (!silent) {
if (!opt_silent) {
this.fire('commit', {value});
}
},

@ -18,6 +18,7 @@
is: 'gr-change-star',
properties: {
/** @type {?} */
change: {
type: Object,
notify: true,

@ -30,6 +30,9 @@
},
observer: '_updateIndex',
},
/**
* @type (?Object)
*/
target: {
type: Object,
notify: true,
@ -37,6 +40,7 @@
},
/**
* The height of content intended to be included with the target.
* @type (?number)
*/
_targetHeight: Number,
@ -61,6 +65,8 @@
* The scroll behavior for the cursor. Values are 'never' and
* 'keep-visible'. 'keep-visible' will only scroll if the cursor is beyond
* the viewport.
* TODO (beckysiegel) figure out why it can be undefined
* @type (string|undefined)
*/
scrollBehavior: {
type: String,
@ -90,8 +96,8 @@
/**
* Set the cursor to an arbitrary element.
* @param {DOMElement} element
* @param {boolean} opt_noScroll prevent any potential scrolling in response
* @param {!HTMLElement} element
* @param {boolean=} opt_noScroll prevent any potential scrolling in response
* setting the cursor.
*/
setCursor(element, opt_noScroll) {
@ -137,11 +143,11 @@
/**
* Move the cursor forward or backward by delta. Noop if moving past either
* end of the stop list.
* @param {Number} delta either -1 or 1.
* @param {Function} opt_condition Optional stop condition. If a condition
* @param {number} delta either -1 or 1.
* @param {!Function=} opt_condition Optional stop condition. If a condition
* is passed the cursor will continue to move in the specified direction
* until the condition is met.
* @param {Function} opt_getTargetHeight Optional function to calculate the
* @param {!Function=} opt_getTargetHeight Optional function to calculate the
* height of the target's 'section'. The height of the target itself is
* sometimes different, used by the diff cursor.
* @private
@ -191,9 +197,9 @@
/**
* Get the next stop index indicated by the delta direction.
* @param {Number} delta either -1 or 1.
* @param {Function} opt_condition Optional stop condition.
* @return {Number} the new index.
* @param {number} delta either -1 or 1.
* @param {!Function=} opt_condition Optional stop condition.
* @return {number} the new index.
* @private
*/
_getNextindex(delta, opt_condition) {
@ -239,7 +245,7 @@
/**
* Calculate where the element is relative to the window.
* @param {object} target Target to scroll to.
* @param {!Object} target Target to scroll to.
* @return {number} Distance to top of the target.
*/
_getTop(target) {

@ -23,6 +23,7 @@
value: false,
observer: '_loggedInChanged',
},
schemes: Array,
selectedScheme: {
type: String,
notify: true,

@ -96,6 +96,11 @@
this._inputText = this.value;
},
/**
* @suppress {checkTypes}
* Closure doesn't think 'e' is an Event.
* TODO(beckysiegel) figure out why.
*/
_handleEnter(e) {
e = this.getKeyboardEvent(e);
const target = Polymer.dom(e).rootTarget;
@ -105,6 +110,11 @@
}
},
/**
* @suppress {checkTypes}
* Closure doesn't think 'e' is an Event.
* TODO(beckysiegel) figure out why.
*/
_handleEsc(e) {
e = this.getKeyboardEvent(e);
const target = Polymer.dom(e).rootTarget;

@ -171,7 +171,9 @@
if (inParagraph) {
// Add the finished paragraph block to the result.
inParagraph = false;
out.push(block);
if (block !== null) {
out.push(block);
}
}
inList = true;
block = {type: 'list', items: []};
@ -193,7 +195,7 @@
}
block.items.push(line);
}
if (block != null) {
if (block !== null) {
out.push(block);
}
},
@ -223,12 +225,16 @@
p.startsWith('- ') || p.startsWith('* ');
},
_makeLinkedText(content, isPre) {
/**
* @param {string} content
* @param {boolean=} opt_isPre
*/
_makeLinkedText(content, opt_isPre) {
const text = document.createElement('gr-linked-text');
text.config = this.config;
text.content = content;
text.pre = true;
if (isPre) {
if (opt_isPre) {
text.classList.add('pre');
}
return text;

@ -1698,7 +1698,7 @@
/**
* Alias for _changeBaseURL.then(send).
* @TODO(beckysiegel) clean up comments
* @todo(beckysiegel) clean up comments
* @param {string|number} changeNum
* @param {string} method
* @param {?string|number} patchNum gets passed as null.
@ -1720,7 +1720,7 @@
/**
* Alias for _changeBaseURL.then(fetchJSON).
* @TODO(beckysiegel) clean up comments
* @todo(beckysiegel) clean up comments
* @param {string|number} changeNum
* @param {string} endpoint
* @param {?string|number=} opt_patchNum gets passed as null.

@ -25,6 +25,7 @@
properties: {
_lastCleanup: Number,
/** @type {?Storage} */
_storage: {
type: Object,
value() {

@ -82,6 +82,7 @@
type: Boolean,
value: false,
},
/** @type(?number) */
_colonIndex: Number,
_currentSearchString: {
type: String,
@ -193,7 +194,7 @@
},
_getText(value) {
return this.text.substr(0, this._colonIndex) +
return this.text.substr(0, this._colonIndex || 0) +
value + this.text.substr(this.$.textarea.selectionStart) + ' ';
},
@ -272,7 +273,7 @@
this._currentSearchString.length + this._colonIndex + 1 ||
this._currentSearchString === ' ' ||
this._currentSearchString === '\n' ||
!e.detail.value[this._colonIndex] === ':' ||
!(e.detail.value[this._colonIndex] === ':') ||
!this._suggestions.length) {
this._resetEmojiDropdown();
// Otherwise open the dropdown and set the position to be just below the

@ -47,7 +47,7 @@
* Example
* // returns 'text.html'
* util.truncatePath.('text.html');
* @return {String} Returns the truncated value of a URL.
* @return {string} Returns the truncated value of a URL.
*/
util.truncatePath = function(path) {
const pathPieces = path.split('/');