Commit f5874da3 authored by Joel Einbinder's avatar Joel Einbinder Committed by Commit Bot

DevTools: Use CodeMirror for the conditional breakpoint editor

This adds syntax highlighting, autocomplete, argument hints, and
smart enter to the breakpoint editor

Change-Id: I973be5e44ff94f36fbefdeb1eb472122ee2789a9
Reviewed-on: https://chromium-review.googlesource.com/1144195Reviewed-by: default avatarAndrey Lushnikov <lushnikov@chromium.org>
Commit-Queue: Andrey Lushnikov <lushnikov@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577394}
parent 88561680
...@@ -232,23 +232,15 @@ Console.ConsolePrompt = class extends UI.Widget { ...@@ -232,23 +232,15 @@ Console.ConsolePrompt = class extends UI.Widget {
if (!str.length) if (!str.length)
return; return;
const currentExecutionContext = UI.context.flavor(SDK.ExecutionContext); if (!this._isCaretAtEndOfPrompt()) {
if (!this._isCaretAtEndOfPrompt() || !currentExecutionContext) { await this._appendCommand(str, true);
this._appendCommand(str, true);
return; return;
} }
const result = await currentExecutionContext.runtimeModel.compileScript(str, '', false, currentExecutionContext.id);
if (str !== this.text()) if (await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(str))
return; await this._appendCommand(str, true);
const exceptionDetails = result.exceptionDetails; else
if (exceptionDetails &&
(exceptionDetails.exception.description.startsWith('SyntaxError: Unexpected end of input') ||
exceptionDetails.exception.description.startsWith('SyntaxError: Unterminated template literal'))) {
this._editor.newlineAndIndent(); this._editor.newlineAndIndent();
this._enterProcessedForTest();
return;
}
await this._appendCommand(str, true);
this._enterProcessedForTest(); this._enterProcessedForTest();
} }
......
...@@ -596,6 +596,23 @@ ObjectUI.JavaScriptAutocomplete = class { ...@@ -596,6 +596,23 @@ ObjectUI.JavaScriptAutocomplete = class {
return -1; return -1;
return String.naturalOrderComparator(a, b); return String.naturalOrderComparator(a, b);
} }
/**
* @param {string} expression
* @return {!Promise<boolean>}
*/
static async isExpressionComplete(expression) {
const currentExecutionContext = UI.context.flavor(SDK.ExecutionContext);
if (!currentExecutionContext)
return true;
const result =
await currentExecutionContext.runtimeModel.compileScript(expression, '', false, currentExecutionContext.id);
if (!result.exceptionDetails)
return true;
const description = result.exceptionDetails.exception.description;
return !description.startsWith('SyntaxError: Unexpected end of input') &&
!description.startsWith('SyntaxError: Unterminated template literal');
}
}; };
/** @typedef {{title:(string|undefined), items:Array<string>}} */ /** @typedef {{title:(string|undefined), items:Array<string>}} */
......
...@@ -40,10 +40,6 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin { ...@@ -40,10 +40,6 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._uiSourceCode = uiSourceCode; this._uiSourceCode = uiSourceCode;
this._transformer = transformer; this._transformer = transformer;
/** @type {?Element} */
this._conditionEditorElement = null;
/** @type {?Element} */
this._conditionElement = null;
/** @type {?Workspace.UILocation} */ /** @type {?Workspace.UILocation} */
this._executionLocation = null; this._executionLocation = null;
this._controlDown = false; this._controlDown = false;
...@@ -646,52 +642,66 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin { ...@@ -646,52 +642,66 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {?Bindings.BreakpointManager.Breakpoint} breakpoint * @param {?Bindings.BreakpointManager.Breakpoint} breakpoint
* @param {?{lineNumber: number, columnNumber: number}} location * @param {?{lineNumber: number, columnNumber: number}} location
*/ */
_editBreakpointCondition(editorLineNumber, breakpoint, location) { async _editBreakpointCondition(editorLineNumber, breakpoint, location) {
this._conditionElement = this._createConditionElement(editorLineNumber); const conditionElement = createElementWithClass('div', 'source-frame-breakpoint-condition');
this._textEditor.addDecoration(this._conditionElement, editorLineNumber);
const labelElement = conditionElement.createChild('label', 'source-frame-breakpoint-message');
labelElement.htmlFor = 'source-frame-breakpoint-condition';
labelElement.createTextChild(
Common.UIString('The breakpoint on line %d will stop only if this expression is true:', editorLineNumber + 1));
this._textEditor.addDecoration(conditionElement, editorLineNumber);
/** @type {!UI.TextEditorFactory} */
const factory = await self.runtime.extension(UI.TextEditorFactory).instance();
const editor =
factory.createEditor({lineNumbers: false, lineWrapping: true, mimeType: 'javascript', autoHeight: true});
editor.widget().show(conditionElement);
if (breakpoint)
editor.setText(breakpoint.condition());
editor.setSelection(editor.fullRange());
editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(editor));
editor.widget().element.addEventListener('keydown', async event => {
if (isEnterKey(event) && !event.shiftKey) {
event.consume(true);
if (event.ctrlKey)
event.consume(true);
const expression = editor.text();
if (event.ctrlKey || await ObjectUI.JavaScriptAutocomplete.isExpressionComplete(expression))
finishEditing.call(this, true);
else
editor.newlineAndIndent();
}
if (isEscKey(event))
finishEditing.call(this, false);
}, true);
editor.widget().focus();
editor.widget().element.id = 'source-frame-breakpoint-condition';
editor.widget().element.addEventListener('blur', event => {
finishEditing.call(this, true);
}, true);
let finished = false;
/** /**
* @this {Sources.DebuggerPlugin} * @this {Sources.DebuggerPlugin}
*/ */
function finishEditing(committed, element, newText) { function finishEditing(committed) {
this._textEditor.removeDecoration(/** @type {!Element} */ (this._conditionElement), editorLineNumber); if (finished)
this._conditionEditorElement = null; return;
this._conditionElement = null; finished = true;
editor.widget().detach();
this._textEditor.removeDecoration(/** @type {!Element} */ (conditionElement), editorLineNumber);
if (!committed) if (!committed)
return; return;
if (breakpoint) if (breakpoint)
breakpoint.setCondition(newText); breakpoint.setCondition(editor.text().trim());
else if (location) else if (location)
this._setBreakpoint(location.lineNumber, location.columnNumber, newText, true); this._setBreakpoint(location.lineNumber, location.columnNumber, editor.text().trim(), true);
else else
this._createNewBreakpoint(editorLineNumber, newText, true); this._createNewBreakpoint(editorLineNumber, editor.text().trim(), true);
} }
const config = new UI.InplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, false));
UI.InplaceEditor.startEditing(/** @type {!Element} */ (this._conditionEditorElement), config);
this._conditionEditorElement.value = breakpoint ? breakpoint.condition() : '';
this._conditionEditorElement.select();
}
/**
* @param {number} editorLineNumber
* @return {!Element}
*/
_createConditionElement(editorLineNumber) {
const conditionElement = createElementWithClass('div', 'source-frame-breakpoint-condition');
const labelElement = conditionElement.createChild('label', 'source-frame-breakpoint-message');
labelElement.htmlFor = 'source-frame-breakpoint-condition';
labelElement.createTextChild(
Common.UIString('The breakpoint on line %d will stop only if this expression is true:', editorLineNumber + 1));
const editorElement = UI.createInput('monospace', 'text');
conditionElement.appendChild(editorElement);
editorElement.id = 'source-frame-breakpoint-condition';
this._conditionEditorElement = editorElement;
return conditionElement;
} }
/** /**
......
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
width: 100%; width: 100%;
box-shadow: none !important; box-shadow: none !important;
outline: none !important; outline: none !important;
background: white;
} }
@-webkit-keyframes source-frame-value-update-highlight-animation { @-webkit-keyframes source-frame-value-update-highlight-animation {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment