Merge "Add ability to add annotation layers from plugins"
This commit is contained in:
commit
617adb42a6
@ -36,6 +36,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>
|
||||
@ -90,6 +91,9 @@ limitations under the License.
|
||||
|
||||
properties: {
|
||||
diff: Object,
|
||||
diffPath: String,
|
||||
changeNum: String,
|
||||
patchNum: String,
|
||||
viewMode: String,
|
||||
comments: Object,
|
||||
isImageDiff: Boolean,
|
||||
@ -113,7 +117,7 @@ limitations under the License.
|
||||
|
||||
attached() {
|
||||
// Setup annotation layers.
|
||||
this._layers = [
|
||||
const layers = [
|
||||
this._createTrailingWhitespaceLayer(),
|
||||
this.$.syntaxLayer,
|
||||
this._createIntralineLayer(),
|
||||
@ -121,6 +125,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();
|
||||
});
|
||||
|
@ -657,6 +657,33 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
|
||||
suite('layers from plugins', () => {
|
||||
let element;
|
||||
let initialLayersCount;
|
||||
|
||||
setup(() => {
|
||||
element = fixture('basic');
|
||||
element._showTrailingWhitespace = true;
|
||||
initialLayersCount = element._layers.length;
|
||||
});
|
||||
|
||||
test('no plugin layers', () => {
|
||||
const getDiffLayersStub = sinon.stub(element.$.jsAPI, 'getDiffLayers')
|
||||
.returns([]);
|
||||
element.attached();
|
||||
assert.isTrue(getDiffLayersStub.called);
|
||||
assert.equal(element._layers.length, initialLayersCount);
|
||||
});
|
||||
|
||||
test('with plugin layers', () => {
|
||||
const getDiffLayersStub = sinon.stub(element.$.jsAPI, 'getDiffLayers')
|
||||
.returns([{}, {}]);
|
||||
element.attached();
|
||||
assert.isTrue(getDiffLayersStub.called);
|
||||
assert.equal(element._layers.length, initialLayersCount+2);
|
||||
});
|
||||
});
|
||||
|
||||
suite('trailing whitespace', () => {
|
||||
let element;
|
||||
let layer;
|
||||
|
@ -266,6 +266,8 @@ limitations under the License.
|
||||
project-name="[[projectName]]"
|
||||
diff="[[_diff]]"
|
||||
diff-path="[[path]]"
|
||||
change-num="[[changeNum]]"
|
||||
patch-num="[[patchRange.patchNum]]"
|
||||
view-mode="[[viewMode]]"
|
||||
line-wrapping="[[lineWrapping]]"
|
||||
is-image-diff="[[isImageDiff]]"
|
||||
|
@ -52,6 +52,7 @@
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
/** @type {?} */
|
||||
patchRange: Object,
|
||||
path: String,
|
||||
prefs: {
|
||||
|
@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2017 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(window) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Used to create a context for GrAnnotationActionsInterface.
|
||||
* @param {HTMLElement} el The DIV.contentText element to apply the
|
||||
* annotation to using annotateRange.
|
||||
* @param {GrDiffLine} line The line object.
|
||||
* @param {String} path The file path (eg: /COMMIT_MSG').
|
||||
* @param {String} changeNum The Gerrit change number.
|
||||
* @param {String} patchNum The Gerrit patch number.
|
||||
*/
|
||||
function GrAnnotationActionsContext(el, line, path, changeNum, patchNum) {
|
||||
this._el = el;
|
||||
|
||||
this.line = line;
|
||||
this.path = path;
|
||||
this.changeNum = parseInt(changeNum);
|
||||
this.patchNum = parseInt(patchNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add annotations to a line.
|
||||
* @param {Number} start The line number where the update starts.
|
||||
* @param {Number} end The line number where the update ends.
|
||||
* @param {String} cssClass The name of a CSS class created using Gerrit.css.
|
||||
* @param {String} side The side of the update. ('left' or 'right')
|
||||
*/
|
||||
GrAnnotationActionsContext.prototype.annotateRange = function(
|
||||
start, end, cssClass, side) {
|
||||
if (this._el.getAttribute('data-side') == side) {
|
||||
GrAnnotation.annotateElement(this._el, start, end, cssClass);
|
||||
}
|
||||
};
|
||||
|
||||
window.GrAnnotationActionsContext = GrAnnotationActionsContext;
|
||||
})(window);
|
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-annotation-actions-context</title>
|
||||
|
||||
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../diff/gr-diff-highlight/gr-annotation.js"></script>
|
||||
|
||||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="gr-js-api-interface.html"/>
|
||||
|
||||
<script>void(0);</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-annotation-actions-context tests', () => {
|
||||
let instance;
|
||||
let sandbox;
|
||||
let el;
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
const str = 'lorem ipsum blah blah';
|
||||
const line = {text: str};
|
||||
el = document.createElement('div');
|
||||
el.textContent = str;
|
||||
el.setAttribute('data-side', 'right');
|
||||
instance = new GrAnnotationActionsContext(
|
||||
el, line, 'dummy/path', '123', '1');
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('test annotateRange', () => {
|
||||
annotateElementSpy = sandbox.spy(GrAnnotation, 'annotateElement');
|
||||
const start = 0;
|
||||
const end = 100;
|
||||
const cssClass = Gerrit.css('background-color: #000000');
|
||||
|
||||
// Assert annotateElement is not called when side is different.
|
||||
instance.annotateRange(start, end, cssClass, 'left');
|
||||
assert.equal(annotateElementSpy.callCount, 0);
|
||||
|
||||
// Assert annotateElement is called once when side is the same.
|
||||
instance.annotateRange(start, end, cssClass, 'right');
|
||||
assert.equal(annotateElementSpy.callCount, 1);
|
||||
const args = annotateElementSpy.getCalls()[0].args;
|
||||
assert.equal(args[0], el);
|
||||
assert.equal(args[1], start);
|
||||
assert.equal(args[2], end);
|
||||
assert.equal(args[3], cssClass);
|
||||
});
|
||||
});
|
||||
</script>
|
@ -0,0 +1,143 @@
|
||||
// Copyright (C) 2017 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(window) {
|
||||
'use strict';
|
||||
|
||||
function GrAnnotationActionsInterface(plugin) {
|
||||
this.plugin = plugin;
|
||||
// Return this instance when there is an annotatediff event.
|
||||
plugin.on('annotatediff', this);
|
||||
|
||||
// Collect all annotation layers instantiated by getLayer. Will be used when
|
||||
// notifying their listeners in the notify function.
|
||||
this._annotationLayers = [];
|
||||
|
||||
// Default impl is a no-op.
|
||||
this._addLayerFunc = annotationActionsContext => {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a function to call to apply annotations. Plugins should use
|
||||
* GrAnnotationActionsContext.annotateRange to apply a CSS class to a range
|
||||
* within a line.
|
||||
* @param {Function<GrAnnotationActionsContext>} addLayerFunc The function
|
||||
* that will be called when the AnnotationLayer is ready to annotate.
|
||||
*/
|
||||
GrAnnotationActionsInterface.prototype.addLayer = function(addLayerFunc) {
|
||||
this._addLayerFunc = addLayerFunc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* The specified function will be called with a notify function for the plugin
|
||||
* to call when it has all required data for annotation. Optional.
|
||||
* @param {Function<Function<String, Number, Number, String>>} notifyFunc See
|
||||
* doc of the notify function below to see what it does.
|
||||
*/
|
||||
GrAnnotationActionsInterface.prototype.addNotifier = function(notifyFunc) {
|
||||
// Register the notify function with the plugin's function.
|
||||
notifyFunc(this.notify.bind(this));
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* The notify function will call the listeners of all required annotation
|
||||
* layers. Intended to be called by the plugin when all required data for
|
||||
* annotation is available.
|
||||
* @param {String} path The file path whose listeners should be notified.
|
||||
* @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').
|
||||
*/
|
||||
GrAnnotationActionsInterface.prototype.notify = function(
|
||||
path, startRange, endRange, side) {
|
||||
for (const annotationLayer of this._annotationLayers) {
|
||||
// Notify only the annotation layer that is associated with the specified
|
||||
// path.
|
||||
if (annotationLayer._path === path) {
|
||||
annotationLayer.notifyListeners(startRange, endRange, side);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be called to register annotation layers by the framework. Not
|
||||
* intended to be called by plugins.
|
||||
* @param {String} path The file path (eg: /COMMIT_MSG').
|
||||
* @param {String} changeNum The Gerrit change number.
|
||||
* @param {String} patchNum The Gerrit patch number.
|
||||
*/
|
||||
GrAnnotationActionsInterface.prototype.getLayer = function(
|
||||
path, changeNum, patchNum) {
|
||||
const annotationLayer = new AnnotationLayer(path, changeNum, patchNum,
|
||||
this._addLayerFunc);
|
||||
this._annotationLayers.push(annotationLayer);
|
||||
return annotationLayer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used to create an instance of the Annotation Layer interface.
|
||||
* @param {String} path The file path (eg: /COMMIT_MSG').
|
||||
* @param {String} changeNum The Gerrit change number.
|
||||
* @param {String} patchNum The Gerrit patch number.
|
||||
* @param {Function<GrAnnotationActionsContext>} addLayerFunc The function
|
||||
* that will be called when the AnnotationLayer is ready to annotate.
|
||||
*/
|
||||
function AnnotationLayer(path, changeNum, patchNum, addLayerFunc) {
|
||||
this._path = path;
|
||||
this._changeNum = changeNum;
|
||||
this._patchNum = patchNum;
|
||||
this._addLayerFunc = addLayerFunc;
|
||||
|
||||
this._listeners = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
AnnotationLayer.prototype.addListener = function(fn) {
|
||||
this._listeners.push(fn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Layer method to add annotations to a line.
|
||||
* @param {HTMLElement} el The DIV.contentText element to apply the
|
||||
* annotation to.
|
||||
* @param {GrDiffLine} line The line object.
|
||||
*/
|
||||
AnnotationLayer.prototype.annotate = function(el, line) {
|
||||
const annotationActionsContext = new GrAnnotationActionsContext(
|
||||
el, line, this._path, this._changeNum, this._patchNum);
|
||||
this._addLayerFunc(annotationActionsContext);
|
||||
};
|
||||
|
||||
/**
|
||||
* 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')
|
||||
*/
|
||||
AnnotationLayer.prototype.notifyListeners = function(
|
||||
startRange, endRange, side) {
|
||||
for (const listener of this._listeners) {
|
||||
listener(startRange, endRange, side);
|
||||
}
|
||||
};
|
||||
|
||||
window.GrAnnotationActionsInterface = GrAnnotationActionsInterface;
|
||||
})(window);
|
@ -0,0 +1,133 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-annotation-actions-js-api-js-api</title>
|
||||
|
||||
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||
<link rel="import" href="../../change/gr-change-actions/gr-change-actions.html">
|
||||
|
||||
<script>
|
||||
suite('gr-annotation-actions-js-api tests', () => {
|
||||
let annotationActions;
|
||||
let sandbox;
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
let plugin;
|
||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||
'http://test.com/plugins/testplugin/static/test.js');
|
||||
annotationActions = plugin.annotationApi();
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
annotationActions = null;
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
test('add/get layer', () => {
|
||||
const str = 'lorem ipsum blah blah';
|
||||
const line = {text: str};
|
||||
el = document.createElement('div');
|
||||
el.textContent = str;
|
||||
const changeNum = 1234;
|
||||
const patchNum = 2;
|
||||
let testLayerFuncCalled = false;
|
||||
|
||||
const testLayerFunc = context => {
|
||||
testLayerFuncCalled = true;
|
||||
assert.equal(context.line, line);
|
||||
assert.equal(context.changeNum, changeNum);
|
||||
assert.equal(context.patchNum, 2);
|
||||
};
|
||||
annotationActions.addLayer(testLayerFunc);
|
||||
|
||||
const annotationLayer = annotationActions.getLayer(
|
||||
'/dummy/path', changeNum, patchNum);
|
||||
|
||||
annotationLayer.annotate(el, line);
|
||||
assert.isTrue(testLayerFuncCalled);
|
||||
});
|
||||
|
||||
test('add notifier', () => {
|
||||
const path1 = '/dummy/path1';
|
||||
const path2 = '/dummy/path2';
|
||||
const annotationLayer1 = annotationActions.getLayer(path1, 1, 2);
|
||||
const annotationLayer2 = annotationActions.getLayer(path2, 1, 2);
|
||||
const layer1Spy = sandbox.spy(annotationLayer1, 'notifyListeners');
|
||||
const layer2Spy = sandbox.spy(annotationLayer2, 'notifyListeners');
|
||||
|
||||
let notify;
|
||||
const notifyFunc = n => {
|
||||
notifyFuncCalled = true;
|
||||
notify = n;
|
||||
};
|
||||
annotationActions.addNotifier(notifyFunc);
|
||||
assert.isTrue(notifyFuncCalled);
|
||||
|
||||
// Assert that no layers are invoked with a different path.
|
||||
notify('/dummy/path3', 0, 10, 'right');
|
||||
assert.isFalse(layer1Spy.called);
|
||||
assert.isFalse(layer2Spy.called);
|
||||
|
||||
// Assert that only the 1st layer is invoked with path1.
|
||||
notify(path1, 0, 10, 'right');
|
||||
assert.isTrue(layer1Spy.called);
|
||||
assert.isFalse(layer2Spy.called);
|
||||
|
||||
// Reset spies.
|
||||
layer1Spy.reset();
|
||||
layer2Spy.reset();
|
||||
|
||||
// Assert that only the 2nd layer is invoked with path2.
|
||||
notify(path2, 0, 20, 'left');
|
||||
assert.isFalse(layer1Spy.called);
|
||||
assert.isTrue(layer2Spy.called);
|
||||
});
|
||||
|
||||
test('layer notify listeners', () => {
|
||||
const annotationLayer = annotationActions.getLayer(
|
||||
'/dummy/path', 1, 2);
|
||||
let listenerCalledTimes = 0;
|
||||
const startRange = 10;
|
||||
const endRange = 20;
|
||||
const side = 'right';
|
||||
const listener = (st, end, s) => {
|
||||
listenerCalledTimes++;
|
||||
assert.equal(st, startRange);
|
||||
assert.equal(end, endRange);
|
||||
assert.equal(s, side);
|
||||
};
|
||||
|
||||
// Notify with 0 listeners added.
|
||||
annotationLayer.notifyListeners(startRange, endRange, side);
|
||||
assert.equal(listenerCalledTimes, 0);
|
||||
|
||||
// Add 1 listener.
|
||||
annotationLayer.addListener(listener);
|
||||
annotationLayer.notifyListeners(startRange, endRange, side);
|
||||
assert.equal(listenerCalledTimes, 1);
|
||||
|
||||
// Add 1 more listener. Total 2 listeners.
|
||||
annotationLayer.addListener(listener);
|
||||
annotationLayer.notifyListeners(startRange, endRange, side);
|
||||
assert.equal(listenerCalledTimes, 3);
|
||||
});
|
||||
});
|
||||
</script>
|
@ -26,6 +26,8 @@ limitations under the License.
|
||||
<link rel="import" href="../gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
|
||||
<dom-module id="gr-js-api-interface">
|
||||
<script src="gr-annotation-actions-context.js"></script>
|
||||
<script src="gr-annotation-actions-js-api.js"></script>
|
||||
<script src="gr-change-actions-js-api.js"></script>
|
||||
<script src="gr-change-reply-js-api.js"></script>
|
||||
<script src="gr-js-api-interface.js"></script>
|
||||
|
@ -23,6 +23,7 @@
|
||||
COMMENT: 'comment',
|
||||
REVERT: 'revert',
|
||||
POST_REVERT: 'postrevert',
|
||||
ANNOTATE_DIFF: 'annotatediff',
|
||||
};
|
||||
|
||||
const Element = {
|
||||
@ -178,6 +179,20 @@
|
||||
return revertMsg;
|
||||
},
|
||||
|
||||
getDiffLayers(path, changeNum, patchNum) {
|
||||
const layers = [];
|
||||
for (const annotationApi of
|
||||
this._getEventCallbacks(EventType.ANNOTATE_DIFF)) {
|
||||
try {
|
||||
const layer = annotationApi.getLayer(path, changeNum, patchNum);
|
||||
layers.push(layer);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
return layers;
|
||||
},
|
||||
|
||||
getLabelValuesPostRevert(change) {
|
||||
let labels = {};
|
||||
for (const cb of this._getEventCallbacks(EventType.POST_REVERT)) {
|
||||
|
@ -175,6 +175,10 @@
|
||||
return Gerrit.delete(this.url(url), opt_callback);
|
||||
};
|
||||
|
||||
Plugin.prototype.annotationApi = function() {
|
||||
return new GrAnnotationActionsInterface(this);
|
||||
};
|
||||
|
||||
Plugin.prototype.changeActions = function() {
|
||||
return new GrChangeActionsInterface(this,
|
||||
Plugin._sharedAPIElement.getElement(
|
||||
|
55
polygerrit-ui/app/samples/coverage-plugin.html
Normal file
55
polygerrit-ui/app/samples/coverage-plugin.html
Normal file
@ -0,0 +1,55 @@
|
||||
<dom-module id="coverage-plugin">
|
||||
<script>
|
||||
|
||||
function populateWithDummyData(coverageData) {
|
||||
coverageData['NewFile'] = {
|
||||
linesMissingCoverage: [1, 2, 3],
|
||||
totalLines: 5,
|
||||
changeNum: 94,
|
||||
patchNum: 2,
|
||||
};
|
||||
coverageData['/COMMIT_MSG'] = {
|
||||
linesMissingCoverage: [3, 4, 7, 14],
|
||||
totalLines: 14,
|
||||
changeNum: 94,
|
||||
patchNum: 2,
|
||||
};
|
||||
coverageData['DEPS'] = {
|
||||
linesMissingCoverage: [3, 4, 7, 14],
|
||||
totalLines: 16,
|
||||
changeNum: 77001,
|
||||
patchNum: 1,
|
||||
};
|
||||
}
|
||||
|
||||
Gerrit.install(plugin => {
|
||||
const coverageData = {};
|
||||
plugin.annotationApi().addNotifier(notifyFunc => {
|
||||
new Promise(resolve => setTimeout(resolve, 3000)).then(
|
||||
() => {
|
||||
populateWithDummyData(coverageData);
|
||||
Object.keys(coverageData).forEach(file => {
|
||||
notifyFunc(file, 0, coverageData[file].totalLines, 'right');
|
||||
});
|
||||
});
|
||||
}).addLayer(context => {
|
||||
if (Object.keys(coverageData).length === 0) {
|
||||
// Coverage data is not ready yet.
|
||||
return;
|
||||
}
|
||||
const path = context.path;
|
||||
const line = context.line;
|
||||
// Highlight lines missing coverage with this background color.
|
||||
const cssClass = Gerrit.css('background-color: #EF9B9B');
|
||||
if (coverageData[path] &&
|
||||
coverageData[path].changeNum === context.changeNum &&
|
||||
coverageData[path].patchNum === context.patchNum) {
|
||||
const linesMissingCoverage = coverageData[path].linesMissingCoverage;
|
||||
if (linesMissingCoverage.includes(line.afterNumber)) {
|
||||
context.annotateRange(0, line.text.length, cssClass, 'right');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
Loading…
Reference in New Issue
Block a user