From 5a9042640fca39c5ad43ecccd974d4c59ab09b42 Mon Sep 17 00:00:00 2001 From: yann300 Date: Thu, 19 Mar 2015 17:32:21 +0100 Subject: [PATCH 1/8] Error annotation --- mix/qml/Debugger.qml | 2 +- mix/qml/WebCodeEditor.qml | 13 ++++++ mix/qml/html/cm/solarized.css | 5 ++ mix/qml/html/codeeditor.js | 71 +++++++++++++++++++++-------- mix/qml/js/ErrorLocationFormater.js | 5 +- 5 files changed, 75 insertions(+), 21 deletions(-) diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index c4b6502b0..1a823e276 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -40,7 +40,7 @@ Rectangle { var errorInfo = ErrorLocationFormater.extractErrorInfo(compilationErrorMessage, false); errorLocation.text = errorInfo.errorLocation; errorDetail.text = errorInfo.errorDetail; - errorLine.text = errorInfo.errorLine; + errorLine.text = errorInfo.line; } function update(data, giveFocus) diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index c424eeddd..e77da0f45 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -4,6 +4,7 @@ import QtQuick.Layouts 1.0 import QtQuick.Controls.Styles 1.1 import QtWebEngine 1.0 import QtWebEngine.experimental 1.0 +import "js/ErrorLocationFormater.js" as ErrorLocationFormater Item { signal editorTextChanged @@ -83,7 +84,19 @@ Item { runJavaScript("getTextChanged()", function(result) { }); pollTimer.running = true; syncClipboard(); + if (currentMode === "solidity") + { + codeModel.onCompilationComplete.connect(function(){ + runJavaScript("compilationComplete()", function(result) { }); + }); + + codeModel.onCompilationError.connect(function(error){ + var errorInfo = ErrorLocationFormater.extractErrorInfo(error, false); + runJavaScript("compilationError('" + errorInfo.line + "', '" + errorInfo.column + "', '" + errorInfo.errorDetail + "')", function(result) { }); + }); + } parent.changeGeneration(); + } } diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index f07b8b43b..9f324241a 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -169,3 +169,8 @@ view-port background: rgba(255, 255, 255, 0.10); } +/* Error annotation */ +.CodeMirror-errorannotation { + background: red; +} + diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 25c20ab2d..ea04f891b 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -22,23 +22,23 @@ editor.on("change", function(eMirror, object) { var mac = /Mac/.test(navigator.platform); if (mac === true) { -editor.setOption("extraKeys", { - "Cmd-V": function(cm) { - cm.replaceSelection(clipboard); - }, - "Cmd-X": function(cm) { - window.document.execCommand("cut"); - }, - "Cmd-C": function(cm) { - window.document.execCommand("copy"); - }}); + editor.setOption("extraKeys", { + "Cmd-V": function(cm) { + cm.replaceSelection(clipboard); + }, + "Cmd-X": function(cm) { + window.document.execCommand("cut"); + }, + "Cmd-C": function(cm) { + window.document.execCommand("copy"); + }}); } makeMarker = function() { - var marker = document.createElement("div"); - marker.style.color = "#822"; - marker.innerHTML = "●"; - return marker; + var marker = document.createElement("div"); + marker.style.color = "#822"; + marker.innerHTML = "●"; + return marker; }; toggleBreakpointLine = function(n) { @@ -77,9 +77,9 @@ getBreakpoints = function() { if (line.gutterMarkers && line.gutterMarkers["breakpoints"]) { var l = doc.getLineNumber(line); locations.push({ - start: editor.indexFromPos({ line: l, ch: 0}), - end: editor.indexFromPos({ line: l + 1, ch: 0}) - });; + start: editor.indexFromPos({ line: l, ch: 0}), + end: editor.indexFromPos({ line: l + 1, ch: 0}) + });; } }); return locations; @@ -101,13 +101,13 @@ setMode = function(mode) { if (mode === "javascript") { CodeMirror.commands.autocomplete = function(cm) { - CodeMirror.showHint(cm, CodeMirror.hint.anyword); // TODO change to a proper JavaScript language completion + CodeMirror.showHint(cm, CodeMirror.hint.anyword); // TODO change to a proper JavaScript language completion } } else if (mode === "solidity") { CodeMirror.commands.autocomplete = function(cm) { - CodeMirror.showHint(cm, CodeMirror.hint.anyword); + CodeMirror.showHint(cm, CodeMirror.hint.anyword); } } }; @@ -133,3 +133,36 @@ isClean = function() { return editor.isClean(changeId); } + +var errorMark; +var compilationCompleteBool = true; +compilationError = function(line, column, content) +{ + compilationCompleteBool = false; + window.setTimeout(function(){ + if (errorMark) + errorMark.clear(); + if (compilationCompleteBool) + return; + line = parseInt(line); + column = parseInt(column); + if (line > 0) + line = line - 1; + if (column > 0) + column = column - 1; + + var separators = [' ', '\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; + var errorPart = editor.getLine(line).substring(column); + var incrMark = column + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; + if (incrMark === column) + incrMark = column + 1; + errorMark = editor.markText({ line: line, ch: column }, { line: line, ch: incrMark }, { className: "CodeMirror-errorannotation" }); + }, 1000) +} + +compilationComplete = function() +{ + if (errorMark) + errorMark.clear(); + compilationCompleteBool = true; +} diff --git a/mix/qml/js/ErrorLocationFormater.js b/mix/qml/js/ErrorLocationFormater.js index 8c83e6b15..cb92f298b 100644 --- a/mix/qml/js/ErrorLocationFormater.js +++ b/mix/qml/js/ErrorLocationFormater.js @@ -16,12 +16,15 @@ function extractErrorInfo(raw, shortMessage) { _return.errorLocation = ErrorLocationFormater.formatLocation(reg[0], shortMessage); _return.errorDetail = detail.replace(reg[0], ""); + _return.line = reg[0].split(':')[1]; + _return.column = reg[0].split(':')[2]; } else { _return.errorLocation = ""; _return.errorDetail = detail; + _return.line = ""; + _return.column = ""; } - _return.errorLine = raw.split('\n')[1]; return _return; } From 28ccaf0cfa672b06ee5f354234d42c5c53f96748 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 20 Mar 2015 15:46:29 +0100 Subject: [PATCH 2/8] error annotation widget --- mix/qml/html/cm/errorannotation.js | 46 ++++++++++++++++++++++++++++++ mix/qml/html/cm/solarized.css | 11 ++++++- mix/qml/html/codeeditor.html | 1 + mix/qml/html/codeeditor.js | 22 ++++++-------- mix/web.qrc | 1 + 5 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 mix/qml/html/cm/errorannotation.js diff --git a/mix/qml/html/cm/errorannotation.js b/mix/qml/html/cm/errorannotation.js new file mode 100644 index 000000000..4da65ffa0 --- /dev/null +++ b/mix/qml/html/cm/errorannotation.js @@ -0,0 +1,46 @@ +function ErrorAnnotation(editor, line, col, content) +{ + this.opened = false; + this.line = line; + this.col = col; + this.content = content; + this.editor = editor; + this.errorMark = null; + this.lineWidget = null; + this.init(); + this.open(); +} + +ErrorAnnotation.prototype.init = function() +{ + var separators = [' ', '\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; + var errorPart = editor.getLine(this.line).substring(this.col); + var incrMark = this.col + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; + if (incrMark === this.col) + incrMark = this.col + 1; + this.errorMark = editor.markText({ line: this.line, ch: this.col }, { line: this.line, ch: incrMark }, { className: "CodeMirror-errorannotation", inclusiveRight: true }); +} + +ErrorAnnotation.prototype.open = function() +{ + var node = document.createElement("div"); + node.id = "annotation" + node.innerHTML = this.content; + node.className = "CodeMirror-errorannotation-context" + this.lineWidget = this.editor.addLineWidget(this.errorMark.find().from.line, node, { coverGutter: true }); + this.opened = true; +} + +ErrorAnnotation.prototype.close = function() +{ + this.lineWidget.clear(); + this.opened = false; +} + +ErrorAnnotation.prototype.detroy = function() +{ + if (this.opened) + this.close(); + if (this.errorMark) + this.errorMark.clear(); +} diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index 9f324241a..8a15b731f 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -171,6 +171,15 @@ view-port /* Error annotation */ .CodeMirror-errorannotation { - background: red; + background: rgb(255, 255, 170); + color: red !important; +} + +.CodeMirror-errorannotation-context { + font-family: monospace; + font-size: small; + color: red; + background: rgb(255, 255, 170); + padding: 2px; } diff --git a/mix/qml/html/codeeditor.html b/mix/qml/html/codeeditor.html index 4545b6239..5a8d5c462 100644 --- a/mix/qml/html/codeeditor.html +++ b/mix/qml/html/codeeditor.html @@ -22,6 +22,7 @@ + diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index ea04f891b..a549d0e68 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -134,14 +134,12 @@ isClean = function() return editor.isClean(changeId); } -var errorMark; +var annotation = null; var compilationCompleteBool = true; compilationError = function(line, column, content) { compilationCompleteBool = false; window.setTimeout(function(){ - if (errorMark) - errorMark.clear(); if (compilationCompleteBool) return; line = parseInt(line); @@ -150,19 +148,17 @@ compilationError = function(line, column, content) line = line - 1; if (column > 0) column = column - 1; - - var separators = [' ', '\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; - var errorPart = editor.getLine(line).substring(column); - var incrMark = column + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; - if (incrMark === column) - incrMark = column + 1; - errorMark = editor.markText({ line: line, ch: column }, { line: line, ch: incrMark }, { className: "CodeMirror-errorannotation" }); - }, 1000) + if (annotation == null) + annotation = new ErrorAnnotation(editor, line, column, content); + }, 500) } compilationComplete = function() { - if (errorMark) - errorMark.clear(); + if (annotation !== null) + { + annotation.detroy(); + annotation = null; + } compilationCompleteBool = true; } diff --git a/mix/web.qrc b/mix/web.qrc index 118177d07..10cd26764 100644 --- a/mix/web.qrc +++ b/mix/web.qrc @@ -27,5 +27,6 @@ qml/html/cm/closebrackets.js qml/html/cm/solidityToken.js qml/html/cm/javascript-hint.js + qml/html/cm/errorannotation.js From 433f47b109b8c9a43dd80c50158ebf11aeff3d75 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 20 Mar 2015 16:57:48 +0100 Subject: [PATCH 3/8] small changes --- mix/qml/html/cm/errorannotation.js | 18 +++++++++--------- mix/qml/html/cm/solarized.css | 8 ++++---- mix/qml/html/codeeditor.js | 8 +++++++- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/mix/qml/html/cm/errorannotation.js b/mix/qml/html/cm/errorannotation.js index 4da65ffa0..0830d2b9e 100644 --- a/mix/qml/html/cm/errorannotation.js +++ b/mix/qml/html/cm/errorannotation.js @@ -1,8 +1,8 @@ -function ErrorAnnotation(editor, line, col, content) +function ErrorAnnotation(editor, line, column, content) { this.opened = false; this.line = line; - this.col = col; + this.column = column; this.content = content; this.editor = editor; this.errorMark = null; @@ -14,11 +14,11 @@ function ErrorAnnotation(editor, line, col, content) ErrorAnnotation.prototype.init = function() { var separators = [' ', '\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; - var errorPart = editor.getLine(this.line).substring(this.col); - var incrMark = this.col + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; - if (incrMark === this.col) - incrMark = this.col + 1; - this.errorMark = editor.markText({ line: this.line, ch: this.col }, { line: this.line, ch: incrMark }, { className: "CodeMirror-errorannotation", inclusiveRight: true }); + var errorPart = editor.getLine(this.line).substring(this.column); + var incrMark = this.column + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; + if (incrMark === this.column) + incrMark = this.column + 1; + this.errorMark = editor.markText({ line: this.line, ch: this.column }, { line: this.line, ch: incrMark }, { className: "CodeMirror-errorannotation", inclusiveRight: true }); } ErrorAnnotation.prototype.open = function() @@ -26,7 +26,7 @@ ErrorAnnotation.prototype.open = function() var node = document.createElement("div"); node.id = "annotation" node.innerHTML = this.content; - node.className = "CodeMirror-errorannotation-context" + node.className = "CodeMirror-errorannotation-context"; this.lineWidget = this.editor.addLineWidget(this.errorMark.find().from.line, node, { coverGutter: true }); this.opened = true; } @@ -37,7 +37,7 @@ ErrorAnnotation.prototype.close = function() this.opened = false; } -ErrorAnnotation.prototype.detroy = function() +ErrorAnnotation.prototype.destroy = function() { if (this.opened) this.close(); diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index 8a15b731f..0f4764c30 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -171,15 +171,15 @@ view-port /* Error annotation */ .CodeMirror-errorannotation { - background: rgb(255, 255, 170); - color: red !important; + background: #b58900; + color: #dc322f !important; } .CodeMirror-errorannotation-context { font-family: monospace; font-size: small; - color: red; - background: rgb(255, 255, 170); + color: #dc322f; + background: #b58900; padding: 2px; } diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index a549d0e68..f42e62c94 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -148,8 +148,14 @@ compilationError = function(line, column, content) line = line - 1; if (column > 0) column = column - 1; + if (annotation == null) annotation = new ErrorAnnotation(editor, line, column, content); + else if (annotation.line !== line || annotation.column !== column || annotation.content !== content) + { + annotation.destroy(); + annotation = new ErrorAnnotation(editor, line, column, content); + } }, 500) } @@ -157,7 +163,7 @@ compilationComplete = function() { if (annotation !== null) { - annotation.detroy(); + annotation.destroy(); annotation = null; } compilationCompleteBool = true; From 2d7fc88e7cd99b3c8f19554d693ee4fd6d659bf6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 20 Mar 2015 17:23:25 +0100 Subject: [PATCH 4/8] ui changes --- mix/qml/html/cm/errorannotation.js | 6 +++--- mix/qml/html/cm/solarized.css | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mix/qml/html/cm/errorannotation.js b/mix/qml/html/cm/errorannotation.js index 0830d2b9e..345d389b2 100644 --- a/mix/qml/html/cm/errorannotation.js +++ b/mix/qml/html/cm/errorannotation.js @@ -3,7 +3,7 @@ function ErrorAnnotation(editor, line, column, content) this.opened = false; this.line = line; this.column = column; - this.content = content; + this.content = content.replace("Contract Error:", ""); this.editor = editor; this.errorMark = null; this.lineWidget = null; @@ -13,7 +13,7 @@ function ErrorAnnotation(editor, line, column, content) ErrorAnnotation.prototype.init = function() { - var separators = [' ', '\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; + var separators = ['\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; var errorPart = editor.getLine(this.line).substring(this.column); var incrMark = this.column + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; if (incrMark === this.column) @@ -27,7 +27,7 @@ ErrorAnnotation.prototype.open = function() node.id = "annotation" node.innerHTML = this.content; node.className = "CodeMirror-errorannotation-context"; - this.lineWidget = this.editor.addLineWidget(this.errorMark.find().from.line, node, { coverGutter: true }); + this.lineWidget = this.editor.addLineWidget(this.errorMark.find().from.line, node, { coverGutter: false }); this.opened = true; } diff --git a/mix/qml/html/cm/solarized.css b/mix/qml/html/cm/solarized.css index 0f4764c30..ece98a95c 100644 --- a/mix/qml/html/cm/solarized.css +++ b/mix/qml/html/cm/solarized.css @@ -171,14 +171,13 @@ view-port /* Error annotation */ .CodeMirror-errorannotation { - background: #b58900; - color: #dc322f !important; + border-bottom: 1px solid #b58900; } .CodeMirror-errorannotation-context { font-family: monospace; font-size: small; - color: #dc322f; + color: #586e75; background: #b58900; padding: 2px; } From 04bb0ff2634c8deb37707ffebd4563dae8b37807 Mon Sep 17 00:00:00 2001 From: yann300 Date: Fri, 20 Mar 2015 17:28:14 +0100 Subject: [PATCH 5/8] small changes --- mix/qml/html/cm/errorannotation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix/qml/html/cm/errorannotation.js b/mix/qml/html/cm/errorannotation.js index 345d389b2..03e36c927 100644 --- a/mix/qml/html/cm/errorannotation.js +++ b/mix/qml/html/cm/errorannotation.js @@ -13,7 +13,7 @@ function ErrorAnnotation(editor, line, column, content) ErrorAnnotation.prototype.init = function() { - var separators = ['\\\+', '-', ';', '\\\(', '\\\{', '\\\}', '\\\)', '\\*', '/', ':', '\\\?']; + var separators = [';', ',', '\\\(', '\\\{', '\\\}', '\\\)', ':']; var errorPart = editor.getLine(this.line).substring(this.column); var incrMark = this.column + errorPart.split(new RegExp(separators.join('|'), 'g'))[0].length; if (incrMark === this.column) From 8bce0525375ced5e5145dfe15383c5faa7175e1b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 23 Mar 2015 11:49:15 +0100 Subject: [PATCH 6/8] Do not hightlight the whole document when debugging. --- mix/qml/html/codeeditor.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 102ba97a6..daf1286d8 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -132,6 +132,8 @@ var executionMark; highlightExecution = function(start, end) { if (executionMark) executionMark.clear(); + if (start === 0 && end + 1 === editor.getValue().length) + return; // Do not hightlight the whole document. executionMark = editor.markText(editor.posFromIndex(start), editor.posFromIndex(end), { className: "CodeMirror-exechighlight" }); } From 7c34bac9db621936356dbc9358c254e39c09d01b Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 23 Mar 2015 12:33:48 +0100 Subject: [PATCH 7/8] Ensure line nb and column nb are set. --- mix/qml/WebCodeEditor.qml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index 8ef3cc40c..7e5945fc7 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -92,7 +92,10 @@ Item { codeModel.onCompilationError.connect(function(error){ var errorInfo = ErrorLocationFormater.extractErrorInfo(error, false); - runJavaScript("compilationError('" + errorInfo.line + "', '" + errorInfo.column + "', '" + errorInfo.errorDetail + "')", function(result) { }); + if (errorInfo.line && errorInfo.column) + runJavaScript("compilationError('" + errorInfo.line + "', '" + errorInfo.column + "', '" + errorInfo.errorDetail + "')", function(result) { }); + else + runJavaScript("compilationComplete()", function(result) { }); }); } parent.changeGeneration(); From e11d04a79e7b61978001e295134ba6500c679d70 Mon Sep 17 00:00:00 2001 From: yann300 Date: Mon, 23 Mar 2015 12:58:34 +0100 Subject: [PATCH 8/8] Fix visible/hidden 'Step Out Back' and 'Run Forward' buttons. --- mix/qml/Debugger.qml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index b1f910ccb..358750b24 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -242,7 +242,6 @@ Rectangle { height: 30 buttonShortcut: "Ctrl+Shift+F11" buttonTooltip: qsTr("Step Out Back") - visible: false } StepActionImage @@ -315,9 +314,8 @@ Rectangle { height: 30 buttonShortcut: "Ctrl+F5" buttonTooltip: qsTr("Run Forward") + visible: false } - - } }