diff --git a/bin/app/data/src/test/main.cpp b/bin/app/data/src/test/main.cpp index c37743b7..b1f839a9 100644 --- a/bin/app/data/src/test/main.cpp +++ b/bin/app/data/src/test/main.cpp @@ -14,6 +14,9 @@ int main() int a = sum(1, 2); int b = diff(a, 3); int c = a * b; + + int x = y; + return 0; } diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp index 8625b15d..a0b78083 100644 --- a/src/app/qt/element/QtCodeFile.cpp +++ b/src/app/qt/element/QtCodeFile.cpp @@ -3,13 +3,14 @@ #include #include +#include "qt/element/QtCodeFileList.h" #include "qt/element/QtCodeSnippet.h" #include "utility/FileSystem.h" -QtCodeFile::QtCodeFile(const std::string& filePath, QWidget *parent) +QtCodeFile::QtCodeFile(const std::string& filePath, QtCodeFileList* parent) : QWidget(parent) + , m_parent(parent) , m_filePath(filePath) - , m_showMaximizeButton(true) { setObjectName("code_file"); @@ -31,21 +32,35 @@ QtCodeFile::~QtCodeFile() { } +const std::string& QtCodeFile::getFilePath() const +{ + return m_filePath; +} + std::string QtCodeFile::getFileName() const { return FileSystem::fileName(m_filePath); } +const std::vector& QtCodeFile::getActiveTokenIds() const +{ + return m_parent->getActiveTokenIds(); +} + +const std::vector& QtCodeFile::getErrorMessages() const +{ + return m_parent->getErrorMessages(); +} + void QtCodeFile::addCodeSnippet( uint startLineNumber, const std::string& code, - const TokenLocationFile& locationFile, - const std::vector& activeTokenIds + const TokenLocationFile& locationFile ){ std::shared_ptr snippet( - new QtCodeSnippet(startLineNumber, code, locationFile, activeTokenIds, this)); + new QtCodeSnippet(startLineNumber, code, locationFile, this)); - if (m_showMaximizeButton) + if (m_parent->getShowMaximizeButton()) { snippet->addMaximizeButton(); } @@ -65,15 +80,10 @@ void QtCodeFile::addCodeSnippet( } } -void QtCodeFile::setActiveTokenIds(const std::vector& activeTokenIds) +void QtCodeFile::update() { for (std::shared_ptr snippet : m_snippets) { - snippet->setActiveTokenIds(activeTokenIds); + snippet->update(); } } - -void QtCodeFile::setShowMaximizeButton(bool show) -{ - m_showMaximizeButton = show; -} diff --git a/src/app/qt/element/QtCodeFile.h b/src/app/qt/element/QtCodeFile.h index c850c6aa..6efe1e22 100644 --- a/src/app/qt/element/QtCodeFile.h +++ b/src/app/qt/element/QtCodeFile.h @@ -9,31 +9,34 @@ #include "utility/types.h" +class QtCodeFileList; class QtCodeSnippet; class TokenLocationFile; class QtCodeFile : public QWidget { public: - QtCodeFile(const std::string& filePath, QWidget *parent = 0); + QtCodeFile(const std::string& filePath, QtCodeFileList* parent); virtual ~QtCodeFile(); + const std::string& getFilePath() const; std::string getFileName() const; + const std::vector& getActiveTokenIds() const; + const std::vector& getErrorMessages() const; void addCodeSnippet( uint startLineNumber, const std::string& code, - const TokenLocationFile& locationFile, - const std::vector& activeTokenIds + const TokenLocationFile& locationFile ); - void setActiveTokenIds(const std::vector& activeTokenIds); - void setShowMaximizeButton(bool show); + void update(); private: - std::vector > m_snippets; + QtCodeFileList* m_parent; + + std::vector> m_snippets; const std::string m_filePath; - bool m_showMaximizeButton; }; #endif // QT_CODE_FILE_H diff --git a/src/app/qt/element/QtCodeFileList.cpp b/src/app/qt/element/QtCodeFileList.cpp index ed83f4df..30dc853d 100644 --- a/src/app/qt/element/QtCodeFileList.cpp +++ b/src/app/qt/element/QtCodeFileList.cpp @@ -36,8 +36,7 @@ QSize QtCodeFileList::sizeHint() const void QtCodeFileList::addCodeSnippet( uint startLineNumber, const std::string& code, - const TokenLocationFile& locationFile, - const std::vector& activeTokenIds + const TokenLocationFile& locationFile ){ std::string fileName = FileSystem::fileName(locationFile.getFilePath()); QtCodeFile* file = nullptr; @@ -58,11 +57,9 @@ void QtCodeFileList::addCodeSnippet( file = filePtr.get(); m_frame->layout()->addWidget(file); - - file->setShowMaximizeButton(m_showMaximizeButton); } - file->addCodeSnippet(startLineNumber, code, locationFile, activeTokenIds); + file->addCodeSnippet(startLineNumber, code, locationFile); } void QtCodeFileList::clearCodeSnippets() @@ -70,15 +67,43 @@ void QtCodeFileList::clearCodeSnippets() m_files.clear(); } +const std::vector& QtCodeFileList::getActiveTokenIds() const +{ + return m_activeTokenIds; +} + void QtCodeFileList::setActiveTokenIds(const std::vector& activeTokenIds) { - for (std::shared_ptr file: m_files) - { - file->setActiveTokenIds(activeTokenIds); - } + m_activeTokenIds = activeTokenIds; + updateFiles(); +} + +const std::vector& QtCodeFileList::getErrorMessages() const +{ + return m_errorMessages; +} + +void QtCodeFileList::setErrorMessages(const std::vector& errorMessages) +{ + m_errorMessages = errorMessages; + updateFiles(); +} + +bool QtCodeFileList::getShowMaximizeButton() const +{ + return m_showMaximizeButton; } void QtCodeFileList::setShowMaximizeButton(bool show) { m_showMaximizeButton = show; + updateFiles(); +} + +void QtCodeFileList::updateFiles() +{ + for (std::shared_ptr file: m_files) + { + file->update(); + } } diff --git a/src/app/qt/element/QtCodeFileList.h b/src/app/qt/element/QtCodeFileList.h index 278bd5e7..806b8c49 100644 --- a/src/app/qt/element/QtCodeFileList.h +++ b/src/app/qt/element/QtCodeFileList.h @@ -25,19 +25,28 @@ public: void addCodeSnippet( uint startLineNumber, const std::string& code, - const TokenLocationFile& locationFile, - const std::vector& activeTokenIds + const TokenLocationFile& locationFile ); void clearCodeSnippets(); + const std::vector& getActiveTokenIds() const; void setActiveTokenIds(const std::vector& activeTokenIds); + + const std::vector& getErrorMessages() const; + void setErrorMessages(const std::vector& errorMessages); + + bool getShowMaximizeButton() const; void setShowMaximizeButton(bool show); private: - std::shared_ptr m_frame; - std::vector > m_files; + void updateFiles(); + std::shared_ptr m_frame; + std::vector> m_files; + + std::vector m_activeTokenIds; + std::vector m_errorMessages; bool m_showMaximizeButton; }; diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp index 43f6a05e..d9e39149 100644 --- a/src/app/qt/element/QtCodeSnippet.cpp +++ b/src/app/qt/element/QtCodeSnippet.cpp @@ -4,10 +4,12 @@ #include #include #include +#include #include "ApplicationSettings.h" #include "data/location/TokenLocation.h" #include "data/location/TokenLocationFile.h" +#include "qt/element/QtCodeFile.h" #include "qt/utility/QtHighlighter.h" #include "utility/messaging/type/MessageActivateTokenLocation.h" #include "utility/messaging/type/MessageShowFile.h" @@ -38,14 +40,13 @@ QtCodeSnippet::QtCodeSnippet( uint startLineNumber, const std::string& code, const TokenLocationFile& locationFile, - const std::vector& activeTokenIds, - QWidget *parent + QtCodeFile* parent ) : QPlainTextEdit(parent) + , m_parent(parent) , m_maximizeButton(nullptr) , m_startLineNumber(startLineNumber) - , m_filePath(locationFile.getFilePath()) - , m_activeTokenIds(activeTokenIds) + , m_hoveredAnnotation(nullptr) , m_digits(0) { setObjectName("code_snippet"); @@ -73,8 +74,9 @@ QtCodeSnippet::QtCodeSnippet( connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); - connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(clickedTokenLocation())); connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection())); + + this->setMouseTracking(true); } QtCodeSnippet::~QtCodeSnippet() @@ -154,9 +156,8 @@ void QtCodeSnippet::updateLineNumberAreaWidthForDigits(int digits) updateLineNumberAreaWidth(0); } -void QtCodeSnippet::setActiveTokenIds(const std::vector& activeTokenIds) +void QtCodeSnippet::update() { - m_activeTokenIds = activeTokenIds; annotateText(); } @@ -192,14 +193,52 @@ void QtCodeSnippet::leaveEvent(QEvent* event) } } +void QtCodeSnippet::mouseReleaseEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) + { + QTextCursor cursor = this->cursorForPosition(event->pos()); + const Annotation* annotation = findAnnotationForPosition(cursor.position()); + + if (annotation) + { + MessageActivateTokenLocation(annotation->locationId).dispatch(); + } + } +} + void QtCodeSnippet::mouseDoubleClickEvent(QMouseEvent* event) { - if (m_maximizeButton) + if (event->button() == Qt::LeftButton && m_maximizeButton) { clickedMaximizeButton(); } } +void QtCodeSnippet::mouseMoveEvent(QMouseEvent* event) +{ + QTextCursor cursor = this->cursorForPosition(event->pos()); + const Annotation* annotation = findAnnotationForPosition(cursor.position()); + + if (annotation != nullptr ? annotation != m_hoveredAnnotation && !annotation->isScope : m_hoveredAnnotation != nullptr) + { + m_hoveredAnnotation = annotation; + + const std::vector& errorMessages = m_parent->getErrorMessages(); + + if (annotation && errorMessages.size() > annotation->tokenId) + { + QToolTip::showText(event->globalPos(), QString::fromStdString(m_parent->getErrorMessages()[annotation->tokenId])); + } + else + { + QToolTip::hideText(); + } + + annotateText(); + } +} + void QtCodeSnippet::updateLineNumberAreaWidth(int /* newBlockCount */) { setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); @@ -222,34 +261,9 @@ void QtCodeSnippet::updateLineNumberArea(const QRect &rect, int dy) } } -void QtCodeSnippet::clickedTokenLocation() -{ - int clickPosition = textCursor().position(); - int diff = endTextEditPosition() + 1; - Id locationId = 0; - - for (Annotation annotation : m_annotations) - { - if (clickPosition >= annotation.start && clickPosition <= annotation.end) - { - int d = annotation.end - annotation.start; - if (d < diff) - { - diff = d; - locationId = annotation.locationId; - } - } - } - - if (locationId) - { - MessageActivateTokenLocation(locationId).dispatch(); - } -} - void QtCodeSnippet::clickedMaximizeButton() { - MessageShowFile(m_filePath, m_startLineNumber, m_startLineNumber + document()->blockCount() - 1).dispatch(); + MessageShowFile(m_parent->getFilePath(), m_startLineNumber, m_startLineNumber + blockCount() - 1).dispatch(); } void QtCodeSnippet::clearSelection() @@ -259,12 +273,33 @@ void QtCodeSnippet::clearSelection() setTextCursor(cursor); } +const QtCodeSnippet::Annotation* QtCodeSnippet::findAnnotationForPosition(int pos) const +{ + const Annotation* annotationPtr = nullptr; + int diff = endTextEditPosition() + 1; + + for (const Annotation& annotation : m_annotations) + { + if (pos >= annotation.start && pos <= annotation.end) + { + int d = annotation.end - annotation.start; + if (d < diff) + { + diff = d; + annotationPtr = &annotation; + } + } + } + + return annotationPtr; +} + void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile) { locationFile.forEachTokenLocation( [&](TokenLocation* location) { - if (location->isEndTokenLocation() && location->getStartTokenLocation()) + if (!locationBelongsToSnippet(location)) { return; } @@ -301,14 +336,27 @@ void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile) void QtCodeSnippet::annotateText() { Colori color; - const std::vector& ids = m_activeTokenIds; + const std::vector& ids = m_parent->getActiveTokenIds(); + const std::vector& errorMessages = m_parent->getErrorMessages(); QList extraSelections; for (const Annotation& annotation: m_annotations) { bool isActive = std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end(); - if (isActive) + if (&annotation == m_hoveredAnnotation && errorMessages.size()) + { + color = Colori(255, 0, 0, 128); + } + else if (&annotation == m_hoveredAnnotation) + { + color = ApplicationSettings::getInstance()->getCodeActiveLinkColor(); + } + else if (errorMessages.size()) + { + color = Colori(255, 0, 0, 255); + } + else if (isActive) { color = ApplicationSettings::getInstance()->getCodeActiveLinkColor(); } @@ -335,6 +383,43 @@ void QtCodeSnippet::annotateText() setExtraSelections(extraSelections); } +bool QtCodeSnippet::locationBelongsToSnippet(TokenLocation* location) const +{ + uint lineNumber = location->getLineNumber(); + + if (location->isEndTokenLocation()) + { + if (location->getStartTokenLocation() || + lineNumber < m_startLineNumber || lineNumber >= m_startLineNumber + blockCount()) + { + return false; + } + else + { + return true; + } + } + + if (lineNumber >= m_startLineNumber + blockCount()) + { + return false; + } + + if (lineNumber >= m_startLineNumber) + { + return true; + } + + TokenLocation* endLocation = location->getEndTokenLocation(); + + if (endLocation && endLocation->getLineNumber() < m_startLineNumber) + { + return false; + } + + return true; +} + int QtCodeSnippet::toTextEditPosition(int lineNumber, int columnNumber) const { lineNumber -= m_startLineNumber - 1; diff --git a/src/app/qt/element/QtCodeSnippet.h b/src/app/qt/element/QtCodeSnippet.h index d70f6ff3..56d708e4 100644 --- a/src/app/qt/element/QtCodeSnippet.h +++ b/src/app/qt/element/QtCodeSnippet.h @@ -11,8 +11,10 @@ class QPaintEvent; class QPushButton; class QResizeEvent; class QSize; +class QtCodeFile; class QtHighlighter; class QWidget; +class TokenLocation; class TokenLocationFile; class QtCodeSnippet: public QPlainTextEdit @@ -39,8 +41,7 @@ public: uint startLineNumber, const std::string& code, const TokenLocationFile& locationFile, - const std::vector& activeTokenIds, - QWidget *parent = 0 + QtCodeFile* parent ); virtual ~QtCodeSnippet(); @@ -53,19 +54,20 @@ public: int lineNumberAreaWidth() const; void updateLineNumberAreaWidthForDigits(int digits); - void setActiveTokenIds(const std::vector& activeTokenIds); + void update(); protected: virtual void resizeEvent(QResizeEvent *event); virtual void showEvent(QShowEvent* event); virtual void enterEvent(QEvent* event); virtual void leaveEvent(QEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); virtual void mouseDoubleClickEvent(QMouseEvent* event); + virtual void mouseMoveEvent(QMouseEvent* event); private slots: void updateLineNumberAreaWidth(int newBlockCount); void updateLineNumberArea(const QRect &, int); - void clickedTokenLocation(); void clickedMaximizeButton(); void clearSelection(); @@ -79,24 +81,28 @@ private: bool isScope; }; + const Annotation* findAnnotationForPosition(int pos) const; void createAnnotations(const TokenLocationFile& locationFile); void annotateText(); + bool locationBelongsToSnippet(TokenLocation* location) const; + int toTextEditPosition(int lineNumber, int columnNumber) const; int startTextEditPosition() const; int endTextEditPosition() const; + QtCodeFile* m_parent; + QWidget* m_lineNumberArea; QtHighlighter* m_highlighter; QPushButton* m_maximizeButton; - bool m_showMaximizeButton; const uint m_startLineNumber; - const std::string m_filePath; - std::vector m_activeTokenIds; std::vector m_annotations; + const Annotation* m_hoveredAnnotation; + int m_digits; }; diff --git a/src/app/qt/element/QtStatusBar.cpp b/src/app/qt/element/QtStatusBar.cpp index fecab162..086a3b07 100644 --- a/src/app/qt/element/QtStatusBar.cpp +++ b/src/app/qt/element/QtStatusBar.cpp @@ -17,5 +17,10 @@ void QtStatusBar::setText(const std::string& text, bool isError) { m_text.setStyleSheet("QLabel { color: red }"); } + else + { + m_text.setStyleSheet(""); + } + m_text.setText(text.c_str()); } diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp index fb647c3c..22837cc2 100644 --- a/src/app/qt/view/QtCodeView.cpp +++ b/src/app/qt/view/QtCodeView.cpp @@ -10,7 +10,6 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout) : CodeView(viewLayout) , m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this)) - , m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this)) , m_showCodeSnippetsFunctor(std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1)) , m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1)) { @@ -35,16 +34,16 @@ void QtCodeView::refreshView() m_refreshViewFunctor(); } -void QtCodeView::clearCodeSnippets() -{ - m_clearCodeSnippetsFunctor(); -} - void QtCodeView::setActiveTokenIds(const std::vector& activeTokenIds) { m_activeTokenIds = activeTokenIds; } +void QtCodeView::setErrorMessages(const std::vector& errorMessages) +{ + m_errorMessages = errorMessages; +} + void QtCodeView::showCodeSnippets(const std::vector& snippets) { m_showCodeSnippetsFunctor(snippets); @@ -66,24 +65,31 @@ void QtCodeView::doRefreshView() } } -void QtCodeView::doClearCodeSnippets() -{ - m_widget->clearCodeSnippets(); -} - void QtCodeView::doShowCodeSnippets(const std::vector& snippets) { - doClearCodeSnippets(); + m_widget->clearCodeSnippets(); clearClosedWindows(); for (std::shared_ptr window: m_windows) { - window->setActiveTokenIds(m_activeTokenIds); + if (m_errorMessages.size()) + { + window->close(); + } + else + { + window->setActiveTokenIds(m_activeTokenIds); + window->setErrorMessages(m_errorMessages); + } } + m_widget->setActiveTokenIds(m_activeTokenIds); + m_widget->setErrorMessages(m_errorMessages); + m_widget->setShowMaximizeButton(m_errorMessages.size() == 0); + for (const CodeSnippetParams& params : snippets) { - m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, m_activeTokenIds); + m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile); } } @@ -93,7 +99,9 @@ void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) m_windows.push_back(ptr); ptr->setShowMaximizeButton(false); - ptr->addCodeSnippet(1, params.code, params.locationFile, m_activeTokenIds); + ptr->setActiveTokenIds(m_activeTokenIds); + ptr->setErrorMessages(m_errorMessages); + ptr->addCodeSnippet(1, params.code, params.locationFile); ptr->setWindowTitle(FileSystem::fileName(params.locationFile.getFilePath()).c_str()); ptr->show(); diff --git a/src/app/qt/view/QtCodeView.h b/src/app/qt/view/QtCodeView.h index 61593717..5f9ce3dd 100644 --- a/src/app/qt/view/QtCodeView.h +++ b/src/app/qt/view/QtCodeView.h @@ -24,14 +24,14 @@ public: virtual void refreshView(); // CodeView implementation - virtual void clearCodeSnippets(); virtual void setActiveTokenIds(const std::vector& activeTokenIds); + virtual void setErrorMessages(const std::vector& errorMessages); + virtual void showCodeSnippets(const std::vector& snippets); virtual void showCodeFile(const CodeSnippetParams& params); private: void doRefreshView(); - void doClearCodeSnippets(); void doShowCodeSnippets(const std::vector& snippets); void doShowCodeFile(const CodeSnippetParams& params); @@ -41,13 +41,14 @@ private: void clearClosedWindows(); QtThreadedFunctor<> m_refreshViewFunctor; - QtThreadedFunctor<> m_clearCodeSnippetsFunctor; QtThreadedFunctor&> m_showCodeSnippetsFunctor; QtThreadedFunctor m_showCodeFileFunctor; std::shared_ptr m_widget; std::vector> m_windows; + std::vector m_activeTokenIds; + std::vector m_errorMessages; }; # endif // QT_CODE_VIEW_H diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index fd311c65..49aaec60 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -47,8 +47,6 @@ void Application::loadProject(const std::string& projectSettingsFilePath) m_project->loadProjectSettings(projectSettingsFilePath); m_project->parseCode(); - - activateInitialNode(); } void Application::loadSource(const std::string& sourceDirectoryPath) @@ -58,16 +56,12 @@ void Application::loadSource(const std::string& sourceDirectoryPath) m_project->clearProjectSettings(); m_project->setSourceDirectoryPath(sourceDirectoryPath); m_project->parseCode(); - - activateInitialNode(); } void Application::reloadProject() { m_project->clearStorage(); m_project->parseCode(); - - activateInitialNode(); } void Application::saveProject(const std::string& projectSettingsFilePath) @@ -78,8 +72,13 @@ void Application::saveProject(const std::string& projectSettingsFilePath) } } -void Application::activateInitialNode() const +void Application::handleMessage(MessageFinishedParsing* message) { + if (message->errorCount > 0) + { + return; + } + Id mainId = m_graphAccessProxy->getIdForNodeWithName("main"); if (!mainId) diff --git a/src/lib/Application.h b/src/lib/Application.h index 6b66e2d0..96647dbd 100644 --- a/src/lib/Application.h +++ b/src/lib/Application.h @@ -6,6 +6,7 @@ #include "component/ComponentManager.h" #include "Project.h" #include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageLoadProject.h" #include "utility/messaging/type/MessageLoadSource.h" #include "utility/messaging/type/MessageRefresh.h" @@ -17,7 +18,8 @@ class GraphAccessProxy; class LocationAccessProxy; class Application - : public MessageListener + : public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -35,8 +37,7 @@ public: private: Application(); - void activateInitialNode() const; - + virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageLoadProject* message); virtual void handleMessage(MessageLoadSource* message); virtual void handleMessage(MessageRefresh* message); diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index b78d5871..d42308d2 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -13,6 +13,8 @@ add_files( data/parser/cxx/ASTConsumer.h data/parser/cxx/ASTVisitor.cpp data/parser/cxx/ASTVisitor.h + data/parser/cxx/CxxDiagnosticConsumer.cpp + data/parser/cxx/CxxDiagnosticConsumer.h data/parser/cxx/CxxParser.cpp data/parser/cxx/CxxParser.h data/parser/cxx/utilityCxx.cpp diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index 78114ce1..4b914e77 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -102,12 +102,13 @@ void Project::parseCode() ); time = clock() - time; - m_storage->logGraph(); - m_storage->logLocations(); + // m_storage->logGraph(); + // m_storage->logLocations(); - LOG_INFO_STREAM(<< "parse time: " << (double)(time) / CLOCKS_PER_SEC); + double parseTime = (double)(time) / CLOCKS_PER_SEC; + LOG_INFO_STREAM(<< "parse time: " << parseTime); - MessageFinishedParsing().dispatch(); + MessageFinishedParsing(parseTime, m_storage->getErrorCount()).dispatch(); } } diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 3a1a702a..82b01446 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -38,8 +38,34 @@ void CodeController::handleMessage(MessageActivateTokens* message) activeTokenIds = m_graphAccess->getActiveTokenIdsForId(activeTokenIds[0], &declarationId); } - getView()->setActiveTokenIds(activeTokenIds); - getView()->showCodeSnippets(getSnippetsForActiveTokenIds(activeTokenIds, declarationId)); + CodeView* view = getView(); + view->setActiveTokenIds(activeTokenIds); + view->setErrorMessages(std::vector()); + view->showCodeSnippets(getSnippetsForActiveTokenIds(activeTokenIds, declarationId)); +} + +void CodeController::handleMessage(MessageFinishedParsing* message) +{ + if (message->errorCount > 0) + { + std::vector errorMessages; + TokenLocationCollection errorCollection = m_locationAccess->getErrorTokenLocations(&errorMessages); + + std::vector snippets; + + errorCollection.forEachTokenLocationFile( + [&](TokenLocationFile* 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(MessageRefresh* message) @@ -78,28 +104,12 @@ std::vector CodeController::getSnippetsForActiveTok collection.forEachTokenLocationFile( [&](TokenLocationFile* file) -> void { - const std::string filePath = file->getFilePath(); - std::shared_ptr textAccess = TextAccess::createFromFile(filePath); + std::vector fileSnippets = getSnippetsForFile(file); - std::vector> ranges = getSnippetRangesForFile(file, s_lineRadius); - std::vector fileSnippets; - - for (const std::pair& range: ranges) + for (CodeView::CodeSnippetParams& params : fileSnippets) { - unsigned int firstLineNumber = std::max(1, range.first - s_lineRadius); - unsigned int lastLineNumber = std::min(textAccess->getLineCount(), range.second + s_lineRadius); - - CodeView::CodeSnippetParams params; - for (const std::string& line: textAccess->getLines(firstLineNumber, lastLineNumber)) - { - params.code += line; - } - - params.startLineNumber = firstLineNumber; - params.locationFile = - m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber); - - fileSnippets.push_back(params); + params.locationFile = m_locationAccess->getTokenLocationsForLinesInFile( + file->getFilePath(), params.startLineNumber, params.endLineNumber); } if (declarationId != 0) @@ -133,9 +143,32 @@ std::vector CodeController::getSnippetsForActiveTok return snippets; } -std::vector> CodeController::getSnippetRangesForFile( - TokenLocationFile* file, const uint lineRadius -) const +std::vector CodeController::getSnippetsForFile(const TokenLocationFile* file) const +{ + std::shared_ptr textAccess = TextAccess::createFromFile(file->getFilePath()); + + std::vector> ranges = getSnippetRangesForFile(file); + std::vector snippets; + + for (const std::pair& range: ranges) + { + CodeView::CodeSnippetParams params; + params.locationFile = *file; + params.startLineNumber = std::max(1, range.first - s_lineRadius); + params.endLineNumber = std::min(textAccess->getLineCount(), range.second + s_lineRadius); + + for (const std::string& line: textAccess->getLines(params.startLineNumber, params.endLineNumber)) + { + params.code += line; + } + + snippets.push_back(params); + } + + return snippets; +} + +std::vector> CodeController::getSnippetRangesForFile(const TokenLocationFile* file) const { std::vector> ranges; uint start = 0; @@ -152,7 +185,7 @@ std::vector> CodeController::getSnippetRangesForFile( { start = lineNumber; } - else if (end && lineNumber > end + 2 * lineRadius + 1) + else if (end && lineNumber > end + 2 * s_lineRadius + 1) { ranges.push_back(std::make_pair(uint(start), uint(end))); start = lineNumber; diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index fa1fc7b6..a4692db4 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -8,6 +8,7 @@ #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateTokenLocation.h" #include "utility/messaging/type/MessageActivateTokens.h" +#include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageRefresh.h" #include "utility/messaging/type/MessageShowFile.h" #include "utility/types.h" @@ -20,6 +21,7 @@ class CodeController : public Controller , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener { @@ -32,6 +34,7 @@ private: virtual void handleMessage(MessageActivateTokenLocation* message); virtual void handleMessage(MessageActivateTokens* message); + virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageRefresh* message); virtual void handleMessage(MessageShowFile* message); @@ -39,7 +42,8 @@ private: std::vector getSnippetsForActiveTokenIds( const std::vector& ids, Id declarationId) const; - std::vector> getSnippetRangesForFile(TokenLocationFile* file, const uint lineRadius) const; + std::vector getSnippetsForFile(const TokenLocationFile* file) const; + std::vector> getSnippetRangesForFile(const TokenLocationFile* file) const; GraphAccess* m_graphAccess; LocationAccess* m_locationAccess; diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index 36ac6fa0..d9b0719e 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -56,6 +56,11 @@ void GraphController::handleMessage(MessageActivateTokens* message) createDummyGraphForTokenIds(m_activeTokenIds); } +void GraphController::handleMessage(MessageFinishedParsing* message) +{ + getView()->clear(); +} + void GraphController::handleMessage(MessageGraphNodeExpand* message) { DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access); @@ -153,10 +158,26 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node) Edge* edge = child->getMemberEdge(); TokenComponentAccess* access = edge->getComponent(); + TokenComponentAccess::AccessType accessType = TokenComponentAccess::ACCESS_NONE; + if (access) { - TokenComponentAccess::AccessType accessType = access->getAccess(); + accessType = access->getAccess(); + } + else + { + if (node->isType(Node::NODE_CLASS | Node::NODE_STRUCT)) + { + accessType = TokenComponentAccess::ACCESS_PUBLIC; + } + else + { + parent = &result; + } + } + if (accessType != TokenComponentAccess::ACCESS_NONE) + { for (DummyNode& dummy : result.subNodes) { if (dummy.accessType == accessType) @@ -178,10 +199,6 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node) } } } - else - { - parent = &result; - } parent->subNodes.push_back(createDummyNodeTopDown(child)); } diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 0bb05c73..1b29c03d 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -5,6 +5,7 @@ #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateTokens.h" +#include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageGraphNodeExpand.h" #include "utility/messaging/type/MessageGraphNodeMove.h" @@ -21,6 +22,7 @@ class Node; class GraphController : public Controller , public MessageListener + , public MessageListener , public MessageListener , public MessageListener { @@ -47,6 +49,7 @@ public: private: virtual void handleMessage(MessageActivateTokens* message); + virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageGraphNodeExpand* message); virtual void handleMessage(MessageGraphNodeMove* message); diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index b65d62a0..2b803570 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -32,6 +32,11 @@ void SearchController::handleMessage(MessageFind* message) getView()->setFocus(); } +void SearchController::handleMessage(MessageFinishedParsing* message) +{ + getView()->setText(""); +} + void SearchController::handleMessage(MessageRefresh* message) { getView()->refreshView(); diff --git a/src/lib/component/controller/SearchController.h b/src/lib/component/controller/SearchController.h index 5479c14d..131ea26b 100644 --- a/src/lib/component/controller/SearchController.h +++ b/src/lib/component/controller/SearchController.h @@ -7,6 +7,7 @@ #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageFind.h" +#include "utility/messaging/type/MessageFinishedParsing.h" #include "utility/messaging/type/MessageRefresh.h" #include "utility/messaging/type/MessageSearch.h" #include "utility/messaging/type/MessageSearchAutocomplete.h" @@ -18,6 +19,7 @@ class SearchController : public Controller , public MessageListener , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -29,6 +31,7 @@ public: private: virtual void handleMessage(MessageActivateTokens* message); virtual void handleMessage(MessageFind* message); + virtual void handleMessage(MessageFinishedParsing* message); virtual void handleMessage(MessageRefresh* message); virtual void handleMessage(MessageSearch* message); virtual void handleMessage(MessageSearchAutocomplete* message); diff --git a/src/lib/component/controller/StatusBarController.cpp b/src/lib/component/controller/StatusBarController.cpp index bb2c34f3..8b63bc37 100644 --- a/src/lib/component/controller/StatusBarController.cpp +++ b/src/lib/component/controller/StatusBarController.cpp @@ -2,6 +2,9 @@ #include "component/view/StatusBarView.h" +#include +#include + StatusBarController::StatusBarController() : MessageListener(true) , MessageListener(true) @@ -23,7 +26,14 @@ StatusBarView* StatusBarController::getView() void StatusBarController::handleMessage(MessageFinishedParsing* message) { - setStatus("Parsing Finished"); + std::stringstream ss; + ss << "Parsing Finished: "; + ss << std::setprecision(2) << message->parseTime << " seconds, "; + ss << message->errorCount << " error(s)"; + + bool hasErrors = message->errorCount > 0; + + setStatus(ss.str(), hasErrors); } void StatusBarController::handleMessage(MessageStatus* message) diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 6f71b406..073ce661 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -34,8 +34,9 @@ public: virtual std::string getName() const; - virtual void clearCodeSnippets() = 0; virtual void setActiveTokenIds(const std::vector& activeTokenIds) = 0; + virtual void setErrorMessages(const std::vector& errorMessages) = 0; + virtual void showCodeSnippets(const std::vector& snippets) = 0; virtual void showCodeFile(const CodeSnippetParams& params) = 0; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 2c8e0fe7..bb2e422b 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -48,6 +48,30 @@ void Storage::logLocations() const LOG_INFO_STREAM(<< '\n' << m_locationCollection); } +size_t Storage::getErrorCount() const +{ + return m_errorMessages.size(); +} + +void Storage::onError(const ParseLocation& location, const std::string& message) +{ + log("ERROR", message, location); + + if (!location.isValid()) + { + return; + } + + Id errorId = m_errorMessages.size(); + + TokenLocation* loc = m_errorLocationCollection.addTokenLocation( + errorId, location.filePath, + location.startLineNumber, location.startColumnNumber, + location.endLineNumber, location.endColumnNumber + ); + + m_errorMessages.push_back(message); +} Id Storage::onTypedefParsed( const ParseLocation& location, const std::vector& nameHierarchy, const ParseTypeUsage& underlyingType, @@ -576,7 +600,6 @@ std::vector Storage::getActiveTokenIdsForId(Id tokenId, Id* declarationId) c ret.push_back(token->getId()); - Node* node; if (token->isNode()) { Node* node = dynamic_cast(token); @@ -744,6 +767,13 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile( return ret; } +TokenLocationCollection Storage::getErrorTokenLocations(std::vector* errorMessages) const +{ + errorMessages->insert(errorMessages->begin(), m_errorMessages.begin(), m_errorMessages.end()); + + return m_errorLocationCollection; +} + const Graph& Storage::getGraph() const { return m_graph; @@ -941,8 +971,16 @@ bool Storage::getSubQuerySearchResults( { if (word.size()) { - SearchResults res = node->runFuzzySearch(word); - results->insert(res.begin(), res.end()); + if (searchNodes.size() > 1) + { + SearchResults res = node->runFuzzySearchOnSelf(word); + results->insert(res.begin(), res.end()); + } + else + { + SearchResults res = node->runFuzzySearch(word); + results->insert(res.begin(), res.end()); + } } else if (searchNodes.size() == 1) { diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 296ef8f8..6e309f1a 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -27,7 +27,11 @@ public: void logGraph() const; void logLocations() const; + size_t getErrorCount() const; + // ParserClient implementation + virtual void onError(const ParseLocation& location, const std::string& message); + virtual Id onTypedefParsed( const ParseLocation& location, const std::vector& nameHierarchy, const ParseTypeUsage& underlyingType, AccessType access); @@ -108,6 +112,8 @@ public: const std::string& filePath, uint firstLineNumber, uint lastLineNumber ) const; + virtual TokenLocationCollection getErrorTokenLocations(std::vector* errorMessages) const; + protected: const Graph& getGraph() const; const TokenLocationCollection& getTokenLocationCollection() const; @@ -137,6 +143,9 @@ private: SearchIndex m_tokenIndex; SearchIndex m_filterIndex; + + TokenLocationCollection m_errorLocationCollection; + std::vector m_errorMessages; }; #endif // STORAGE_H diff --git a/src/lib/data/access/LocationAccess.h b/src/lib/data/access/LocationAccess.h index 8a73ff9b..a0f7ea08 100644 --- a/src/lib/data/access/LocationAccess.h +++ b/src/lib/data/access/LocationAccess.h @@ -18,6 +18,8 @@ public: virtual TokenLocationFile getTokenLocationsForLinesInFile( const std::string& filePath, uint firstLineNumber, uint lastLineNumber ) const = 0; + + virtual TokenLocationCollection getErrorTokenLocations(std::vector* errorMessages) const = 0; }; diff --git a/src/lib/data/access/LocationAccessProxy.cpp b/src/lib/data/access/LocationAccessProxy.cpp index 78dc5368..c067abad 100644 --- a/src/lib/data/access/LocationAccessProxy.cpp +++ b/src/lib/data/access/LocationAccessProxy.cpp @@ -60,3 +60,13 @@ TokenLocationFile LocationAccessProxy::getTokenLocationsForLinesInFile( return TokenLocationFile(""); } + +TokenLocationCollection LocationAccessProxy::getErrorTokenLocations(std::vector* errorMessages) const +{ + if (hasSubject()) + { + return m_subject->getErrorTokenLocations(errorMessages); + } + + return TokenLocationCollection(); +} diff --git a/src/lib/data/access/LocationAccessProxy.h b/src/lib/data/access/LocationAccessProxy.h index 53ada5ab..8b6b6445 100644 --- a/src/lib/data/access/LocationAccessProxy.h +++ b/src/lib/data/access/LocationAccessProxy.h @@ -19,6 +19,8 @@ public: const std::string& filePath, uint firstLineNumber, uint lastLineNumber ) const; + virtual TokenLocationCollection getErrorTokenLocations(std::vector* errorMessages) const; + private: LocationAccess* m_subject; }; diff --git a/src/lib/data/parser/ParseLocation.cpp b/src/lib/data/parser/ParseLocation.cpp index 16957979..cd1034d3 100644 --- a/src/lib/data/parser/ParseLocation.cpp +++ b/src/lib/data/parser/ParseLocation.cpp @@ -9,6 +9,19 @@ ParseLocation::ParseLocation() { } +ParseLocation::ParseLocation( + const std::string& filePath, + uint lineNumber, + uint columnNumber +) + : filePath(filePath) + , startLineNumber(lineNumber) + , startColumnNumber(columnNumber) + , endLineNumber(lineNumber) + , endColumnNumber(columnNumber) +{ +} + ParseLocation::ParseLocation( const std::string& filePath, uint startLineNumber, uint startColumnNumber, diff --git a/src/lib/data/parser/ParseLocation.h b/src/lib/data/parser/ParseLocation.h index 77951e84..a97e6234 100644 --- a/src/lib/data/parser/ParseLocation.h +++ b/src/lib/data/parser/ParseLocation.h @@ -8,6 +8,11 @@ struct ParseLocation { ParseLocation(); + ParseLocation( + const std::string& filePath, + uint lineNumber, + uint columnNumber + ); ParseLocation( const std::string& filePath, uint startLineNumber, uint startColumnNumber, diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 4d0c51b7..51a8a492 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -49,6 +49,8 @@ public: ParserClient(); virtual ~ParserClient(); + virtual void onError(const ParseLocation& location, const std::string& message) = 0; + virtual Id onTypedefParsed( const ParseLocation& location, const std::vector& nameHierarchy, const ParseTypeUsage& underlyingType, AccessType access) = 0; diff --git a/src/lib/data/parser/cxx/ASTConsumer.cpp b/src/lib/data/parser/cxx/ASTConsumer.cpp index 74591c8c..381a2a1d 100644 --- a/src/lib/data/parser/cxx/ASTConsumer.cpp +++ b/src/lib/data/parser/cxx/ASTConsumer.cpp @@ -1,5 +1,7 @@ #include "data/parser/cxx/ASTConsumer.h" +#include "data/parser/ParserClient.h" + ASTConsumer::ASTConsumer(clang::ASTContext* context, ParserClient* client) : m_visitor(context, client) { diff --git a/src/lib/data/parser/cxx/CxxDiagnosticConsumer.cpp b/src/lib/data/parser/cxx/CxxDiagnosticConsumer.cpp new file mode 100644 index 00000000..5cefa272 --- /dev/null +++ b/src/lib/data/parser/cxx/CxxDiagnosticConsumer.cpp @@ -0,0 +1,75 @@ +#include "data/parser/cxx/CxxDiagnosticConsumer.h" + +#include "clang/Basic/SourceManager.h" + +#include "data/parser/ParseLocation.h" +#include "data/parser/ParserClient.h" + +CxxDiagnosticConsumer::CxxDiagnosticConsumer( + clang::raw_ostream &os, + clang::DiagnosticOptions *diags, + ParserClient* client, + bool useLogging +) + : clang::TextDiagnosticPrinter(os, diags) + , m_client(client) + , m_isParsingFile(false) + , m_useLogging(useLogging) +{ +} + +void CxxDiagnosticConsumer::BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor) +{ + if (m_useLogging) + { + clang::TextDiagnosticPrinter::BeginSourceFile(langOptions, preProcessor); + } + + m_isParsingFile = true; +} + +void CxxDiagnosticConsumer::EndSourceFile() +{ + if (m_useLogging) + { + clang::TextDiagnosticPrinter::EndSourceFile(); + } + + m_isParsingFile = false; +} + +void CxxDiagnosticConsumer::HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info) +{ + if (m_useLogging) + { + clang::TextDiagnosticPrinter::HandleDiagnostic(level, info); + } + + if (!m_isParsingFile) + { + return; + } + + if (level == clang::DiagnosticsEngine::Error || level == clang::DiagnosticsEngine::Fatal) + { + llvm::SmallString<100> messageStr; + info.FormatDiagnostic(messageStr); + std::string message = messageStr.str(); + + std::string filePath; + uint line = 0; + uint column = 0; + + if (info.getLocation().isValid() && info.hasSourceManager()) + { + const clang::SourceManager& sourceManager = info.getSourceManager(); + clang::PresumedLoc presumedLocation = sourceManager.getPresumedLoc(info.getLocation()); + + filePath = presumedLocation.getFilename(); + line = presumedLocation.getLine(); + column = presumedLocation.getColumn(); + } + + m_client->onError(ParseLocation(filePath, line, column), message); + } +} diff --git a/src/lib/data/parser/cxx/CxxDiagnosticConsumer.h b/src/lib/data/parser/cxx/CxxDiagnosticConsumer.h new file mode 100644 index 00000000..ac437c6e --- /dev/null +++ b/src/lib/data/parser/cxx/CxxDiagnosticConsumer.h @@ -0,0 +1,25 @@ +#ifndef CXX_DIAGNOSTIC_CONSUMER +#define CXX_DIAGNOSTIC_CONSUMER + +#include "clang/Frontend/TextDiagnosticPrinter.h" + +class ParserClient; + +class CxxDiagnosticConsumer + : public clang::TextDiagnosticPrinter +{ +public: + CxxDiagnosticConsumer(clang::raw_ostream &os, clang::DiagnosticOptions *diags, ParserClient* client, bool useLogging = true); + + void BeginSourceFile(const clang::LangOptions& langOptions, const clang::Preprocessor* preProcessor); + void EndSourceFile(); + + void HandleDiagnostic(clang::DiagnosticsEngine::Level level, const clang::Diagnostic& info); + +private: + ParserClient* m_client; + bool m_isParsingFile; + bool m_useLogging; +}; + +#endif // CXX_DIAGNOSTIC_CONSUMER diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp index 4726a0e7..49bc76a4 100644 --- a/src/lib/data/parser/cxx/CxxParser.cpp +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -1,9 +1,54 @@ #include "data/parser/cxx/CxxParser.h" -#include "data/parser/cxx/ASTActionFactory.h" #include "utility/logging/logging.h" #include "utility/text/TextAccess.h" +#include "data/parser/cxx/ASTActionFactory.h" +#include "data/parser/cxx/CxxDiagnosticConsumer.h" + +namespace { + +static std::vector getSyntaxOnlyToolArgs(const std::vector &ExtraArgs, llvm::StringRef FileName) +{ + std::vector Args; + Args.push_back("clang-tool"); + Args.push_back("-fsyntax-only"); + Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end()); + Args.push_back(FileName.str()); + return Args; +} + +// custom implementation of clang::runToolOnCodeWithArgs which also sets our custon DiagnosticConsumer +static bool runToolOnCodeWithArgs( + clang::DiagnosticConsumer* DiagConsumer, + clang::FrontendAction *ToolAction, + const llvm::Twine &Code, + const std::vector &Args, + const llvm::Twine &FileName = "input.cc", + const clang::tooling::FileContentMappings &VirtualMappedFiles = clang::tooling::FileContentMappings() +){ + llvm::SmallString<16> FileNameStorage; + llvm::StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); + llvm::IntrusiveRefCntPtr Files(new clang::FileManager(clang::FileSystemOptions())); + clang::tooling::ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction, Files.get()); + + llvm::SmallString<1024> CodeStorage; + Invocation.mapVirtualFile(FileNameRef, + Code.toNullTerminatedStringRef(CodeStorage)); + + for (auto &FilenameWithContent : VirtualMappedFiles) + { + Invocation.mapVirtualFile(FilenameWithContent.first, + FilenameWithContent.second); + } + + Invocation.setDiagnosticConsumer(DiagConsumer); + + return Invocation.run(); +} + +} + CxxParser::CxxParser(ParserClient* client) : Parser(client) { @@ -68,15 +113,22 @@ void CxxParser::parseFiles( clang::tooling::ClangTool tool(*compilationDatabase, filePaths); - ASTActionFactory actionFactory(m_client); + llvm::IntrusiveRefCntPtr options = new clang::DiagnosticOptions(); + CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client); + tool.setDiagnosticConsumer(&reporter); + ASTActionFactory actionFactory(m_client); tool.run(&actionFactory); } void CxxParser::parseFile(std::shared_ptr textAccess) { - ASTActionFactory actionFactory(m_client); std::vector args; args.push_back("-fno-delayed-template-parsing"); - clang::tooling::runToolOnCodeWithArgs(actionFactory.create(), textAccess->getText(), args); + + llvm::IntrusiveRefCntPtr options = new clang::DiagnosticOptions(); + CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, false); + + ASTActionFactory actionFactory(m_client); + runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args); } diff --git a/src/lib/data/search/SearchNode.cpp b/src/lib/data/search/SearchNode.cpp index d254cc46..882b6997 100644 --- a/src/lib/data/search/SearchNode.cpp +++ b/src/lib/data/search/SearchNode.cpp @@ -107,6 +107,20 @@ SearchResults SearchNode::runFuzzySearch(const std::string& query) const return result; } +SearchResults SearchNode::runFuzzySearchOnSelf(const std::string& query) const +{ + SearchResults result; + FuzzyMap m = fuzzyMatchRecursive(query, 0, 0, 0); + for (const std::pair& p : m) + { + addResultsRecursive(result, p.first, p.second); + } + + // TODO: Currently all matches are added to the ordered set and get compared by their fullName for alphabetical + // order. This could be improved by limiting the number of items to e.g. 100. + return result; +} + void SearchNode::addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const { result.insert(SearchResult(weight, node, this)); diff --git a/src/lib/data/search/SearchNode.h b/src/lib/data/search/SearchNode.h index d3c7ab9b..f93f6493 100644 --- a/src/lib/data/search/SearchNode.h +++ b/src/lib/data/search/SearchNode.h @@ -37,6 +37,8 @@ public: const std::set>& getChildren() const; SearchResults runFuzzySearch(const std::string& query) const; + SearchResults runFuzzySearchOnSelf(const std::string& query) const; + void addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const; private: diff --git a/src/lib/utility/messaging/type/MessageFinishedParsing.h b/src/lib/utility/messaging/type/MessageFinishedParsing.h index c41978ee..0eca55c3 100644 --- a/src/lib/utility/messaging/type/MessageFinishedParsing.h +++ b/src/lib/utility/messaging/type/MessageFinishedParsing.h @@ -6,7 +6,9 @@ class MessageFinishedParsing: public Message { public: - MessageFinishedParsing() + MessageFinishedParsing(float parseTime, size_t errorCount) + : parseTime(parseTime) + , errorCount(errorCount) { } @@ -14,6 +16,9 @@ public: { return "MessageFinishedParsing"; } + + float parseTime; + size_t errorCount; }; #endif // MESSAGE_FINISHED_PARSING_H diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 88d5ac1a..984f9d8c 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -1397,6 +1397,8 @@ public: filePaths.push_back("data/CxxParserTestSuite/code.cpp"); parser.parseFiles(filePaths, std::vector(), std::vector()); + TS_ASSERT_EQUALS(client.errors.size(), 0); + TS_ASSERT_EQUALS(client.typedefs.size(), 1); TS_ASSERT_EQUALS(client.classes.size(), 4); TS_ASSERT_EQUALS(client.enums.size(), 1); @@ -1414,10 +1416,25 @@ public: TS_ASSERT_EQUALS(client.typeUses.size(), 8); } + void test_cxx_parser_catches_error() + { + std::shared_ptr client = parseCode( + "int a = b;\n" + ); + + TS_ASSERT_EQUALS(client->errors.size(), 1); + TS_ASSERT_EQUALS(client->errors[0], "use of undeclared identifier \'b\' <1:9 1:9>"); + } + private: class TestParserClient: public ParserClient { public: + virtual void onError(const ParseLocation& location, const std::string& message) + { + errors.push_back(addLocationSuffix(message, location)); + } + virtual Id onTypedefParsed( const ParseLocation& location, const std::vector& nameHierarchy, const ParseTypeUsage& underlyingType, AccessType access @@ -1610,6 +1627,8 @@ private: return 0; } + std::vector errors; + std::vector typedefs; std::vector classes; std::vector enums;