Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/components_lazy/CoverageProfile.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/components_lazy/CoverageProfile.js b/third_party/WebKit/Source/devtools/front_end/components_lazy/CoverageProfile.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..86958cf1af6e93c8f8940af7238f0f6d9db357fa |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/devtools/front_end/components_lazy/CoverageProfile.js |
| @@ -0,0 +1,149 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +WebInspector.CoverageProfile = class { |
| + constructor() { |
| + this._updateTimer = null; |
| + this._locationPool = new WebInspector.LiveLocationPool(); |
| + this.reset(); |
| + } |
| + |
| + /** |
| + * @return {!WebInspector.CoverageProfile} |
| + */ |
| + static instance() { |
| + if (!WebInspector.CoverageProfile._instance) |
| + WebInspector.CoverageProfile._instance = new WebInspector.CoverageProfile(); |
| + |
| + return WebInspector.CoverageProfile._instance; |
| + } |
| + |
| + /** |
| + * @param {string} url |
| + * @param {!WebInspector.TextRange} range |
| + */ |
| + appendUnusedRule(url, range) { |
| + if (!url) |
| + return; |
| + |
| + var fileInfo = this._files.get(url); |
| + if (!fileInfo) { |
| + fileInfo = new Set(); |
| + this._files.set(url, fileInfo); |
| + } |
| + fileInfo.add(range); |
| + this._scheduleUpdate(); |
| + } |
| + |
| + reset() { |
| + /** @type {!Map<string, !Set<!WebInspector.TextRange>>} */ |
| + this._files = new Map(); |
|
lushnikov
2016/11/09 00:45:30
this is not a collection of "files". Let's come up
|
| + this._scheduleUpdate(); |
| + } |
| + |
| + _scheduleUpdate() { |
| + if (this._updateTimer) |
| + return; |
| + |
| + this._updateTimer = setTimeout(() => { |
| + this._updateTimer = null; |
| + this._doUpdate(); |
| + }, 0); |
| + } |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _uiSourceCodeChanged(event) { |
| + WebInspector.workspace.uiSourceCodes().forEach( |
| + uiSourceCode => uiSourceCode.removeAllLineDecorations(WebInspector.CoverageProfile.LineDecorator.type)); |
| + } |
| + |
| + _doUpdate() { |
| + this._locationPool.disposeAll(); |
| + WebInspector.workspace.uiSourceCodes().forEach( |
| + uiSourceCode => uiSourceCode.removeAllLineDecorations(WebInspector.CoverageProfile.LineDecorator.type)); |
|
lushnikov
2016/11/09 00:45:30
can we be smarter and avoid traversing the whole w
|
| + |
| + WebInspector.workspace.uiSourceCodes().forEach( |
| + uiSourceCode => uiSourceCode.addEventListener( |
| + WebInspector.UISourceCode.Events.WorkingCopyChanged, this._uiSourceCodeChanged, this)); |
|
lushnikov
2016/11/09 00:45:30
The workignCopyChanged happens for every keypress
|
| + |
| + for (var fileInfo of this._files) { |
|
lushnikov
2016/11/09 00:45:30
let's iterate keys here - this way you'll avoid un
|
| + var url = /** @type {string} */ (fileInfo[0]); |
| + var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(url); |
| + if (!uiSourceCode) |
| + continue; |
| + |
| + var target = |
| + WebInspector.NetworkProject.targetForUISourceCode(uiSourceCode) || WebInspector.targetManager.mainTarget(); |
|
lushnikov
2016/11/09 00:45:30
why do you need mainTarget?
|
| + var debuggerModel = target ? WebInspector.DebuggerModel.fromTarget(target) : null; |
|
lushnikov
2016/11/09 00:45:30
since you're dealing with CSS, you should not talk
|
| + if (!debuggerModel) |
| + continue; |
| + |
| + for (var range of fileInfo[1]) { |
| + for (var line = range.startLine; line <= range.endLine; ++line) { |
| + |
| + var rawLocation = debuggerModel.createRawLocationByURL(url, line, 0); |
|
lushnikov
2016/11/09 00:45:31
this whole code will not work; let's add a test wh
|
| + if (rawLocation) |
| + new WebInspector.CoverageProfile.Presentation(rawLocation, this._locationPool); |
| + else if (uiSourceCode) |
| + uiSourceCode.addLineDecoration(line, WebInspector.CoverageProfile.LineDecorator.type, 0); |
| + } |
| + } |
| + } |
| + } |
| +}; |
| + |
| +WebInspector.CoverageProfile.Presentation = class { |
|
lushnikov
2016/11/09 00:45:30
probably you don't need this - unless it comes han
|
| + /** |
| + * @param {!WebInspector.DebuggerModel.Location} rawLocation |
| + * @param {!WebInspector.LiveLocationPool} locationPool |
| + */ |
| + constructor(rawLocation, locationPool) { |
| + WebInspector.debuggerWorkspaceBinding.createLiveLocation(rawLocation, this.updateLocation.bind(this), locationPool); |
|
lushnikov
2016/11/09 00:45:30
Debugger has nothing to do with styles; use cssWor
|
| + this._uiLocation = null; |
| + } |
| + |
| + /** |
| + * @param {!WebInspector.LiveLocation} liveLocation |
| + */ |
| + updateLocation(liveLocation) { |
| + if (this._uiLocation) |
| + this._uiLocation.uiSourceCode.removeLineDecoration( |
| + this._uiLocation.lineNumber, WebInspector.CoverageProfile.LineDecorator.type); |
| + |
| + this._uiLocation = liveLocation.uiLocation(); |
| + if (this._uiLocation) |
| + this._uiLocation.uiSourceCode.addLineDecoration( |
| + this._uiLocation.lineNumber, WebInspector.CoverageProfile.LineDecorator.type, 0); |
| + } |
| +}; |
| + |
| +/** |
| + * @implements {WebInspector.UISourceCodeFrame.LineDecorator} |
| + */ |
| +WebInspector.CoverageProfile.LineDecorator = class { |
| + /** |
| + * @override |
| + * @param {!WebInspector.UISourceCode} uiSourceCode |
| + * @param {!WebInspector.CodeMirrorTextEditor} textEditor |
| + */ |
| + decorate(uiSourceCode, textEditor) { |
| + var gutterType = 'CodeMirror-gutter-coverage'; |
| + |
| + var decorations = uiSourceCode.lineDecorations(WebInspector.CoverageProfile.LineDecorator.type); |
| + textEditor.uninstallGutter(gutterType); |
| + if (!decorations) |
| + return; |
| + |
| + textEditor.installGutter(gutterType, false); |
| + |
| + for (var decoration of decorations.values()) { |
| + var element = createElementWithClass('div', 'text-editor-line-marker-coverage'); |
| + textEditor.setGutterDecoration(decoration.line(), gutterType, element); |
| + } |
| + } |
| +}; |
| + |
| +WebInspector.CoverageProfile.LineDecorator.type = 'coverage'; |