diff --git a/bin/app/data/gui/statusbar_view/octagon.png b/bin/app/data/gui/statusbar_view/octagon.png new file mode 100644 index 00000000..71894336 Binary files /dev/null and b/bin/app/data/gui/statusbar_view/octagon.png differ diff --git a/src/app/qt/element/QtCodeArea.cpp b/src/app/qt/element/QtCodeArea.cpp index 66e5a1c0..177fcff3 100644 --- a/src/app/qt/element/QtCodeArea.cpp +++ b/src/app/qt/element/QtCodeArea.cpp @@ -36,8 +36,8 @@ bool MouseWheelOverScrollbarFilter::eventFilter(QObject* obj, QEvent* event) QRect scrollbarArea(scrollbar->pos(), scrollbar->size()); QPoint globalMousePos = dynamic_cast(event)->globalPos(); QPoint localMousePos = scrollbar->mapFromGlobal(globalMousePos); - - // instead of "scrollbar->underMouse()" we need this check implemented here because "underMouse()" + + // instead of "scrollbar->underMouse()" we need this check implemented here because "underMouse()" // does not work when the mouse enters the area without being moved if (scrollbarArea.contains(localMousePos)) { @@ -114,7 +114,7 @@ QtCodeArea::QtCodeArea( this->setMouseTracking(true); // MouseWheelOverScrollbarFilter is deleted by parent. - horizontalScrollBar()->installEventFilter(new MouseWheelOverScrollbarFilter(this)); + horizontalScrollBar()->installEventFilter(new MouseWheelOverScrollbarFilter(this)); } QtCodeArea::~QtCodeArea() @@ -289,7 +289,7 @@ void QtCodeArea::mouseReleaseEvent(QMouseEvent* event) { QTextCursor cursor = this->cursorForPosition(event->pos()); std::vector locationIds = findLocationIdsForPosition(cursor.position()); - if (locationIds.size()) + if (locationIds.size() && !m_fileWidget->getErrorMessages().size()) { MessageActivateTokenLocations(locationIds).dispatch(); } @@ -301,7 +301,7 @@ void QtCodeArea::mouseDoubleClickEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { - MessageShowFile(m_fileWidget->getFilePath().str(), m_startLineNumber, m_startLineNumber + blockCount() - 1).dispatch(); + MessageShowFile(m_fileWidget->getFilePath().str(), (m_fileWidget->getErrorMessages().size() > 0)).dispatch(); } } diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp index 83b0416d..444449e6 100644 --- a/src/app/qt/element/QtCodeFile.cpp +++ b/src/app/qt/element/QtCodeFile.cpp @@ -382,7 +382,7 @@ void QtCodeFile::clickedMaximizeButton() } else { - MessageShowFile(m_filePath, 0, 0).dispatch(); + MessageShowFile(m_filePath, (getErrorMessages().size() > 0)).dispatch(); } m_minimizeButton->setEnabled(true); @@ -449,7 +449,7 @@ void QtCodeFile::doUpdateTitleBar() m_title->setStyleSheet("background-image: url(data/gui/code_view/images/pattern.png);"); } else - { + { m_title->setStyleSheet(""); } } diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp index 299be014..4a1f7265 100644 --- a/src/app/qt/element/QtCodeSnippet.cpp +++ b/src/app/qt/element/QtCodeSnippet.cpp @@ -147,7 +147,7 @@ void QtCodeSnippet::clickedTitle() } else { - MessageShowFile(FilePath(m_titleString), 0, 0).dispatch(); + MessageShowFile(FilePath(m_titleString), (dynamic_cast(parent())->getErrorMessages().size() > 0)).dispatch(); } } diff --git a/src/app/qt/element/QtStatusBar.cpp b/src/app/qt/element/QtStatusBar.cpp index 309da332..944fc29c 100644 --- a/src/app/qt/element/QtStatusBar.cpp +++ b/src/app/qt/element/QtStatusBar.cpp @@ -2,6 +2,9 @@ #include +#include "qt/utility/utilityQt.h" +#include "utility/messaging/type/MessageShowErrors.h" + QtStatusBar::QtStatusBar() : m_text(this) { @@ -19,6 +22,17 @@ QtStatusBar::QtStatusBar() m_text.setText(""); addWidget(&m_text); + + m_errorButton.hide(); + m_errorButton.setFlat(true); + m_errorButton.setStyleSheet("QPushButton { color: #D00000; margin-right: 0; spacing: none; }"); + m_errorButton.setIcon(utility::colorizePixmap( + QPixmap("data/gui/statusbar_view/octagon.png"), + "#D00000" + ).scaledToHeight(10)); + addPermanentWidget(&m_errorButton); + + connect(&m_errorButton, SIGNAL(clicked()), this, SLOT(showErrors())); } QtStatusBar::~QtStatusBar() @@ -29,7 +43,7 @@ void QtStatusBar::setText(const std::string& text, bool isError, bool showLoader { if (isError) { - m_text.setStyleSheet("QLabel { color: #E00000 }"); + m_text.setStyleSheet("QLabel { color: #D00000 }"); } else { @@ -47,3 +61,21 @@ void QtStatusBar::setText(const std::string& text, bool isError, bool showLoader m_text.setText(text.c_str()); } + +void QtStatusBar::setErrorCount(size_t count) +{ + if (count > 0) + { + m_errorButton.setText(QString::number(count) + " error(s)"); + m_errorButton.show(); + } + else + { + m_errorButton.hide(); + } +} + +void QtStatusBar::showErrors() +{ + MessageShowErrors().dispatch(); +} diff --git a/src/app/qt/element/QtStatusBar.h b/src/app/qt/element/QtStatusBar.h index b8d81240..edbcafeb 100644 --- a/src/app/qt/element/QtStatusBar.h +++ b/src/app/qt/element/QtStatusBar.h @@ -2,21 +2,30 @@ #define QT_STATUS_BAR_H #include -#include + +#include #include +#include class QtStatusBar : public QStatusBar { + Q_OBJECT + public: QtStatusBar(void); - ~QtStatusBar(void); + virtual ~QtStatusBar(void); void setText(const std::string& text, bool isError, bool showLoader); + void setErrorCount(size_t count); + +private slots: + void showErrors(); private: QLabel m_text; QLabel m_loader; + QPushButton m_errorButton; }; #endif // QT_STATUS_BAR_H diff --git a/src/app/qt/view/QtStatusBarView.cpp b/src/app/qt/view/QtStatusBarView.cpp index 38ca7585..89e0d45d 100644 --- a/src/app/qt/view/QtStatusBarView.cpp +++ b/src/app/qt/view/QtStatusBarView.cpp @@ -1,6 +1,7 @@ #include "qt/view/QtStatusBarView.h" #include + #include "qt/view/QtMainView.h" #include "qt/view/QtViewWidgetWrapper.h" @@ -8,12 +9,14 @@ QtStatusBarView::QtStatusBarView(ViewLayout* viewLayout) : StatusBarView(viewLayout) , m_showMessageFunctor(std::bind( &QtStatusBarView::doShowMessage, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) + , m_setErrorCountFunctor(std::bind(&QtStatusBarView::doSetErrorCount, this, std::placeholders::_1)) { - QtMainView* mw = static_cast(viewLayout); m_widget = std::make_shared(); + m_widget->show(); + + QtMainView* mw = static_cast(viewLayout); QStatusBar* sb = static_cast(m_widget.get()); mw->setStatusBar(sb); - m_widget->show(); } QtStatusBarView::~QtStatusBarView() @@ -32,12 +35,22 @@ void QtStatusBarView::refreshView() { } +void QtStatusBarView::showMessage(const std::string& message, bool isError, bool showLoader) +{ + m_showMessageFunctor(message, isError, showLoader); +} + +void QtStatusBarView::setErrorCount(size_t count) +{ + m_setErrorCountFunctor(count); +} + void QtStatusBarView::doShowMessage(const std::string& message, bool isError, bool showLoader) { m_widget->setText(message, isError, showLoader); } -void QtStatusBarView::showMessage(const std::string& message, bool isError, bool showLoader) +void QtStatusBarView::doSetErrorCount(size_t count) { - m_showMessageFunctor(message, isError, showLoader); + m_widget->setErrorCount(count); } diff --git a/src/app/qt/view/QtStatusBarView.h b/src/app/qt/view/QtStatusBarView.h index b5b1bf66..da9ada35 100644 --- a/src/app/qt/view/QtStatusBarView.h +++ b/src/app/qt/view/QtStatusBarView.h @@ -8,7 +8,8 @@ #include "qt/element/QtStatusBar.h" #include "qt/utility/QtThreadedFunctor.h" -class QtStatusBarView : public StatusBarView +class QtStatusBarView + : public StatusBarView { public: QtStatusBarView(ViewLayout* viewLayout); @@ -21,12 +22,16 @@ public: // StatusBar view implementation virtual void showMessage(const std::string& message, bool isError, bool showLoader); + virtual void setErrorCount(size_t count); private: void doShowMessage(const std::string& message, bool isError, bool showLoader); - std::shared_ptr m_widget; + void doSetErrorCount(size_t count); QtThreadedFunctor m_showMessageFunctor; + QtThreadedFunctor m_setErrorCountFunctor; + + std::shared_ptr m_widget; }; #endif // !QT_STATUS_BAR_VIEW_H diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index bfceeb67..bca540f3 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -3,6 +3,7 @@ #include "utility/logging/logging.h" #include "utility/messaging/MessageQueue.h" #include "utility/messaging/type/MessageActivateNodes.h" +#include "utility/messaging/type/MessageShowErrors.h" #include "utility/messaging/type/MessageStatus.h" #include "utility/scheduling/TaskScheduler.h" #include "utility/Version.h" @@ -115,6 +116,10 @@ void Application::handleMessage(MessageFinishedParsing* message) { MessageRefresh().refreshUiOnly().dispatch(); } + else + { + MessageShowErrors().dispatch(); + } } void Application::handleMessage(MessageLoadProject* message) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 1f0320fc..8f4fa8b6 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -265,6 +265,7 @@ add_files( utility/messaging/type/MessageSaveProject.h utility/messaging/type/MessageSearch.h utility/messaging/type/MessageSearchAutocomplete.h + utility/messaging/type/MessageShowErrors.h utility/messaging/type/MessageShowFile.h utility/messaging/type/MessageShowScope.h utility/messaging/type/MessageShowSnippets.h diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index 2beedf13..0daf3b6d 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -78,7 +78,7 @@ void Project::loadStorage() { m_storage->startParsing(); m_storage->finishParsing(); - MessageFinishedParsing(0, 0, 0, 0).dispatch(); + MessageFinishedParsing(0, 0, 0, m_storage->getErrorCount()).dispatch(); } else { diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index d5d262d9..f4038eb4 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -78,30 +78,6 @@ void CodeController::handleMessage(MessageActivateTokens* message) } } -void CodeController::handleMessage(MessageFinishedParsing* message) -{ - if (message->errorCount > 0) - { - std::vector errorMessages; - TokenLocationCollection errorCollection = m_storageAccess->getErrorTokenLocations(&errorMessages); - - std::vector snippets; - - errorCollection.forEachTokenLocationFile( - [&](std::shared_ptr file) -> void - { - std::vector fileSnippets = getSnippetsForFile(file); - snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end()); - } - ); - - CodeView* view = getView(); - view->setActiveTokenIds(std::vector()); - view->setErrorMessages(errorMessages); - view->showCodeSnippets(snippets); - } -} - void CodeController::handleMessage(MessageFocusIn* message) { getView()->focusToken(message->tokenId); @@ -112,17 +88,49 @@ void CodeController::handleMessage(MessageFocusOut* message) getView()->defocusToken(); } +void CodeController::handleMessage(MessageShowErrors* message) +{ + std::vector errorMessages; + TokenLocationCollection errorCollection = m_storageAccess->getErrorTokenLocations(&errorMessages); + + std::vector snippets; + + errorCollection.forEachTokenLocationFile( + [&](std::shared_ptr file) -> void + { + std::vector fileSnippets = getSnippetsForFile(file); + snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end()); + } + ); + + CodeView* view = getView(); + view->setActiveTokenIds(std::vector()); + view->setErrorMessages(errorMessages); + view->showCodeSnippets(snippets); +} + void CodeController::handleMessage(MessageShowFile* message) { CodeView::CodeSnippetParams params; - params.startLineNumber = message->startLineNumber; - params.endLineNumber = message->endLineNumber; + params.startLineNumber = 0; + params.endLineNumber = 0; std::shared_ptr textAccess = m_storageAccess->getFileContent(message->filePath); params.code = textAccess->getText(); params.modificationTime = m_storageAccess->getFileModificationTime(message->filePath); - params.locationFile = m_storageAccess->getTokenLocationsForFile(message->filePath.str()); + + if (message->showErrors) + { + std::vector errorMessages; + TokenLocationCollection errorCollection = m_storageAccess->getErrorTokenLocations(&errorMessages); + params.locationFile = std::make_shared(*errorCollection.findTokenLocationFileByPath(message->filePath)); + params.locationFile->isWholeCopy = true; + } + else + { + params.locationFile = m_storageAccess->getTokenLocationsForFile(message->filePath.str()); + } getView()->showCodeFile(params); } diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index 11256067..f4cf3191 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -6,9 +6,9 @@ #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateTokens.h" -#include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageFocusIn.h" #include "utility/messaging/type/MessageFocusOut.h" +#include "utility/messaging/type/MessageShowErrors.h" #include "utility/messaging/type/MessageShowFile.h" #include "utility/messaging/type/MessageShowScope.h" #include "utility/messaging/type/MessageShowSnippets.h" @@ -25,9 +25,9 @@ class TokenLocationFile; class CodeController : public Controller , public MessageListener - , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -40,9 +40,9 @@ private: static const uint s_lineRadius; virtual void handleMessage(MessageActivateTokens* message); - virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageFocusIn* message); virtual void handleMessage(MessageFocusOut* message); + virtual void handleMessage(MessageShowErrors* message); virtual void handleMessage(MessageShowFile* message); virtual void handleMessage(MessageShowScope* message); virtual void handleMessage(MessageShowSnippets* message); diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 475f91d6..3f0f227a 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -134,6 +134,11 @@ void GraphController::handleMessage(MessageGraphNodeMove* message) } } +void GraphController::handleMessage(MessageShowErrors* message) +{ + clear(); +} + GraphView* GraphController::getView() const { return Controller::getView(); diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 357cb0f0..232f156f 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -11,6 +11,7 @@ #include "utility/messaging/type/MessageGraphNodeBundleSplit.h" #include "utility/messaging/type/MessageGraphNodeExpand.h" #include "utility/messaging/type/MessageGraphNodeMove.h" +#include "utility/messaging/type/MessageShowErrors.h" #include "component/controller/Controller.h" #include "component/view/GraphView.h" @@ -32,6 +33,7 @@ class GraphController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener { public: GraphController(StorageAccess* storageAccess); @@ -45,6 +47,7 @@ private: virtual void handleMessage(MessageGraphNodeBundleSplit* message); virtual void handleMessage(MessageGraphNodeExpand* message); virtual void handleMessage(MessageGraphNodeMove* message); + virtual void handleMessage(MessageShowErrors* message); GraphView* getView() const; diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index dc9feaf4..290cd2d4 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -31,6 +31,11 @@ void SearchController::handleMessage(MessageSearchAutocomplete* message) getView()->setAutocompletionList(m_storageAccess->getAutocompletionMatches(message->query)); } +void SearchController::handleMessage(MessageShowErrors* message) +{ + getView()->setMatches(std::vector()); +} + SearchView* SearchController::getView() { return Controller::getView(); diff --git a/src/lib/component/controller/SearchController.h b/src/lib/component/controller/SearchController.h index d0075c4d..e47d90f4 100644 --- a/src/lib/component/controller/SearchController.h +++ b/src/lib/component/controller/SearchController.h @@ -6,6 +6,7 @@ #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageFind.h" #include "utility/messaging/type/MessageSearchAutocomplete.h" +#include "utility/messaging/type/MessageShowErrors.h" class StorageAccess; class SearchView; @@ -15,6 +16,7 @@ class SearchController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener { public: SearchController(StorageAccess* storageAccess); @@ -24,6 +26,7 @@ private: virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageFind* message); virtual void handleMessage(MessageSearchAutocomplete* message); + virtual void handleMessage(MessageShowErrors* message); SearchView* getView(); diff --git a/src/lib/component/controller/StatusBarController.cpp b/src/lib/component/controller/StatusBarController.cpp index 9bbb7ea2..cadcba3e 100644 --- a/src/lib/component/controller/StatusBarController.cpp +++ b/src/lib/component/controller/StatusBarController.cpp @@ -17,6 +17,11 @@ StatusBarView* StatusBarController::getView() return Controller::getView(); } +void StatusBarController::handleMessage(MessageFinishedParsing* message) +{ + getView()->setErrorCount(message->errorCount); +} + void StatusBarController::handleMessage(MessageStatus* message) { setStatus(message->status, message->isError, message->showLoader); diff --git a/src/lib/component/controller/StatusBarController.h b/src/lib/component/controller/StatusBarController.h index d0ea8b06..5025ba5d 100644 --- a/src/lib/component/controller/StatusBarController.h +++ b/src/lib/component/controller/StatusBarController.h @@ -6,12 +6,14 @@ #include "component/controller/Controller.h" #include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageStatus.h" class StatusBarView; class StatusBarController : public Controller + , public MessageListener , public MessageListener { public: @@ -21,6 +23,7 @@ public: StatusBarView* getView(); private: + virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageStatus* message); void setStatus(const std::string& status, bool isError, bool showLoader); diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index 58bece15..d52d222d 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -196,6 +196,17 @@ void UndoRedoController::handleMessage(MessageSearch* message) processCommand(command); } +void UndoRedoController::handleMessage(MessageShowErrors* message) +{ + if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType()) + { + return; + } + + Command command(std::make_shared(*message), 0); + processCommand(command); +} + void UndoRedoController::handleMessage(MessageShowFile* message) { if (m_lastCommand.message && m_lastCommand.message->getType() == message->getType() && diff --git a/src/lib/component/controller/UndoRedoController.h b/src/lib/component/controller/UndoRedoController.h index 2de8af22..c545cf29 100644 --- a/src/lib/component/controller/UndoRedoController.h +++ b/src/lib/component/controller/UndoRedoController.h @@ -16,6 +16,7 @@ #include "utility/messaging/type/MessageRedo.h" #include "utility/messaging/type/MessageRefresh.h" #include "utility/messaging/type/MessageSearch.h" +#include "utility/messaging/type/MessageShowErrors.h" #include "utility/messaging/type/MessageShowFile.h" #include "utility/messaging/type/MessageShowScope.h" #include "utility/messaging/type/MessageUndo.h" @@ -39,6 +40,7 @@ class UndoRedoController , public MessageListener , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -69,6 +71,7 @@ private: virtual void handleMessage(MessageRedo* message); virtual void handleMessage(MessageRefresh* message); virtual void handleMessage(MessageSearch* message); + virtual void handleMessage(MessageShowErrors* message); virtual void handleMessage(MessageShowFile* message); virtual void handleMessage(MessageShowScope* message); virtual void handleMessage(MessageUndo* message); diff --git a/src/lib/component/view/StatusBarView.h b/src/lib/component/view/StatusBarView.h index 5424f374..7c2140c0 100644 --- a/src/lib/component/view/StatusBarView.h +++ b/src/lib/component/view/StatusBarView.h @@ -13,6 +13,7 @@ public: virtual std::string getName() const; virtual void showMessage(const std::string& message, bool isError, bool showLoader) = 0; + virtual void setErrorCount(size_t count) = 0; protected: StatusBarController* getController(); diff --git a/src/lib/data/SqliteStorage.cpp b/src/lib/data/SqliteStorage.cpp index 57c9c8ba..175c61af 100644 --- a/src/lib/data/SqliteStorage.cpp +++ b/src/lib/data/SqliteStorage.cpp @@ -164,6 +164,35 @@ Id SqliteStorage::addSignature(Id nodeId, const std::string& signature) return m_database.lastRowId(); } +Id SqliteStorage::addError(const std::string& message, const std::string& filePath, uint lineNumber, uint columnNumber) +{ + std::string sanitizedMessage = utility::replace(message, "'", "''"); + + // check for duplicate + CppSQLite3Query q = m_database.execQuery(( + "SELECT * FROM error WHERE " + "message == '" + sanitizedMessage + "' AND " + "file_path == '" + filePath + "' AND " + "line_number == " + std::to_string(lineNumber) + " AND " + "column_number == " + std::to_string(columnNumber) + ";" + ).c_str()); + + if (!q.eof()) + { + return q.getIntField(0, -1); + } + + std::cout << ("INSERT INTO error(message, file_path, line_number, column_number) " + "VALUES ('" + sanitizedMessage + "', '" + filePath + "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");") << std::endl; + + m_database.execDML(( + "INSERT INTO error(message, file_path, line_number, column_number) " + "VALUES ('" + sanitizedMessage + "', '" + filePath + "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");" + ).c_str()); + + return m_database.lastRowId(); +} + void SqliteStorage::removeElement(Id id) { m_database.execDML(( @@ -231,6 +260,13 @@ void SqliteStorage::removeUnusedNameHierarchyElements() ); } +void SqliteStorage::removeErrorsInFiles(const std::vector& filePaths) +{ + m_database.execDML(( + "DELETE FROM error WHERE file_path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "');" + ).c_str()); +} + StorageNode SqliteStorage::getFirstNode() const { std::vector nodes = getAllNodes("LIMIT 1"); @@ -691,6 +727,28 @@ Id SqliteStorage::getNodeIdBySignature(const std::string& signature) const return 0; } +std::vector SqliteStorage::getAllErrors() const +{ + CppSQLite3Query q = m_database.execQuery( + "SELECT message, file_path, line_number, column_number FROM error;" + ); + + std::vector errors; + while (!q.eof()) + { + const std::string message = q.getStringField(0, ""); + const std::string filePath = q.getStringField(1, ""); + const uint lineNumber = q.getIntField(2, 0); + const uint columnNumber = q.getIntField(3, 0); + + errors.push_back(StorageError(message, filePath, lineNumber, columnNumber)); + + q.nextRow(); + } + + return errors; +} + int SqliteStorage::getNodeCount() const { return m_database.execScalar("SELECT COUNT(*) FROM node;"); @@ -718,6 +776,7 @@ int SqliteStorage::getSourceLocationCount() const void SqliteStorage::clearTables() { + m_database.execDML("DROP TABLE IF EXISTS main.error;"); m_database.execDML("DROP TABLE IF EXISTS main.function_signature;"); m_database.execDML("DROP TABLE IF EXISTS main.component_access;"); m_database.execDML("DROP TABLE IF EXISTS main.source_location;"); @@ -818,6 +877,16 @@ void SqliteStorage::setupTables() "PRIMARY KEY(id), " "FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);" ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS error(" + "id INTEGER NOT NULL, " + "message TEXT, " + "file_path TEXT, " + "line_number INTEGER, " + "column_number INTEGER, " + "PRIMARY KEY(id));" + ); } bool SqliteStorage::hasTable(const std::string& tableName) const diff --git a/src/lib/data/SqliteStorage.h b/src/lib/data/SqliteStorage.h index 51c608f6..b6a1368b 100644 --- a/src/lib/data/SqliteStorage.h +++ b/src/lib/data/SqliteStorage.h @@ -42,6 +42,8 @@ public: Id addComponentAccess(Id memberEdgeId, int type); Id addSignature(Id nodeId, const std::string& signature); + Id addError(const std::string& message, const std::string& filePath, uint lineNumber, uint columnNumber); + void removeElement(Id id); void removeNameHierarchyElement(Id id); void removeElementsWithLocationInFiles(const std::vector& fileIds); @@ -49,6 +51,8 @@ public: void removeFiles(const std::vector& fileIds); void removeUnusedNameHierarchyElements(); + void removeErrorsInFiles(const std::vector& filePaths); + StorageNode getFirstNode() const; std::vector getAllNodes() const; @@ -101,6 +105,8 @@ public: std::vector getComponentAccessByMemberEdgeIds(const std::vector& memberEdgeIds) const; Id getNodeIdBySignature(const std::string& signature) const; + std::vector getAllErrors() const; + int getNodeCount() const; int getEdgeCount() const; int getFileCount() const; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 1aa3cdd4..93d0da39 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -41,9 +41,6 @@ void Storage::clear() m_sqliteStorage.clear(); clearCaches(); - - m_errorMessages.clear(); - m_errorLocationCollection.clear(); } void Storage::clearCaches() @@ -96,6 +93,8 @@ void Storage::clearFileElements(const std::vector& filePaths) { m_sqliteStorage.removeElementsWithLocationInFiles(fileNodeIds); m_sqliteStorage.removeFiles(fileNodeIds); + + m_sqliteStorage.removeErrorsInFiles(filePaths); } } @@ -183,41 +182,12 @@ void Storage::onError(const ParseLocation& location, const std::string& message) return; } - bool duplicate = false; - TokenLocationFile* file = m_errorLocationCollection.findTokenLocationFileByPath(location.filePath); - - if (file) - { - file->forEachStartTokenLocation( - [&](TokenLocation* loc) - { - if (loc->getLineNumber() == location.startLineNumber && - loc->getColumnNumber() == location.startColumnNumber && - m_errorMessages[loc->getTokenId()] == message) - { - duplicate = true; - } - } - ); - } - - if (!duplicate) - { - Id errorId = m_errorMessages.size(); - - m_errorLocationCollection.addTokenLocation( - getErrorCount(), errorId, location.filePath, - location.startLineNumber, location.startColumnNumber, - location.endLineNumber, location.endColumnNumber - ); - - m_errorMessages.push_back(message); - } + m_sqliteStorage.addError(message, location.filePath.str(), location.startLineNumber, location.startColumnNumber); } size_t Storage::getErrorCount() const { - return m_errorLocationCollection.getTokenLocationCount(); + return m_sqliteStorage.getAllErrors().size(); } Id Storage::onTypedefParsed( @@ -1176,8 +1146,18 @@ std::shared_ptr Storage::getTokenLocationsForLinesInFile( TokenLocationCollection Storage::getErrorTokenLocations(std::vector* errorMessages) const { - errorMessages->insert(errorMessages->begin(), m_errorMessages.begin(), m_errorMessages.end()); - return m_errorLocationCollection; + TokenLocationCollection errorCollection; + + std::vector errors = m_sqliteStorage.getAllErrors(); + for (size_t i = 0; i < errors.size(); i++) + { + const StorageError& error = errors[i]; + errorCollection.addTokenLocation( + i, i, error.filePath, error.lineNumber, error.columnNumber, error.lineNumber, error.columnNumber); + errorMessages->push_back(error.message); + } + + return errorCollection; } std::shared_ptr Storage::getTokenLocationOfParentScope(const TokenLocation* child) const diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index c59b24f3..58ab0f5b 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -203,9 +203,6 @@ private: mutable std::map m_fileNodeIds; HierarchyCache m_hierarchyCache; - TokenLocationCollection m_errorLocationCollection; - std::vector m_errorMessages; - mutable SearchResults m_cachedResults; mutable std::string m_cachedQuery; }; diff --git a/src/lib/data/StorageTypes.h b/src/lib/data/StorageTypes.h index 621f9d9d..2c68453d 100644 --- a/src/lib/data/StorageTypes.h +++ b/src/lib/data/StorageTypes.h @@ -80,4 +80,19 @@ struct StorageComponentAccess int type; }; +struct StorageError +{ + StorageError(const std::string& message, const std::string& filePath, uint lineNumber, uint columnNumber) + : message(message) + , filePath(filePath) + , lineNumber(lineNumber) + , columnNumber(columnNumber) + {} + + std::string message; + std::string filePath; + uint lineNumber; + uint columnNumber; +}; + #endif // STORAGE_TYPES_H diff --git a/src/lib/utility/messaging/type/MessageShowErrors.h b/src/lib/utility/messaging/type/MessageShowErrors.h new file mode 100644 index 00000000..2761f374 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageShowErrors.h @@ -0,0 +1,20 @@ +#ifndef MESSAGE_SHOW_ERRORS_H +#define MESSAGE_SHOW_ERRORS_H + +#include "utility/messaging/Message.h" + +class MessageShowErrors + : public Message +{ +public: + MessageShowErrors() + { + } + + static const std::string getStaticType() + { + return "MessageShowErrors"; + } +}; + +#endif // MESSAGE_SHOW_ERRORS_H diff --git a/src/lib/utility/messaging/type/MessageShowFile.h b/src/lib/utility/messaging/type/MessageShowFile.h index f296b266..ec63acd2 100644 --- a/src/lib/utility/messaging/type/MessageShowFile.h +++ b/src/lib/utility/messaging/type/MessageShowFile.h @@ -9,10 +9,9 @@ class MessageShowFile : public Message { public: - MessageShowFile(const FilePath& filePath, uint startLineNumber, uint endLineNumber) + MessageShowFile(const FilePath& filePath, bool showErrors) : filePath(filePath) - , startLineNumber(startLineNumber) - , endLineNumber(endLineNumber) + , showErrors(showErrors) { } @@ -22,8 +21,7 @@ public: } const FilePath filePath; - const uint startLineNumber; - const uint endLineNumber; + const bool showErrors; }; #endif // MESSAGE_SHOW_FILE_H diff --git a/src/lib/utility/utility.h b/src/lib/utility/utility.h index df8dfb8f..810d84e6 100644 --- a/src/lib/utility/utility.h +++ b/src/lib/utility/utility.h @@ -7,6 +7,7 @@ #include "boost/date_time/posix_time/posix_time.hpp" +#include "utility/file/FilePath.h" #include "utility/math/Vector2.h" #include "utility/TimePoint.h" @@ -81,4 +82,15 @@ std::vector utility::toStrings(const std::vector& d) return v; } +template<> +inline std::vector utility::toStrings(const std::vector& d) +{ + std::vector v; + for (const FilePath& t : d) + { + v.push_back(t.str()); + } + return v; +} + #endif // UTILITY_H