Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Unified Diff: third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js

Issue 1427653002: DevTools: move ui messages from SourceFrame to UISourceCodeFrame (step1) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebaselined Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
index 60617f396623f94838a257c25e50cad66bf195b3..af503388e301ea172e26a82dde6800621a489d4b 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/UISourceCodeFrame.js
@@ -36,10 +36,13 @@ WebInspector.UISourceCodeFrame = function(uiSourceCode)
this._uiSourceCode = uiSourceCode;
WebInspector.SourceFrame.call(this, this._uiSourceCode);
this.textEditor.setAutocompleteDelegate(new WebInspector.SimpleAutocompleteDelegate());
-
+ this._rowMessageBuckets = {};
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
this._updateStyle();
+
+ this._errorPopoverHelper = new WebInspector.PopoverHelper(this.element, this._getErrorAnchor.bind(this), this._showErrorPopover.bind(this));
+ this._errorPopoverHelper.setTimeout(100, 100);
}
WebInspector.UISourceCodeFrame.prototype = {
@@ -57,6 +60,8 @@ WebInspector.UISourceCodeFrame.prototype = {
this._boundWindowFocused = this._windowFocused.bind(this);
this.element.ownerDocument.defaultView.addEventListener("focus", this._boundWindowFocused, false);
this._checkContentUpdated();
+ // We need CodeMirrorTextEditor to be initialized prior to this call as it calls |cursorPositionToCoordinates| internally. @see crbug.com/506566
+ setImmediate(this._updateBucketDecorations.bind(this));
},
willHide: function()
@@ -106,6 +111,7 @@ WebInspector.UISourceCodeFrame.prototype = {
onTextChanged: function(oldRange, newRange)
{
WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange);
+ this.clearMessages();
if (this._isSettingContent)
return;
this._muteSourceCodeEvents = true;
@@ -116,6 +122,12 @@ WebInspector.UISourceCodeFrame.prototype = {
delete this._muteSourceCodeEvents;
},
+ onTextEditorContentLoaded: function()
+ {
+ WebInspector.SourceFrame.prototype.onTextEditorContentLoaded.call(this);
+ this.clearMessages();
+ },
+
/**
* @param {!WebInspector.Event} event
*/
@@ -200,6 +212,90 @@ WebInspector.UISourceCodeFrame.prototype = {
this.detach();
},
+ /**
+ * @param {!WebInspector.UISourceCode.Message} message
+ */
+ addMessageToSource: function(message)
+ {
+ var lineNumber = message.lineNumber();
+ if (lineNumber >= this._textEditor.linesCount)
+ lineNumber = this._textEditor.linesCount - 1;
+ if (lineNumber < 0)
+ lineNumber = 0;
+
+ if (!this._rowMessageBuckets[lineNumber])
+ this._rowMessageBuckets[lineNumber] = new WebInspector.UISourceCodeFrame.RowMessageBucket(this, this._textEditor, lineNumber);
+ var messageBucket = this._rowMessageBuckets[lineNumber];
+ messageBucket.addMessage(message);
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode.Message} message
+ */
+ removeMessageFromSource: function(message)
+ {
+ var lineNumber = message.lineNumber();
+ if (lineNumber >= this._textEditor.linesCount)
+ lineNumber = this._textEditor.linesCount - 1;
+ if (lineNumber < 0)
+ lineNumber = 0;
+
+ var messageBucket = this._rowMessageBuckets[lineNumber];
+ if (!messageBucket)
+ return;
+ messageBucket.removeMessage(message);
+ if (!messageBucket.uniqueMessagesCount()) {
+ messageBucket.detachFromEditor();
+ delete this._rowMessageBuckets[lineNumber];
+ }
+ },
+
+ clearMessages: function()
+ {
+ for (var line in this._rowMessageBuckets) {
+ var bubble = this._rowMessageBuckets[line];
+ bubble.detachFromEditor();
+ }
+
+ this._rowMessageBuckets = {};
+ this._errorPopoverHelper.hidePopover();
+ },
+
+ /**
+ * @param {!Element} target
+ * @param {!Event} event
+ * @return {(!Element|undefined)}
+ */
+ _getErrorAnchor: function(target, event)
+ {
+ var element = target.enclosingNodeOrSelfWithClass("text-editor-line-decoration-icon")
+ || target.enclosingNodeOrSelfWithClass("text-editor-line-decoration-wave");
+ if (!element)
+ return;
+ this._errorWavePopoverAnchor = new AnchorBox(event.clientX, event.clientY, 1, 1);
+ return element;
+ },
+
+ /**
+ * @param {!Element} anchor
+ * @param {!WebInspector.Popover} popover
+ */
+ _showErrorPopover: function(anchor, popover)
+ {
+ var messageBucket = anchor.enclosingNodeOrSelfWithClass("text-editor-line-decoration")._messageBucket;
+ var messagesOutline = messageBucket.messagesDescription();
+ var popoverAnchor = anchor.enclosingNodeOrSelfWithClass("text-editor-line-decoration-icon") ? anchor : this._errorWavePopoverAnchor;
+ popover.showForAnchor(messagesOutline, popoverAnchor);
+ },
+
+ _updateBucketDecorations: function()
+ {
+ for (var line in this._rowMessageBuckets) {
+ var bucket = this._rowMessageBuckets[line];
+ bucket._updateDecoration();
+ }
+ },
+
__proto__: WebInspector.SourceFrame.prototype
}
@@ -276,3 +372,238 @@ WebInspector.UISourceCodeFrame.Infobar.prototype = {
__proto__: WebInspector.Infobar.prototype
}
+
+/**
+ * @param {!WebInspector.ConsoleMessage} consoleMessage
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {!WebInspector.UISourceCode.Message}
+ */
+WebInspector.UISourceCodeFrame.uiMessageFromConsoleMessage = function(consoleMessage, lineNumber, columnNumber)
+{
+ console.assert(consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.Error || consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.Warning);
+ var level = consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.Error ? WebInspector.UISourceCode.Message.Level.Error : WebInspector.UISourceCode.Message.Level.Warning;
+ return new WebInspector.UISourceCode.Message(level, consoleMessage.messageText, lineNumber, columnNumber);
+}
+
+WebInspector.UISourceCodeFrame._iconClassPerLevel = {};
+WebInspector.UISourceCodeFrame._iconClassPerLevel[WebInspector.UISourceCode.Message.Level.Error] = "error-icon";
+WebInspector.UISourceCodeFrame._iconClassPerLevel[WebInspector.UISourceCode.Message.Level.Warning] = "warning-icon";
+
+WebInspector.UISourceCodeFrame._lineClassPerLevel = {};
+WebInspector.UISourceCodeFrame._lineClassPerLevel[WebInspector.UISourceCode.Message.Level.Error] = "text-editor-line-with-error";
+WebInspector.UISourceCodeFrame._lineClassPerLevel[WebInspector.UISourceCode.Message.Level.Warning] = "text-editor-line-with-warning";
+
+/**
+ * @constructor
+ * @param {!WebInspector.UISourceCode.Message} message
+ */
+WebInspector.UISourceCodeFrame.RowMessage = function(message)
+{
+ this._message = message;
+ this._repeatCount = 1;
+ this.element = createElementWithClass("div", "text-editor-row-message");
+ this._icon = this.element.createChild("label", "", "dt-icon-label");
+ this._icon.type = WebInspector.UISourceCodeFrame._iconClassPerLevel[message.level()];
+ this._repeatCountElement = this.element.createChild("span", "bubble-repeat-count hidden error");
+ var linesContainer = this.element.createChild("div", "text-editor-row-message-lines");
+ var lines = this._message.text().split("\n");
+ for (var i = 0; i < lines.length; ++i) {
+ var messageLine = linesContainer.createChild("div");
+ messageLine.textContent = lines[i];
+ }
+}
+
+WebInspector.UISourceCodeFrame.RowMessage.prototype = {
+ /**
+ * @return {!WebInspector.UISourceCode.Message}
+ */
+ message: function()
+ {
+ return this._message;
+ },
+
+ /**
+ * @return {number}
+ */
+ repeatCount: function()
+ {
+ return this._repeatCount;
+ },
+
+ setRepeatCount: function(repeatCount)
+ {
+ if (this._repeatCount === repeatCount)
+ return;
+ this._repeatCount = repeatCount;
+ this._updateMessageRepeatCount();
+ },
+
+ _updateMessageRepeatCount: function()
+ {
+ this._repeatCountElement.textContent = this._repeatCount;
+ var showRepeatCount = this._repeatCount > 1;
+ this._repeatCountElement.classList.toggle("hidden", !showRepeatCount);
+ this._icon.classList.toggle("hidden", showRepeatCount);
+ }
+}
+
+/**
+ * @constructor
+ * @param {!WebInspector.UISourceCodeFrame} sourceFrame
+ * @param {!WebInspector.CodeMirrorTextEditor} textEditor
+ * @param {number} lineNumber
+ */
+WebInspector.UISourceCodeFrame.RowMessageBucket = function(sourceFrame, textEditor, lineNumber)
+{
+ this._sourceFrame = sourceFrame;
+ this._textEditor = textEditor;
+ this._lineHandle = textEditor.textEditorPositionHandle(lineNumber, 0);
+ this._decoration = createElementWithClass("div", "text-editor-line-decoration");
+ this._decoration._messageBucket = this;
+ this._wave = this._decoration.createChild("div", "text-editor-line-decoration-wave");
+ this._icon = this._wave.createChild("label", "text-editor-line-decoration-icon", "dt-icon-label");
+
+ this._textEditor.addDecoration(lineNumber, this._decoration);
+
+ this._messagesDescriptionElement = createElementWithClass("div", "text-editor-messages-description-container");
+ /** @type {!Array.<!WebInspector.UISourceCodeFrame.RowMessage>} */
+ this._messages = [];
+
+ this._level = null;
+}
+
+WebInspector.UISourceCodeFrame.RowMessageBucket.prototype = {
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ */
+ _updateWavePosition: function(lineNumber, columnNumber)
+ {
+ lineNumber = Math.min(lineNumber, this._textEditor.linesCount - 1);
+ var lineText = this._textEditor.line(lineNumber);
+ columnNumber = Math.min(columnNumber, lineText.length);
+ var lineIndent = WebInspector.TextUtils.lineIndent(lineText).length;
+ var base = this._textEditor.cursorPositionToCoordinates(lineNumber, 0);
+
+ var start = this._textEditor.cursorPositionToCoordinates(lineNumber, Math.max(columnNumber - 1, lineIndent));
+ var end = this._textEditor.cursorPositionToCoordinates(lineNumber, lineText.length);
+ /** @const */
+ var codeMirrorLinesLeftPadding = 4;
+ this._wave.style.left = (start.x - base.x + codeMirrorLinesLeftPadding) + "px";
+ this._wave.style.width = (end.x - start.x) + "px";
+ },
+
+ /**
+ * @return {!Element}
+ */
+ messagesDescription: function()
+ {
+ this._messagesDescriptionElement.removeChildren();
+ for (var i = 0; i < this._messages.length; ++i) {
+ this._messagesDescriptionElement.appendChild(this._messages[i].element);
+ }
+ return this._messagesDescriptionElement;
+ },
+
+ detachFromEditor: function()
+ {
+ var position = this._lineHandle.resolve();
+ if (!position)
+ return;
+ var lineNumber = position.lineNumber;
+ if (this._level)
+ this._textEditor.toggleLineClass(lineNumber, WebInspector.UISourceCodeFrame._lineClassPerLevel[this._level], false);
+ this._textEditor.removeDecoration(lineNumber, this._decoration);
+ },
+
+ /**
+ * @return {number}
+ */
+ uniqueMessagesCount: function()
+ {
+ return this._messages.length;
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode.Message} message
+ */
+ addMessage: function(message)
+ {
+ for (var i = 0; i < this._messages.length; ++i) {
+ var rowMessage = this._messages[i];
+ if (rowMessage.message().isEqual(message)) {
+ rowMessage.setRepeatCount(rowMessage.repeatCount() + 1);
+ return;
+ }
+ }
+
+ var rowMessage = new WebInspector.UISourceCodeFrame.RowMessage(message);
+ this._messages.push(rowMessage);
+ this._updateDecoration();
+ },
+
+ /**
+ * @param {!WebInspector.UISourceCode.Message} message
+ */
+ removeMessage: function(message)
+ {
+ for (var i = 0; i < this._messages.length; ++i) {
+ var rowMessage = this._messages[i];
+ if (!rowMessage.message().isEqual(message))
+ continue;
+ rowMessage.setRepeatCount(rowMessage.repeatCount() - 1);
+ if (!rowMessage.repeatCount())
+ this._messages.splice(i, 1);
+ this._updateDecoration();
+ return;
+ }
+ },
+
+ _updateDecoration: function()
+ {
+ if (!this._sourceFrame.isEditorShowing())
+ return;
+ if (!this._messages.length)
+ return;
+ var position = this._lineHandle.resolve();
+ if (!position)
+ return;
+
+ var lineNumber = position.lineNumber;
+ var columnNumber = Number.MAX_VALUE;
+ var maxMessage = null;
+ for (var i = 0; i < this._messages.length; ++i) {
+ var message = this._messages[i].message();
+ columnNumber = Math.min(columnNumber, message.columnNumber());
+ if (!maxMessage || WebInspector.UISourceCode.Message.messageLevelComparator(maxMessage, message) < 0)
+ maxMessage = message;
+ }
+ this._updateWavePosition(lineNumber, columnNumber);
+
+ if (this._level) {
+ this._textEditor.toggleLineClass(lineNumber, WebInspector.UISourceCodeFrame._lineClassPerLevel[this._level], false);
+ this._icon.type = "";
+ }
+ this._level = maxMessage.level();
+ if (!this._level)
+ return;
+ this._textEditor.toggleLineClass(lineNumber, WebInspector.UISourceCodeFrame._lineClassPerLevel[this._level], true);
+ this._icon.type = WebInspector.UISourceCodeFrame._iconClassPerLevel[this._level];
+ }
+}
+
+WebInspector.UISourceCode.Message._messageLevelPriority = {
+ "Warning": 3,
+ "Error": 4
+};
+
+/**
+ * @param {!WebInspector.UISourceCode.Message} a
+ * @param {!WebInspector.UISourceCode.Message} b
+ * @return {number}
+ */
+WebInspector.UISourceCode.Message.messageLevelComparator = function(a, b)
+{
+ return WebInspector.UISourceCode.Message._messageLevelPriority[a.level()] - WebInspector.UISourceCode.Message._messageLevelPriority[b.level()];
+}

Powered by Google App Engine
This is Rietveld 408576698