Index: third_party/WebKit/Source/devtools/front_end/coverage/CoverageDecorationManager.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/coverage/CoverageDecorationManager.js b/third_party/WebKit/Source/devtools/front_end/coverage/CoverageDecorationManager.js |
index 351cfa15e0579b86a71a2880889ae0f59f49fbba..4727ff6f2fe834ec0b103eb1ae9cde862d07e89d 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/coverage/CoverageDecorationManager.js |
+++ b/third_party/WebKit/Source/devtools/front_end/coverage/CoverageDecorationManager.js |
@@ -22,6 +22,9 @@ Coverage.CoverageDecorationManager = class { |
this._textByProvider = new Map(); |
/** @type {!Multimap<!Common.ContentProvider, !Workspace.UISourceCode>} */ |
this._uiSourceCodeByContentProvider = new Multimap(); |
+ // TODO(crbug.com/720162): get rid of this, use bindings. |
+ /** @type {!WeakMap<!Workspace.UISourceCode, !Array<!SDK.CSSStyleSheetHeader>>} */ |
+ this._documentUISouceCodeToStylesheets = new WeakMap(); |
for (var uiSourceCode of Workspace.workspace.uiSourceCodes()) |
uiSourceCode.addLineDecoration(0, Coverage.CoverageDecorationManager._decoratorType, this); |
@@ -59,12 +62,12 @@ Coverage.CoverageDecorationManager = class { |
for (var line = 0; line < sourceText.lineCount(); ++line) { |
var lineLength = lineEndings[line] - (line ? lineEndings[line - 1] : 0) - 1; |
if (!lineLength) { |
- result.push(false); |
+ result.push(undefined); |
continue; |
} |
var startLocations = this._rawLocationsForSourceLocation(uiSourceCode, line, 0); |
var endLocations = this._rawLocationsForSourceLocation(uiSourceCode, line, lineLength); |
- var used = false; |
+ var used = undefined; |
for (var startIndex = 0, endIndex = 0; startIndex < startLocations.length; ++startIndex) { |
var start = startLocations[startIndex]; |
while (endIndex < endLocations.length && |
@@ -77,14 +80,14 @@ Coverage.CoverageDecorationManager = class { |
if (!text) |
continue; |
var textValue = text.value(); |
- var startOffset = text.offsetFromPosition(start.line, start.column); |
- var endOffset = text.offsetFromPosition(end.line, end.column); |
+ var startOffset = Math.min(text.offsetFromPosition(start.line, start.column), textValue.length - 1); |
+ var endOffset = Math.min(text.offsetFromPosition(end.line, end.column), textValue.length - 1); |
while (startOffset <= endOffset && /\s/.test(textValue[startOffset])) |
++startOffset; |
while (startOffset <= endOffset && /\s/.test(textValue[endOffset])) |
--endOffset; |
- used = |
- startOffset <= endOffset && this._coverageModel.usageForRange(end.contentProvider, startOffset, endOffset); |
+ if (startOffset <= endOffset) |
+ used = this._coverageModel.usageForRange(end.contentProvider, startOffset, endOffset); |
if (used) |
break; |
} |
@@ -133,20 +136,41 @@ Coverage.CoverageDecorationManager = class { |
if (contentType.hasScripts()) { |
var location = Bindings.debuggerWorkspaceBinding.uiLocationToRawLocation(uiSourceCode, line, column); |
if (location && location.script()) { |
- result.push({ |
- id: `js:${location.scriptId}`, |
- contentProvider: location.script(), |
- line: location.lineNumber, |
- column: location.columnNumber |
- }); |
+ var script = location.script(); |
+ if (script.isInlineScript() && contentType.isDocument()) { |
+ if (comparePositions(script.lineOffset, script.columnOffset, location.lineNumber, location.columnNumber) > |
+ 0 || |
+ comparePositions(script.endLine, script.endColumn, location.lineNumber, location.columnNumber) <= 0) { |
+ location = null; |
+ } else { |
+ location.lineNumber -= script.lineOffset; |
+ if (!location.lineNumber) |
+ location.columnNumber -= script.columnOffset; |
+ } |
+ } |
+ if (location) { |
+ result.push({ |
+ id: `js:${location.scriptId}`, |
+ contentProvider: location.script(), |
+ line: location.lineNumber, |
+ column: location.columnNumber |
+ }); |
+ } |
} |
} |
if (contentType.isStyleSheet() || contentType.isDocument()) { |
- var rawStyleLocations = |
+ var rawStyleLocations = contentType.isDocument() ? |
+ this._documentUILocationToCSSRawLocations(uiSourceCode, line, column) : |
Bindings.cssWorkspaceBinding.uiLocationToRawLocations(new Workspace.UILocation(uiSourceCode, line, column)); |
for (var location of rawStyleLocations) { |
- if (!location.header()) |
+ var header = location.header(); |
+ if (!header) |
continue; |
+ if (header.isInline && contentType.isDocument()) { |
+ location.lineNumber -= header.startLine; |
+ if (!location.lineNumber) |
+ location.columnNumber -= header.startColumn; |
+ } |
result.push({ |
id: `css:${location.styleSheetId}`, |
contentProvider: location.header(), |
@@ -156,9 +180,65 @@ Coverage.CoverageDecorationManager = class { |
} |
} |
result.sort(Coverage.CoverageDecorationManager._compareLocations); |
+ |
+ /** |
+ * @param {number} aLine |
+ * @param {number} aColumn |
+ * @param {number} bLine |
+ * @param {number} bColumn |
+ * @return {number} |
+ */ |
+ function comparePositions(aLine, aColumn, bLine, bColumn) { |
+ return aLine - bLine || aColumn - bColumn; |
+ } |
return result; |
} |
+ /** |
+ * TODO(crbug.com/720162): get rid of this, use bindings. |
+ * |
+ * @param {!Workspace.UISourceCode} uiSourceCode |
+ * @param {number} line |
+ * @param {number} column |
+ * @return {!Array<!SDK.CSSLocation>} |
+ */ |
+ _documentUILocationToCSSRawLocations(uiSourceCode, line, column) { |
+ var stylesheets = this._documentUISouceCodeToStylesheets.get(uiSourceCode); |
+ if (!stylesheets) { |
+ stylesheets = []; |
+ var cssModel = this._coverageModel.target().model(SDK.CSSModel); |
+ if (!cssModel) |
+ return []; |
+ for (var headerId of cssModel.styleSheetIdsForURL(uiSourceCode.url())) { |
+ var header = cssModel.styleSheetHeaderForId(headerId); |
+ if (header) |
+ stylesheets.push(header); |
+ } |
+ stylesheets.sort(stylesheetComparator); |
+ this._documentUISouceCodeToStylesheets.set(uiSourceCode, stylesheets); |
+ } |
+ var endIndex = |
+ stylesheets.upperBound(undefined, (unused, header) => line - header.startLine || column - header.startColumn); |
+ if (!endIndex) |
+ return []; |
+ var locations = []; |
+ var last = stylesheets[endIndex - 1]; |
+ for (var index = endIndex - 1; index >= 0 && stylesheets[index].startLine === last.startLine && |
+ stylesheets[index].startColumn === last.startColumn; |
+ --index) |
+ locations.push(new SDK.CSSLocation(stylesheets[index], line, column)); |
+ |
+ return locations; |
+ /** |
+ * @param {!SDK.CSSStyleSheetHeader} a |
+ * @param {!SDK.CSSStyleSheetHeader} b |
+ * @return {number} |
+ */ |
+ function stylesheetComparator(a, b) { |
+ return a.startLine - b.startLine || a.startColumn - b.startColumn || a.id.localeCompare(b.id); |
+ } |
+ } |
+ |
/** |
* @param {!Coverage.RawLocation} a |
* @param {!Coverage.RawLocation} b |
@@ -189,7 +269,7 @@ Coverage.CoverageView.LineDecorator = class { |
*/ |
decorate(uiSourceCode, textEditor) { |
var decorations = uiSourceCode.decorationsForType(Coverage.CoverageDecorationManager._decoratorType); |
- if (!decorations.size) { |
+ if (!decorations || !decorations.size) { |
textEditor.uninstallGutter(Coverage.CoverageView.LineDecorator._gutterType); |
return; |
} |
@@ -209,6 +289,9 @@ Coverage.CoverageView.LineDecorator = class { |
textEditor.uninstallGutter(gutterType); |
textEditor.installGutter(gutterType, false); |
for (var line = 0; line < lineUsage.length; ++line) { |
+ // Do not decorate the line if we don't have data. |
+ if (typeof lineUsage[line] !== 'boolean') |
+ continue; |
var className = lineUsage[line] ? 'text-editor-coverage-used-marker' : 'text-editor-coverage-unused-marker'; |
textEditor.setGutterDecoration(line, gutterType, createElementWithClass('div', className)); |
} |