 cd6efc34da
			
		
	
	cd6efc34da
	
	
	
		
			
			Leads to a "too many template parameter" compile error. Change-Id: I2d7791f16467e148c2dcf9ef1864891f7ad1c32f
		
			
				
	
	
		
			205 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			205 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * @license
 | |
|  * Copyright (C) 2016 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  * http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| (function() {
 | |
|   'use strict';
 | |
| 
 | |
|   const HOVER_PATH_PATTERN = /^comments\.(left|right)\.\#(\d+)\.__hovering$/;
 | |
|   const SPLICE_PATH_PATTERN = /^comments\.(left|right)\.splices$/;
 | |
| 
 | |
|   const RANGE_HIGHLIGHT = 'range';
 | |
|   const HOVER_HIGHLIGHT = 'rangeHighlight';
 | |
| 
 | |
|   const NORMALIZE_RANGE_EVENT = 'normalize-range';
 | |
| 
 | |
|   Polymer({
 | |
|     is: 'gr-ranged-comment-layer',
 | |
| 
 | |
|     properties: {
 | |
|       comments: Object,
 | |
|       _listeners: {
 | |
|         type: Array,
 | |
|         value() { return []; },
 | |
|       },
 | |
|       _commentMap: {
 | |
|         type: Object,
 | |
|         value() { return {left: [], right: []}; },
 | |
|       },
 | |
|     },
 | |
| 
 | |
|     observers: [
 | |
|       '_handleCommentChange(comments.*)',
 | |
|     ],
 | |
| 
 | |
|     /**
 | |
|      * Layer method to add annotations to a line.
 | |
|      * @param {!HTMLElement} el The DIV.contentText element to apply the
 | |
|      *     annotation to.
 | |
|      * @param {!Object} line The line object. (GrDiffLine)
 | |
|      */
 | |
|     annotate(el, line) {
 | |
|       let ranges = [];
 | |
|       if (line.type === GrDiffLine.Type.REMOVE || (
 | |
|           line.type === GrDiffLine.Type.BOTH &&
 | |
|           el.getAttribute('data-side') !== 'right')) {
 | |
|         ranges = ranges.concat(this._getRangesForLine(line, 'left'));
 | |
|       }
 | |
|       if (line.type === GrDiffLine.Type.ADD || (
 | |
|           line.type === GrDiffLine.Type.BOTH &&
 | |
|           el.getAttribute('data-side') !== 'left')) {
 | |
|         ranges = ranges.concat(this._getRangesForLine(line, 'right'));
 | |
|       }
 | |
| 
 | |
|       for (const range of ranges) {
 | |
|         GrAnnotation.annotateElement(el, range.start,
 | |
|             range.end - range.start,
 | |
|             range.hovering ? HOVER_HIGHLIGHT : RANGE_HIGHLIGHT);
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     /**
 | |
|      * Register a listener for layer updates.
 | |
|      * @param {function(number, number, string)} fn The update handler function.
 | |
|      *     Should accept as arguments the line numbers for the start and end of
 | |
|      *     the update and the side as a string.
 | |
|      */
 | |
|     addListener(fn) {
 | |
|       this._listeners.push(fn);
 | |
|     },
 | |
| 
 | |
|     /**
 | |
|      * 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')
 | |
|      */
 | |
|     _notifyUpdateRange(start, end, side) {
 | |
|       for (const listener of this._listeners) {
 | |
|         listener(start, end, side);
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     /**
 | |
|      * Handle change in the comments by updating the comment maps and by
 | |
|      * emitting appropriate update notifications.
 | |
|      * @param {Object} record The change record.
 | |
|      */
 | |
|     _handleCommentChange(record) {
 | |
|       if (!record.path) { return; }
 | |
| 
 | |
|       // If the entire set of comments was changed.
 | |
|       if (record.path === 'comments') {
 | |
|         this._commentMap.left = this._computeCommentMap(this.comments.left);
 | |
|         this._commentMap.right = this._computeCommentMap(this.comments.right);
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       // If the change only changed the `hovering` property of a comment.
 | |
|       let match = record.path.match(HOVER_PATH_PATTERN);
 | |
|       let side;
 | |
| 
 | |
|       if (match) {
 | |
|         side = match[1];
 | |
|         const index = match[2];
 | |
|         const comment = this.comments[side][index];
 | |
|         if (comment && comment.range) {
 | |
|           this._commentMap[side] = this._computeCommentMap(this.comments[side]);
 | |
|           this._notifyUpdateRange(
 | |
|               comment.range.start_line, comment.range.end_line, side);
 | |
|         }
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       // If comments were spliced in or out.
 | |
|       match = record.path.match(SPLICE_PATH_PATTERN);
 | |
|       if (match) {
 | |
|         side = match[1];
 | |
|         this._commentMap[side] = this._computeCommentMap(this.comments[side]);
 | |
|         this._handleCommentSplice(record.value, side);
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     /**
 | |
|      * 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 {?} commentList The list of comments.
 | |
|      *    Getting this param to match closure requirements caused problems.
 | |
|      * @return {!Object} The sparse list.
 | |
|      */
 | |
|     _computeCommentMap(commentList) {
 | |
|       const result = {};
 | |
|       for (const comment of commentList) {
 | |
|         if (!comment.range) { continue; }
 | |
|         const range = comment.range;
 | |
|         for (let line = range.start_line; line <= range.end_line; line++) {
 | |
|           if (!result[line]) { result[line] = []; }
 | |
|           result[line].push({
 | |
|             comment,
 | |
|             start: line === range.start_line ? range.start_character : 0,
 | |
|             end: line === range.end_line ? range.end_character : -1,
 | |
|           });
 | |
|         }
 | |
|       }
 | |
|       return result;
 | |
|     },
 | |
| 
 | |
|     /**
 | |
|      * Translate a splice record into range update notifications.
 | |
|      */
 | |
|     _handleCommentSplice(record, side) {
 | |
|       if (!record || !record.indexSplices) { return; }
 | |
| 
 | |
|       for (const splice of record.indexSplices) {
 | |
|         const ranges = splice.removed.length ?
 | |
|             splice.removed.map(c => { return c.range; }) :
 | |
|             [splice.object[splice.index].range];
 | |
|         for (const range of ranges) {
 | |
|           if (!range) { continue; }
 | |
|           this._notifyUpdateRange(range.start_line, range.end_line, side);
 | |
|         }
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     _getRangesForLine(line, side) {
 | |
|       const lineNum = side === 'left' ? line.beforeNumber : line.afterNumber;
 | |
|       const ranges = this.get(['_commentMap', side, lineNum]) || [];
 | |
|       return ranges
 | |
|           .map(range => {
 | |
|             range = {
 | |
|               start: range.start,
 | |
|               end: range.end === -1 ? line.text.length : range.end,
 | |
|               hovering: !!range.comment.__hovering,
 | |
|             };
 | |
| 
 | |
|             // Normalize invalid ranges where the start is after the end but the
 | |
|             // start still makes sense. Set the end to the end of the line.
 | |
|             // @see Issue 5744
 | |
|             if (range.start >= range.end && range.start < line.text.length) {
 | |
|               range.end = line.text.length;
 | |
|               this.$.reporting.reportInteraction(NORMALIZE_RANGE_EVENT,
 | |
|                   'Modified invalid comment range on l.' + lineNum +
 | |
|                   ' of the ' + side + ' side');
 | |
|             }
 | |
| 
 | |
|             return range;
 | |
|           })
 | |
|           // Sort the ranges so that hovering highlights are on top.
 | |
|           .sort((a, b) => a.hovering && !b.hovering ? 1 : 0);
 | |
|     },
 | |
|   });
 | |
| })();
 |