diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 5c6ec07c0..82f9291df 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -309,24 +309,37 @@ void CodeModel::runCompilationJob(int _jobId) } catch (dev::Exception const& _exception) { - std::ostringstream error; + std::stringstream error; solidity::SourceReferenceFormatter::printExceptionInformation(error, _exception, "Error", cs); QString message = QString::fromStdString(error.str()); - QString sourceName; - if (SourceLocation const* location = boost::get_error_info(_exception)) - { - if (location->sourceName) - sourceName = QString::fromStdString(*location->sourceName); - if (!sourceName.isEmpty()) - if (CompiledContract* contract = contractByDocumentId(sourceName)) - message = message.replace(sourceName, contract->contract()->name()); //substitute the location to match our contract names - } - compilationError(message, sourceName); + QVariantMap firstLocation; + QVariantMap secondLocation; + if (SourceLocation const* first = boost::get_error_info(_exception)) + firstLocation = resolveCompilationErrorLocation(cs, *first); + if (SecondarySourceLocation const* second = boost::get_error_info(_exception)) + secondLocation = resolveCompilationErrorLocation(cs, second->infos.front().second); + compilationError(message, firstLocation, secondLocation); } m_compiling = false; emit stateChanged(); } +QVariantMap CodeModel::resolveCompilationErrorLocation(CompilerStack const& _compiler, SourceLocation const& _location) +{ + std::tuple pos = _compiler.positionFromSourceLocation(_location); + QVariantMap startError; + startError.insert("line", std::get<0>(pos) - 1); + startError.insert("column", std::get<1>(pos) - 1); + QVariantMap endError; + endError.insert("line", std::get<2>(pos) - 1); + endError.insert("column", std::get<3>(pos) - 1); + QVariantMap error; + error.insert("start", startError); + error.insert("end", endError); + error.insert("source", QString::fromStdString(*_location.sourceName)); + return error; +} + void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames) { Guard pl(x_pendingContracts); diff --git a/mix/CodeModel.h b/mix/CodeModel.h index a0b03951f..05d013f9a 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -175,7 +175,7 @@ signals: /// Emitted on compilation complete void compilationComplete(); /// Emitted on compilation error - void compilationError(QString _error, QString _sourceName); + void compilationError(QString _error, QVariantMap _firstErrorLoc, QVariantMap _secondErrorLoc); /// Internal signal used to transfer compilation job to background thread void scheduleCompilationJob(int _jobId); /// Emitted if there are any changes in the code model @@ -198,6 +198,7 @@ private: void stop(); void releaseContracts(); void collectContracts(dev::solidity::CompilerStack const& _cs, std::vector const& _sourceNames); + QVariantMap resolveCompilationErrorLocation(dev::solidity::CompilerStack const& _cs, dev::SourceLocation const& _location); std::atomic m_compiling; mutable dev::Mutex x_contractMap; diff --git a/mix/qml/CodeEditorView.qml b/mix/qml/CodeEditorView.qml index bb7e203bf..8ebb7319f 100644 --- a/mix/qml/CodeEditorView.qml +++ b/mix/qml/CodeEditorView.qml @@ -173,7 +173,7 @@ Item { Connections { target: codeModel onCompilationError: { - sourceInError = _sourceName; + sourceInError = _firstErrorLoc.source; } onCompilationComplete: { sourceInError = ""; diff --git a/mix/qml/WebCodeEditor.qml b/mix/qml/WebCodeEditor.qml index 38f2327b1..49a0576cc 100644 --- a/mix/qml/WebCodeEditor.qml +++ b/mix/qml/WebCodeEditor.qml @@ -137,17 +137,28 @@ Item { editorBrowser.runJavaScript("compilationComplete()", function(result) { }); } - function compilationError(error, sourceName) + function compilationError(error, firstLocation, secondLocation) { - if (sourceName !== parent.sourceName) + console.log("current " + parent.sourceName); + console.log("source " + firstLocation.source); + if (firstLocation.source !== parent.sourceName && secondLocation.source !== parent.sourceName) return; if (!editorBrowser || !error) return; - var errorInfo = ErrorLocationFormater.extractErrorInfo(error, false); - if (errorInfo.line && errorInfo.column) - editorBrowser.runJavaScript("compilationError('" + errorInfo.line + "', '" + errorInfo.column + "', '" + errorInfo.errorDetail + "')", function(result) { }); + if (firstLocation.start.line) + { + var detail = error.split('\n')[0]; + var reg = detail.match(/:\d+:\d+:/g); + if (reg !== null) + detail = detail.replace(reg[0], ""); + editorBrowser.runJavaScript("compilationError('" + JSON.stringify(firstLocation) + "', '" + JSON.stringify(secondLocation) + "', '" + detail + "')", function(result){}); + } else + { + console.log("e d qml"); editorBrowser.runJavaScript("compilationComplete()", function(result) { }); + } + } Timer diff --git a/mix/qml/html/cm/errorannotation.js b/mix/qml/html/cm/errorannotation.js index 071f0e0d8..f5266d4dc 100644 --- a/mix/qml/html/cm/errorannotation.js +++ b/mix/qml/html/cm/errorannotation.js @@ -1,42 +1,39 @@ -function ErrorAnnotation(editor, line, column, content) +function ErrorAnnotation(editor, location, content) { + this.location = JSON.parse(location); this.opened = false; - this.line = line; - this.column = column; + this.rawContent = content; this.content = content.replace("Contract Error:", ""); this.editor = editor; this.errorMark = null; this.lineWidget = null; this.init(); - this.open(); + if (this.content) + this.open(); } ErrorAnnotation.prototype.init = function() { - 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) - incrMark = this.column + 1; - this.errorMark = editor.markText({ line: this.line, ch: this.column }, { line: this.line, ch: incrMark }, { className: "CodeMirror-errorannotation", inclusiveRight: true }); + this.errorMark = editor.markText({ line: this.location.start.line, ch: this.location.start.column }, { line: this.location.end.line, ch: this.location.end.column }, { className: "CodeMirror-errorannotation", inclusiveRight: true }); } ErrorAnnotation.prototype.open = function() { - if (this.line) + if (this.location.start.line) { var node = document.createElement("div"); node.id = "annotation" node.innerHTML = this.content; node.className = "CodeMirror-errorannotation-context"; - this.lineWidget = this.editor.addLineWidget(this.line, node, { coverGutter: false }); + this.lineWidget = this.editor.addLineWidget(this.location.start.line, node, { coverGutter: false }); this.opened = true; } } ErrorAnnotation.prototype.close = function() { - this.lineWidget.clear(); + if (this.lineWidget) + this.lineWidget.clear(); this.opened = false; } @@ -47,3 +44,6 @@ ErrorAnnotation.prototype.destroy = function() if (this.errorMark) this.errorMark.clear(); } + + + diff --git a/mix/qml/html/cm/solidityToken.js b/mix/qml/html/cm/solidityToken.js index d8e588a10..d803697cb 100644 --- a/mix/qml/html/cm/solidityToken.js +++ b/mix/qml/html/cm/solidityToken.js @@ -5,7 +5,7 @@ function solCurrency() function solKeywords() { - return { "break": true, "case": true, "constant": true, "continue": true, "contract": true, "default": true, "do": true, "else": true, "event": true, "external": true, "is": true, "indexed": true, "for": true, "function": true, "if": true, "import": true, "mapping": true, "modifier": true, "new": true, "public": true, "private": true, "internal": true, "return": true, "returns": true, "struct": true, "switch": true, "var": true, "while": true, "enum": true }; + return { "delete": true, "break": true, "case": true, "constant": true, "continue": true, "contract": true, "default": true, "do": true, "else": true, "event": true, "external": true, "is": true, "indexed": true, "for": true, "function": true, "if": true, "import": true, "mapping": true, "modifier": true, "new": true, "public": true, "private": true, "internal": true, "return": true, "returns": true, "struct": true, "switch": true, "var": true, "while": true, "enum": true }; } function solStdContract() diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index d25fbd091..4c8af5888 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -158,30 +158,43 @@ showWarning = function(content) } var annotation = null; +var secondaryAnnotation = null; var compilationCompleteBool = true; -compilationError = function(line, column, content) +compilationError = function(location, secondLocation, error) { compilationCompleteBool = false; window.setTimeout(function(){ if (compilationCompleteBool) return; - line = parseInt(line); - column = parseInt(column); - if (line > 0) - line = line - 1; - if (column > 0) - column = column - 1; + var loc = JSON.parse(location); if (annotation == null) - annotation = new ErrorAnnotation(editor, line, column, content); - else if (annotation.line !== line || annotation.column !== column || annotation.content !== content) + { + annotation = new ErrorAnnotation(editor, location, error); + if (secondLocation.start) + secondaryAnnotation = new ErrorAnnotation(editor, secondLocation, ""); + } + else if (annotation.location.start.line !== loc.start.line || annotation.location.start.column !== loc.start.column || annotation.rawContent !== error) { annotation.destroy(); - annotation = new ErrorAnnotation(editor, line, column, content); + annotation = new ErrorAnnotation(editor, location, error); + if (secondaryAnnotation) + secondaryAnnotation.destroy(); + secondaryAnnotation = new ErrorAnnotation(editor, secondLocation, ""); } }, 500) } +formatSource = function(line, column) +{ + line = parseInt(line); + column = parseInt(column); + if (line > 0) + line = line - 1; + if (column > 0) + column = column - 1; +} + compilationComplete = function() { if (annotation !== null) @@ -189,12 +202,20 @@ compilationComplete = function() annotation.destroy(); annotation = null; } + + if (secondaryAnnotation !== null) + { + secondaryAnnotation.destroy(); + secondaryAnnotation = null; + } + compilationCompleteBool = true; + console.log("end"); } goToCompilationError = function() { - editor.setCursor(annotation.line, annotation.column) + editor.setCursor(annotation.start.line, annotation.start.column) } setFontSize = function(size)