diff --git a/src/app/qt/element/QtMainWindow.cpp b/src/app/qt/element/QtMainWindow.cpp index 7ffb09b1..6022aa20 100644 --- a/src/app/qt/element/QtMainWindow.cpp +++ b/src/app/qt/element/QtMainWindow.cpp @@ -12,6 +12,7 @@ #include "qt/view/QtViewWidgetWrapper.h" #include "utility/logging/logging.h" #include "utility/messaging/type/MessageFind.h" +#include "utility/messaging/type/MessageInterruptTasks.h" #include "utility/messaging/type/MessageLoadProject.h" #include "utility/messaging/type/MessageLoadSource.h" #include "utility/messaging/type/MessageRedo.h" @@ -36,7 +37,9 @@ QtMainWindow::QtMainWindow() setupFindMenu(); setupHelpMenu(); - // Need to call loadLayout here for right DockWidgetsize on Linux + setupShortcuts(); + + // Need to call loadLayout here for right DockWidget size on Linux // Seconde call is in Application.cpp loadLayout(); } @@ -45,94 +48,6 @@ QtMainWindow::~QtMainWindow() { } -void QtMainWindow::about() -{ - QMessageBox::about( - this, - tr("About"), - tr( - "Developed by:\n\n" - "Manuel Dobusch\n" - "Eberhard Gräther\n" - "Malte Langkabel\n" - "Victoria Pfausler\n" - "Andreas Stallinger\n" - ) - ); -} - -void QtMainWindow::newProject() -{ - QString sourceDir = QFileDialog::getExistingDirectory(this, tr("Open Directory")); - - if (!sourceDir.isEmpty()) - { - MessageLoadSource(sourceDir.toStdString()).dispatch(); - } -} - -void QtMainWindow::openProject(const QString &path) -{ - QString fileName = path; - - if (fileName.isNull()) - { - fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", "XML Files (*.xml)"); - } - - if (!fileName.isEmpty()) - { - MessageLoadProject(fileName.toStdString()).dispatch(); - } -} - -void QtMainWindow::undo() -{ - MessageUndo().dispatch(); -} - -void QtMainWindow::redo() -{ - MessageRedo().dispatch(); -} - -void QtMainWindow::saveProject() -{ - MessageSaveProject("").dispatch(); -} - -void QtMainWindow::saveAsProject() -{ - QString filename = ""; - filename = QFileDialog::getSaveFileName(this, "Save File as", "", "XML Files(*.xml)"); - - if(!filename.isEmpty()) - { - MessageSaveProject(filename.toStdString()).dispatch(); - } -} - -void QtMainWindow::find() -{ - MessageFind().dispatch(); -} - -void QtMainWindow::closeWindow() -{ - QApplication* app = dynamic_cast(QCoreApplication::instance()); - - QWidget* activeWindow = app->activeWindow(); - if (activeWindow) - { - activeWindow->close(); - } -} - -void QtMainWindow::refresh() -{ - MessageRefresh().dispatch(); -} - void QtMainWindow::addView(View* view) { QDockWidget* dock = new QDockWidget(tr(view->getName().c_str()), this); @@ -207,6 +122,99 @@ bool QtMainWindow::event(QEvent* event) return QMainWindow::event(event); } +void QtMainWindow::about() +{ + QMessageBox::about( + this, + tr("About"), + tr( + "Developed by:\n\n" + "Manuel Dobusch\n" + "Eberhard Gräther\n" + "Malte Langkabel\n" + "Victoria Pfausler\n" + "Andreas Stallinger\n" + ) + ); +} + +void QtMainWindow::newProject() +{ + QString sourceDir = QFileDialog::getExistingDirectory(this, tr("Open Directory")); + + if (!sourceDir.isEmpty()) + { + MessageLoadSource(sourceDir.toStdString()).dispatch(); + } +} + +void QtMainWindow::openProject(const QString &path) +{ + QString fileName = path; + + if (fileName.isNull()) + { + fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", "XML Files (*.xml)"); + } + + if (!fileName.isEmpty()) + { + MessageLoadProject(fileName.toStdString()).dispatch(); + } +} + +void QtMainWindow::find() +{ + MessageFind().dispatch(); +} + +void QtMainWindow::closeWindow() +{ + QApplication* app = dynamic_cast(QCoreApplication::instance()); + + QWidget* activeWindow = app->activeWindow(); + if (activeWindow) + { + activeWindow->close(); + } +} + +void QtMainWindow::refresh() +{ + MessageRefresh().dispatch(); +} + +void QtMainWindow::saveProject() +{ + MessageSaveProject("").dispatch(); +} + +void QtMainWindow::saveAsProject() +{ + QString filename = ""; + filename = QFileDialog::getSaveFileName(this, "Save File as", "", "XML Files(*.xml)"); + + if(!filename.isEmpty()) + { + MessageSaveProject(filename.toStdString()).dispatch(); + } +} + +void QtMainWindow::undo() +{ + MessageUndo().dispatch(); +} + +void QtMainWindow::redo() +{ + MessageRedo().dispatch(); +} + +void QtMainWindow::handleEscapeShortcut() +{ + MessageInterruptTasks().dispatch(); +} + void QtMainWindow::setupProjectMenu() { QMenu *menu = new QMenu(tr("&Project"), this); @@ -254,6 +262,12 @@ void QtMainWindow::setupHelpMenu() menu->addAction(tr("About &Qt"), QCoreApplication::instance(), SLOT(aboutQt())); } +void QtMainWindow::setupShortcuts() +{ + m_escapeShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this); + connect(m_escapeShortcut, SIGNAL(activated()), SLOT(handleEscapeShortcut())); +} + QDockWidget* QtMainWindow::getDockWidgetForView(View* view) const { for (size_t i = 0; i < m_dockWidgets.size(); i++) diff --git a/src/app/qt/element/QtMainWindow.h b/src/app/qt/element/QtMainWindow.h index c5ea0c64..3fb0c54c 100644 --- a/src/app/qt/element/QtMainWindow.h +++ b/src/app/qt/element/QtMainWindow.h @@ -4,6 +4,7 @@ #include #include +#include #include class QDockWidget; @@ -41,6 +42,8 @@ public slots: void undo(); void redo(); + void handleEscapeShortcut(); + private: void setupEditMenu(); void setupProjectMenu(); @@ -48,9 +51,13 @@ private: void setupFindMenu(); void setupHelpMenu(); + void setupShortcuts(); + QDockWidget* getDockWidgetForView(View* view) const; std::vector> m_dockWidgets; + + QShortcut* m_escapeShortcut; }; #endif // QT_MAIN_WINDOW_H diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 5f8ac3c4..01de79c4 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/MessageActivateTokens.h" +#include "utility/scheduling/TaskScheduler.h" #include "component/view/MainView.h" #include "component/view/ViewFactory.h" @@ -40,10 +41,12 @@ std::shared_ptr Application::create(ViewFactory* viewFactory) Application::Application() { MessageQueue::getInstance()->startMessageLoopThreaded(); + TaskScheduler::getInstance()->startSchedulerLoopThreaded(); } Application::~Application() { + TaskScheduler::getInstance()->stopSchedulerLoop(); MessageQueue::getInstance()->stopMessageLoop(); m_mainView->saveLayout(); } diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 53c9896e..37da7fe7 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -142,6 +142,9 @@ add_files( data/name/NameHierarchy.cpp data/name/NameHierarchy.h + data/parser/cxx/TaskParseCxx.cpp + data/parser/cxx/TaskParseCxx.h + data/parser/ParseFunction.cpp data/parser/ParseFunction.h data/parser/ParseLocation.cpp @@ -241,6 +244,7 @@ add_files( utility/messaging/type/MessageFinishedParsing.h utility/messaging/type/MessageGraphNodeExpand.h utility/messaging/type/MessageGraphNodeMove.h + utility/messaging/type/MessageInterruptTasks.h utility/messaging/type/MessageLoadProject.h utility/messaging/type/MessageLoadSource.h utility/messaging/type/MessageRefresh.h @@ -260,6 +264,15 @@ add_files( utility/messaging/MessageQueue.cpp utility/messaging/MessageQueue.h + utility/scheduling/Task.cpp + utility/scheduling/Task.h + utility/scheduling/TaskGroup.cpp + utility/scheduling/TaskGroup.h + utility/scheduling/TaskGroupSequential.cpp + utility/scheduling/TaskGroupSequential.h + utility/scheduling/TaskScheduler.cpp + utility/scheduling/TaskScheduler.h + utility/text/Dictionary.cpp utility/text/Dictionary.h utility/text/TextAccess.cpp diff --git a/src/lib/Project.cpp b/src/lib/Project.cpp index 2a6753f8..0ae78875 100644 --- a/src/lib/Project.cpp +++ b/src/lib/Project.cpp @@ -6,7 +6,7 @@ #include "data/access/StorageAccessProxy.h" #include "data/graph/Token.h" -#include "data/parser/cxx/CxxParser.h" +#include "data/parser/cxx/TaskParseCxx.h" #include "settings/ApplicationSettings.h" #include "settings/ProjectSettings.h" @@ -24,29 +24,31 @@ Project::~Project() bool Project::loadProjectSettings(const std::string& projectSettingsFile) { bool success = ProjectSettings::getInstance()->load(projectSettingsFile); - if(success) + if (success) { m_projectSettingsFilepath = projectSettingsFile; + + createFileManager(); } return success; } -bool Project::saveProjectSettings( const std::string& projectSettingsFile ) +bool Project::saveProjectSettings(const std::string& projectSettingsFile) { - if(!projectSettingsFile.empty()) + if (projectSettingsFile.size()) { m_projectSettingsFilepath = projectSettingsFile; - ProjectSettings::getInstance()->save(projectSettingsFile); } - else if (!m_projectSettingsFilepath.empty()) - { - ProjectSettings::getInstance()->save(m_projectSettingsFilepath); - } - else + + if (!m_projectSettingsFilepath.size()) { return false; } - LOG_INFO_STREAM(<< "Projectsettings saved in File: " << m_projectSettingsFilepath); + + ProjectSettings::getInstance()->save(m_projectSettingsFilepath); + + LOG_INFO_STREAM(<< "ProjectSettings saved to file: " << m_projectSettingsFilepath); + return true; } @@ -54,12 +56,21 @@ void Project::clearProjectSettings() { m_projectSettingsFilepath.clear(); ProjectSettings::getInstance()->clear(); + + m_fileManager.reset(); } bool Project::setSourceDirectoryPath(const std::string& sourceDirectoryPath) { m_projectSettingsFilepath = sourceDirectoryPath + "/ProjectSettings.xml"; - return ProjectSettings::getInstance()->setSourcePaths(std::vector(1, sourceDirectoryPath)); + bool success = ProjectSettings::getInstance()->setSourcePaths(std::vector(1, sourceDirectoryPath)); + + if (success) + { + createFileManager(); + } + + return success; } void Project::clearStorage() @@ -72,25 +83,13 @@ void Project::clearStorage() void Project::parseCode() { - std::shared_ptr projSettings = ProjectSettings::getInstance(); - std::shared_ptr appSettings = ApplicationSettings::getInstance(); - - std::vector sourcePaths = projSettings->getSourcePaths(); - if (!sourcePaths.size()) + if (!m_fileManager) { + LOG_ERROR("No FileManger was created."); return; } - std::vector includePaths(sourcePaths); - - // TODO: move this creation to another place (after projectsettings have been loaded) - if (!m_fileManager) - { - std::vector sourceExtensions = ProjectSettings::getInstance()->getSourceExtensions(); - std::vector includeExtensions = ProjectSettings::getInstance()->getHeaderExtensions(); - - m_fileManager = std::make_shared(sourcePaths, includePaths, sourceExtensions, includeExtensions); - } + std::shared_ptr projSettings = ProjectSettings::getInstance(); m_fileManager->fetchFilePaths(); std::set addedFilePaths = m_fileManager->getAddedFilePaths(); @@ -109,36 +108,59 @@ void Project::parseCode() if (filesToParse.size() == 0) { - MessageFinishedParsing(0, 0, m_storage->getErrorCount()).dispatch(); + MessageFinishedParsing(0, 0, 0, m_storage->getErrorCount()).dispatch(); return; } + Task::dispatch(std::make_shared( + m_storage.get(), + m_fileManager.get(), + getParserArguments(), + filesToParse + )); +} + +void Project::createFileManager() +{ + std::shared_ptr projSettings = ProjectSettings::getInstance(); + + std::vector sourcePaths(projSettings->getSourcePaths()); + std::vector includePaths(sourcePaths); + + std::vector sourceExtensions = projSettings->getSourceExtensions(); + std::vector includeExtensions = projSettings->getHeaderExtensions(); + + if (sourcePaths.size()) + { + m_fileManager = std::make_shared(sourcePaths, includePaths, sourceExtensions, includeExtensions); + } +} + +Parser::Arguments Project::getParserArguments() const +{ + std::shared_ptr projSettings = ProjectSettings::getInstance(); + std::shared_ptr appSettings = ApplicationSettings::getInstance(); + Parser::Arguments args; + if (!m_fileManager) + { + LOG_ERROR("No FileManger was created."); + return args; + } + utility::append(args.compilerFlags, projSettings->getCompilerFlags()); utility::append(args.compilerFlags, appSettings->getCompilerFlags()); // Add the include paths as HeaderSearchPaths as well, so clang will also look here when searching include files. - utility::append(args.systemHeaderSearchPaths, includePaths); + utility::append(args.systemHeaderSearchPaths, m_fileManager->getIncludePaths()); utility::append(args.systemHeaderSearchPaths, projSettings->getHeaderSearchPaths()); utility::append(args.systemHeaderSearchPaths, appSettings->getHeaderSearchPaths()); utility::append(args.frameworkSearchPaths, projSettings->getFrameworkSearchPaths()); utility::append(args.frameworkSearchPaths, appSettings->getFrameworkSearchPaths()); - CxxParser parser(m_storage.get(), m_fileManager.get()); - - float duration = utility::duration( - [&]() - { - parser.parseFiles(filesToParse, args); - } - ); - - // m_storage->logGraph(); - // m_storage->logLocations(); - - MessageFinishedParsing(filesToParse.size(), duration, m_storage->getErrorCount()).dispatch(); + return args; } Project::Project(StorageAccessProxy* storageAccessProxy) diff --git a/src/lib/Project.h b/src/lib/Project.h index 6ac97830..b9a3b9b5 100644 --- a/src/lib/Project.h +++ b/src/lib/Project.h @@ -5,6 +5,7 @@ #include "utility/file/FileManager.h" +#include "data/parser/Parser.h" #include "data/Storage.h" class StorageAccessProxy; @@ -30,6 +31,10 @@ private: Project(const Project&); Project operator=(const Project&); + void createFileManager(); + + Parser::Arguments getParserArguments() const; + std::string m_projectSettingsFilepath; StorageAccessProxy* const m_storageAccessProxy; diff --git a/src/lib/component/controller/StatusBarController.cpp b/src/lib/component/controller/StatusBarController.cpp index 8c8492f4..823af47d 100644 --- a/src/lib/component/controller/StatusBarController.cpp +++ b/src/lib/component/controller/StatusBarController.cpp @@ -30,7 +30,7 @@ void StatusBarController::handleMessage(MessageFinishedParsing* message) { std::stringstream ss; ss << "Parsing Finished: "; - ss << message->fileCount << " files, "; + ss << message->fileCount << "/" << message->totalFileCount << " files, "; ss << std::setprecision(2) << std::fixed << message->parseTime << " seconds, "; ss << message->errorCount << " error(s)"; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 09351955..0413f4b4 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -150,11 +150,6 @@ void Storage::logLocations() const LOG_INFO_STREAM(<< '\n' << m_locationCollection); } -size_t Storage::getErrorCount() const -{ - return m_errorLocationCollection.getTokenLocationCount(); -} - void Storage::onError(const ParseLocation& location, const std::string& message) { log("ERROR", message, location); @@ -198,6 +193,11 @@ void Storage::onError(const ParseLocation& location, const std::string& message) } } +size_t Storage::getErrorCount() const +{ + return m_errorLocationCollection.getTokenLocationCount(); +} + Id Storage::onTypedefParsed( const ParseLocation& location, const NameHierarchy& nameHierarchy, const ParseTypeUsage& underlyingType, AccessType access diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 92f65efc..d7489075 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -29,10 +29,9 @@ public: void logGraph() const; void logLocations() const; - size_t getErrorCount() const; - // ParserClient implementation virtual void onError(const ParseLocation& location, const std::string& message); + virtual size_t getErrorCount() const; virtual Id onTypedefParsed( const ParseLocation& location, const NameHierarchy& nameHierarchy, diff --git a/src/lib/data/parser/Parser.h b/src/lib/data/parser/Parser.h index e87cc9ae..ff34659e 100644 --- a/src/lib/data/parser/Parser.h +++ b/src/lib/data/parser/Parser.h @@ -5,9 +5,8 @@ #include #include -#include "data/parser/ParserClient.h" - class FilePath; +class ParserClient; class TextAccess; class Parser diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 2c961c17..dbbfc550 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -51,6 +51,7 @@ public: virtual ~ParserClient(); virtual void onError(const ParseLocation& location, const std::string& message) = 0; + virtual size_t getErrorCount() const = 0; virtual Id onTypedefParsed( const ParseLocation& location, const NameHierarchy& nameHierarchy, diff --git a/src/lib/data/parser/cxx/ASTAction.cpp b/src/lib/data/parser/cxx/ASTAction.cpp index f87f4dd9..f9efabab 100644 --- a/src/lib/data/parser/cxx/ASTAction.cpp +++ b/src/lib/data/parser/cxx/ASTAction.cpp @@ -21,8 +21,6 @@ std::unique_ptr ASTAction::CreateASTConsumer(clang::Compiler bool ASTAction::BeginSourceFileAction(clang::CompilerInstance& compiler, llvm::StringRef filePath) { - m_client->onFileParsed(filePath.str()); - clang::Preprocessor& preprocessor = compiler.getPreprocessor(); preprocessor.addPPCallbacks( llvm::make_unique(compiler.getSourceManager(), m_client, m_fileRegister)); diff --git a/src/lib/data/parser/cxx/CxxParser.cpp b/src/lib/data/parser/cxx/CxxParser.cpp index 371d6596..6dbcef85 100644 --- a/src/lib/data/parser/cxx/CxxParser.cpp +++ b/src/lib/data/parser/cxx/CxxParser.cpp @@ -1,5 +1,8 @@ #include "data/parser/cxx/CxxParser.h" +#include "clang/Tooling/Tooling.h" + +#include "utility/file/FileManager.h" #include "utility/file/FileRegister.h" #include "utility/logging/logging.h" #include "utility/text/TextAccess.h" @@ -50,7 +53,7 @@ namespace CxxParser::CxxParser(ParserClient* client, const FileManager* fileManager) : Parser(client) - , m_fileManager(fileManager) + , m_fileRegister(std::make_shared(fileManager)) { } @@ -60,70 +63,33 @@ CxxParser::~CxxParser() void CxxParser::parseFiles(const std::vector& filePaths, const Arguments& arguments) { - // Commandline flags passed to the programm. Everything after '--' will be interpreted by the ClangTool. - std::vector args = getCommandlineArguments(arguments); - args.insert(args.begin(), "app"); - args.insert(args.begin() + 1, "--"); - - int argc = args.size(); - const char** argv = new const char*[argc]; - for (size_t i = 0; i < args.size(); i++) - { - argv[i] = args[i].c_str(); - } - - std::shared_ptr compilationDatabase( - clang::tooling::FixedCompilationDatabase::loadFromCommandLine(argc, argv) - ); - - if (!compilationDatabase) - { - LOG_ERROR("Failed to load compilation database"); - return; - } - - FileRegister fileRegister(m_fileManager, filePaths); + setupParsing(filePaths, arguments); std::vector sourcePaths; - for (const FilePath& path : fileRegister.getSourceFilePaths()) + for (const FilePath& path : m_fileRegister->getUnparsedSourceFilePaths()) { sourcePaths.push_back(path.absoluteStr()); } - llvm::IntrusiveRefCntPtr options = new clang::DiagnosticOptions(); - CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, arguments.logErrors); + runTool(sourcePaths); - ASTActionFactory actionFactory(m_client, &fileRegister); - - clang::tooling::ClangTool tool(*compilationDatabase, sourcePaths); - tool.setDiagnosticConsumer(&reporter); - tool.run(&actionFactory); - - std::vector unparsedHeaders = fileRegister.getUnparsedIncludeFilePaths(); + std::vector unparsedHeaders = m_fileRegister->getUnparsedIncludeFilePaths(); for (const FilePath& path : unparsedHeaders) { - if (!fileRegister.includeFileIsParsed(path)) + if (!m_fileRegister->includeFileIsParsed(path)) { - clang::tooling::ClangTool tool(*compilationDatabase, std::vector(1, path.str())); - tool.setDiagnosticConsumer(&reporter); - tool.run(&actionFactory); + runTool(std::vector(1, path.str())); } } - - delete argv; } void CxxParser::parseFile(std::shared_ptr textAccess, const Arguments& arguments) { std::vector args = getCommandlineArguments(arguments); + std::shared_ptr diagnostics = getDiagnostics(arguments); - llvm::IntrusiveRefCntPtr options = new clang::DiagnosticOptions(); - CxxDiagnosticConsumer reporter(llvm::errs(), &*options, m_client, arguments.logErrors); - - FileRegister fileRegister(m_fileManager, std::vector()); - - ASTActionFactory actionFactory(m_client, &fileRegister); - runToolOnCodeWithArgs(&reporter, actionFactory.create(), textAccess->getText(), args); + ASTActionFactory actionFactory(m_client, m_fileRegister.get()); + runToolOnCodeWithArgs(diagnostics.get(), actionFactory.create(), textAccess->getText(), args); } std::vector CxxParser::getCommandlineArguments(const Arguments& arguments) const @@ -165,3 +131,65 @@ std::vector CxxParser::getCommandlineArguments(const Arguments& arg return args; } + +std::shared_ptr CxxParser::getCompilationDatabase( + const Arguments& arguments +) const { + // Commandline flags passed to the programm. Everything after '--' will be interpreted by the ClangTool. + std::vector args = getCommandlineArguments(arguments); + args.insert(args.begin(), "app"); + args.insert(args.begin() + 1, "--"); + + int argc = args.size(); + const char** argv = new const char*[argc]; + for (size_t i = 0; i < args.size(); i++) + { + argv[i] = args[i].c_str(); + } + + std::shared_ptr compilationDatabase( + clang::tooling::FixedCompilationDatabase::loadFromCommandLine(argc, argv) + ); + + delete argv; + + if (!compilationDatabase) + { + LOG_ERROR("Failed to load compilation database"); + return nullptr; + } + + return compilationDatabase; +} + +std::shared_ptr CxxParser::getDiagnostics(const Arguments& arguments) const +{ + llvm::IntrusiveRefCntPtr options = new clang::DiagnosticOptions(); + return std::make_shared(llvm::errs(), &*options, m_client, arguments.logErrors); +} + +void CxxParser::setupParsing(const std::vector& filePaths, const Arguments& arguments) +{ + m_fileRegister->setFilePaths(filePaths); + m_compilationDatabase = getCompilationDatabase(arguments); + m_diagnostics = getDiagnostics(arguments); +} + +void CxxParser::runTool(const std::vector& files) +{ + clang::tooling::ClangTool tool(*m_compilationDatabase, files); + tool.setDiagnosticConsumer(m_diagnostics.get()); + + ASTActionFactory actionFactory(m_client, m_fileRegister.get()); + tool.run(&actionFactory); +} + +FileRegister* CxxParser::getFileRegister() +{ + return m_fileRegister.get(); +} + +ParserClient* CxxParser::getParserClient() +{ + return m_client; +} diff --git a/src/lib/data/parser/cxx/CxxParser.h b/src/lib/data/parser/cxx/CxxParser.h index 10e05886..cc393952 100644 --- a/src/lib/data/parser/cxx/CxxParser.h +++ b/src/lib/data/parser/cxx/CxxParser.h @@ -2,7 +2,19 @@ #define CXX_PARSER_H #include "data/parser/Parser.h" -#include "utility/file/FileManager.h" + +namespace clang +{ + namespace tooling + { + class FixedCompilationDatabase; + } +} + +class CxxDiagnosticConsumer; +class FileManager; +class FileRegister; +class TaskParseCxx; class CxxParser: public Parser { @@ -10,13 +22,29 @@ public: CxxParser(ParserClient* client, const FileManager* fileManager); ~CxxParser(); + // ParserClient implementation virtual void parseFiles(const std::vector& filePaths, const Arguments& arguments); virtual void parseFile(std::shared_ptr textAccess, const Arguments& arguments); private: std::vector getCommandlineArguments(const Arguments& arguments) const; + std::shared_ptr getCompilationDatabase(const Arguments& arguments) const; - const FileManager* m_fileManager; + std::shared_ptr getDiagnostics(const Arguments& arguments) const; + + // Accessed by TaskParseCxx + void setupParsing(const std::vector& filePaths, const Arguments& arguments); + void runTool(const std::vector& files); + + FileRegister* getFileRegister(); + ParserClient* getParserClient(); + + friend class TaskParseCxx; + + std::shared_ptr m_fileRegister; + + std::shared_ptr m_compilationDatabase; + std::shared_ptr m_diagnostics; }; #endif // CXX_PARSER_H diff --git a/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp b/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp index 481831bc..e8074303 100644 --- a/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp +++ b/src/lib/data/parser/cxx/PreprocessorCallbacks.cpp @@ -26,6 +26,7 @@ void PreprocessorCallbacks::FileChanged( const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(m_sourceManager.getFileID(location)); if (fileEntry && m_fileRegister->getFileManager()->hasFilePath(fileEntry->getName())) { + m_client->onFileParsed(fileEntry->getName()); m_fileRegister->markIncludeFileParsing(fileEntry->getName()); } } diff --git a/src/lib/data/parser/cxx/TaskParseCxx.cpp b/src/lib/data/parser/cxx/TaskParseCxx.cpp new file mode 100644 index 00000000..7bcde31c --- /dev/null +++ b/src/lib/data/parser/cxx/TaskParseCxx.cpp @@ -0,0 +1,97 @@ +#include "data/parser/cxx/TaskParseCxx.h" + +#include + +#include "utility/file/FileRegister.h" +#include "utility/messaging/type/MessageFinishedParsing.h" +#include "utility/messaging/type/MessageStatus.h" + +#include "data/parser/ParserClient.h" + +TaskParseCxx::TaskParseCxx( + ParserClient* client, + const FileManager* fileManager, + const Parser::Arguments& arguments, + const std::vector& files +) + : m_parser(client, fileManager) + , m_arguments(arguments) + , m_files(files) +{ +} + +void TaskParseCxx::enter() +{ + m_start = utility::durationStart(); + + m_parser.setupParsing(m_files, m_arguments); + + for (const FilePath& path : m_parser.getFileRegister()->getUnparsedSourceFilePaths()) + { + m_sourcePaths.push(path.absoluteStr()); + } +} + +Task::TaskState TaskParseCxx::update() +{ + std::string sourcePath; + bool isSource = false; + + FileRegister* fileRegister = m_parser.getFileRegister(); + + if (m_sourcePaths.size()) + { + sourcePath = m_sourcePaths.front(); + m_sourcePaths.pop(); + isSource = true; + } + else + { + std::vector unparsedHeaders = fileRegister->getUnparsedIncludeFilePaths(); + if (unparsedHeaders.size()) + { + sourcePath = unparsedHeaders[0].str(); + } + } + + if (!sourcePath.size()) + { + return Task::STATE_FINISHED; + } + + std::stringstream ss; + ss << "parsing (ESC to quit): ["; + ss << fileRegister->getParsedFilesCount() << "/" << fileRegister->getFilesCount() << "] "; + ss << sourcePath; + + MessageStatus(ss.str()).dispatch(); + + m_parser.runTool(std::vector(1, sourcePath)); + + if (isSource) + { + fileRegister->markSourceFileParsed(sourcePath); + } + + return Task::STATE_RUNNING; +} + +void TaskParseCxx::exit() +{ + FileRegister* fileRegister = m_parser.getFileRegister(); + + MessageFinishedParsing( + fileRegister->getParsedFilesCount(), + fileRegister->getFilesCount(), + utility::duration(m_start), + m_parser.getParserClient()->getErrorCount() + ).dispatch(); +} + +void TaskParseCxx::interrupt() +{ +} + +void TaskParseCxx::revert() +{ +} diff --git a/src/lib/data/parser/cxx/TaskParseCxx.h b/src/lib/data/parser/cxx/TaskParseCxx.h new file mode 100644 index 00000000..99a3d658 --- /dev/null +++ b/src/lib/data/parser/cxx/TaskParseCxx.h @@ -0,0 +1,39 @@ +#ifndef TASK_PARSE_CXX_H +#define TASK_PARSE_CXX_H + +#include + +#include "utility/scheduling/Task.h" +#include "utility/utility.h" + +#include "data/parser/cxx/CxxParser.h" + +class TaskParseCxx + : public Task +{ +public: + TaskParseCxx( + ParserClient* client, + const FileManager* fileManager, + const Parser::Arguments& arguments, + const std::vector& files + ); + + virtual void enter(); + virtual TaskState update(); + virtual void exit(); + + virtual void interrupt(); + virtual void revert(); + +private: + CxxParser m_parser; + const Parser::Arguments m_arguments; + const std::vector m_files; + + std::queue m_sourcePaths; + + utility::TimePoint m_start; +}; + +#endif // TASK_PARSE_CXX_H diff --git a/src/lib/utility/file/FileManager.cpp b/src/lib/utility/file/FileManager.cpp index 401f575c..0f4e8c87 100644 --- a/src/lib/utility/file/FileManager.cpp +++ b/src/lib/utility/file/FileManager.cpp @@ -22,6 +22,16 @@ FileManager::~FileManager() { } +const std::vector& FileManager::getSourcePaths() const +{ + return m_sourcePaths; +} + +const std::vector& FileManager::getIncludePaths() const +{ + return m_includePaths; +} + void FileManager::reset() { m_files.clear(); diff --git a/src/lib/utility/file/FileManager.h b/src/lib/utility/file/FileManager.h index e9615b60..8aac62b5 100644 --- a/src/lib/utility/file/FileManager.h +++ b/src/lib/utility/file/FileManager.h @@ -18,6 +18,9 @@ public: ); ~FileManager(); + const std::vector& getSourcePaths() const; + const std::vector& getIncludePaths() const; + void reset(); void fetchFilePaths(); diff --git a/src/lib/utility/file/FileRegister.cpp b/src/lib/utility/file/FileRegister.cpp index c76c1ea1..1a321004 100644 --- a/src/lib/utility/file/FileRegister.cpp +++ b/src/lib/utility/file/FileRegister.cpp @@ -3,14 +3,26 @@ #include "utility/file/FileManager.h" #include "utility/file/FileSystem.h" -FileRegister::FileRegister(const FileManager* fileManager, const std::vector& filePaths) +FileRegister::FileRegister(const FileManager* fileManager) : m_fileManager(fileManager) { +} + +const FileManager* FileRegister::getFileManager() const +{ + return m_fileManager; +} + +void FileRegister::setFilePaths(const std::vector& filePaths) +{ + m_sourceFilePaths.clear(); + m_includeFilePaths.clear(); + for (const FilePath& path : filePaths) { if (m_fileManager->hasSourceExtension(path)) { - m_sourceFilePaths.push_back(path); + m_sourceFilePaths.emplace(path, STATE_UNPARSED); } else { @@ -19,29 +31,14 @@ FileRegister::FileRegister(const FileManager* fileManager, const std::vector FileRegister::getUnparsedSourceFilePaths() const { - return m_fileManager; -} - -const std::vector& FileRegister::getSourceFilePaths() const -{ - return m_sourceFilePaths; + return getUnparsedFilePaths(m_sourceFilePaths); } std::vector FileRegister::getUnparsedIncludeFilePaths() const { - std::vector filePaths; - - for (std::pair&& p : m_includeFilePaths) - { - if (p.second == STATE_UNPARSED) - { - filePaths.push_back(p.first); - } - } - - return filePaths; + return getUnparsedFilePaths(m_includeFilePaths); } bool FileRegister::includeFileIsParsing(const FilePath& filePath) const @@ -66,6 +63,17 @@ bool FileRegister::includeFileIsParsed(const FilePath& filePath) const return it->second == STATE_PARSED; } +void FileRegister::markSourceFileParsed(const std::string& filePath) +{ + std::map::iterator it = m_sourceFilePaths.find(FilePath(filePath)); + if (it == m_sourceFilePaths.end()) + { + return; + } + + it->second = STATE_PARSED; +} + void FileRegister::markIncludeFileParsing(const std::string& filePath) { std::map::iterator it = m_includeFilePaths.find(FilePath(filePath)); @@ -90,3 +98,28 @@ void FileRegister::markParsingIncludeFilesParsed() } } } + +std::vector FileRegister::getUnparsedFilePaths(const std::map filePaths) const +{ + std::vector files; + + for (std::pair&& p : filePaths) + { + if (p.second == STATE_UNPARSED) + { + files.push_back(p.first); + } + } + + return files; +} + +size_t FileRegister::getFilesCount() const +{ + return m_sourceFilePaths.size() + m_includeFilePaths.size(); +} + +size_t FileRegister::getParsedFilesCount() const +{ + return getFilesCount() - getUnparsedSourceFilePaths().size() - getUnparsedIncludeFilePaths().size(); +} diff --git a/src/lib/utility/file/FileRegister.h b/src/lib/utility/file/FileRegister.h index b5aa4865..01038b1c 100644 --- a/src/lib/utility/file/FileRegister.h +++ b/src/lib/utility/file/FileRegister.h @@ -12,19 +12,25 @@ class FileManager; class FileRegister { public: - FileRegister(const FileManager* fileManager, const std::vector& filePaths); + explicit FileRegister(const FileManager* fileManager); const FileManager* getFileManager() const; - const std::vector& getSourceFilePaths() const; + void setFilePaths(const std::vector& filePaths); + + std::vector getUnparsedSourceFilePaths() const; std::vector getUnparsedIncludeFilePaths() const; bool includeFileIsParsing(const FilePath& filePath) const; bool includeFileIsParsed(const FilePath& filePath) const; + void markSourceFileParsed(const std::string& filePath); void markIncludeFileParsing(const std::string& filePath); void markParsingIncludeFilesParsed(); + size_t getFilesCount() const; + size_t getParsedFilesCount() const; + private: enum ParseState { @@ -33,9 +39,11 @@ private: STATE_PARSED }; + std::vector getUnparsedFilePaths(const std::map filePaths) const; + const FileManager* m_fileManager; - std::vector m_sourceFilePaths; + std::map m_sourceFilePaths; std::map m_includeFilePaths; }; diff --git a/src/lib/utility/messaging/type/MessageFinishedParsing.h b/src/lib/utility/messaging/type/MessageFinishedParsing.h index a8f80c6d..1050868c 100644 --- a/src/lib/utility/messaging/type/MessageFinishedParsing.h +++ b/src/lib/utility/messaging/type/MessageFinishedParsing.h @@ -6,8 +6,9 @@ class MessageFinishedParsing: public Message { public: - MessageFinishedParsing(size_t fileCount, float parseTime, size_t errorCount) + MessageFinishedParsing(size_t fileCount, size_t totalFileCount, float parseTime, size_t errorCount) : fileCount(fileCount) + , totalFileCount(totalFileCount) , parseTime(parseTime) , errorCount(errorCount) { @@ -19,6 +20,7 @@ public: } size_t fileCount; + size_t totalFileCount; float parseTime; size_t errorCount; }; diff --git a/src/lib/utility/messaging/type/MessageInterruptTasks.h b/src/lib/utility/messaging/type/MessageInterruptTasks.h new file mode 100644 index 00000000..40c72414 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageInterruptTasks.h @@ -0,0 +1,20 @@ +#ifndef MESSAGE_INTERRUPT_TASKS_H +#define MESSAGE_INTERRUPT_TASKS_H + +#include "utility/messaging/Message.h" + +class MessageInterruptTasks: + public Message +{ +public: + MessageInterruptTasks() + { + } + + static const std::string getStaticType() + { + return "MessageInterruptTasks"; + } +}; + +#endif // MESSAGE_INTERRUPT_TASKS_H diff --git a/src/lib/utility/scheduling/Task.cpp b/src/lib/utility/scheduling/Task.cpp new file mode 100644 index 00000000..37c6230c --- /dev/null +++ b/src/lib/utility/scheduling/Task.cpp @@ -0,0 +1,89 @@ +#include "utility/scheduling/Task.h" + +#include "utility/logging/logging.h" +#include "utility/scheduling/TaskScheduler.h" + +void Task::dispatch(std::shared_ptr task) +{ + TaskScheduler::getInstance()->pushTask(task); +} + +Task::Task() + : m_state(STATE_NEW) +{ +} + +Task::~Task() +{ +} + +Task::TaskState Task::getState() const +{ + return m_state; +} + +Task::TaskState Task::process(bool interruptTask) +{ + if (interruptTask) + { + switch (m_state) + { + case STATE_NEW: + case STATE_CANCELED: + break; + case STATE_RUNNING: + interrupt(); + exit(); + break; + case STATE_FINISHED: + revert(); + break; + } + + setState(STATE_CANCELED); + } + else + { + switch (m_state) + { + case STATE_NEW: + case STATE_CANCELED: + enter(); + case STATE_RUNNING: + { + TaskState newState = update(); + if (newState == STATE_NEW || newState == STATE_CANCELED) + { + LOG_ERROR("Task can't change to state NEW or CANCELLED"); + return m_state; + } + + setState(newState); + if (m_state == STATE_FINISHED) + { + exit(); + } + } + break; + case STATE_FINISHED: + break; + } + } + + return m_state; +} + +void Task::execute() +{ + TaskState state; + do + { + state = process(false); + } + while (state != STATE_FINISHED); +} + +void Task::setState(TaskState state) +{ + m_state = state; +} diff --git a/src/lib/utility/scheduling/Task.h b/src/lib/utility/scheduling/Task.h new file mode 100644 index 00000000..1fca06ae --- /dev/null +++ b/src/lib/utility/scheduling/Task.h @@ -0,0 +1,41 @@ +#ifndef TASK_H +#define TASK_H + +#include + +class Task +{ +public: + enum TaskState + { + STATE_NEW, + STATE_RUNNING, + STATE_FINISHED, + STATE_CANCELED + }; + + static void dispatch(std::shared_ptr task); + + Task(); + virtual ~Task(); + + TaskState getState() const; + + TaskState process(bool interruptTask); + void execute(); + + virtual void enter() = 0; + virtual TaskState update() = 0; + virtual void exit() = 0; + + virtual void interrupt() = 0; + virtual void revert() = 0; + +protected: + void setState(TaskState state); + +private: + TaskState m_state; +}; + +#endif // TASK_H diff --git a/src/lib/utility/scheduling/TaskGroup.cpp b/src/lib/utility/scheduling/TaskGroup.cpp new file mode 100644 index 00000000..54d1db5c --- /dev/null +++ b/src/lib/utility/scheduling/TaskGroup.cpp @@ -0,0 +1,14 @@ +#include "utility/scheduling/TaskGroup.h" + +TaskGroup::TaskGroup() +{ +} + +TaskGroup::~TaskGroup() +{ +} + +void TaskGroup::addTask(std::shared_ptr task) +{ + m_tasks.push_back(task); +} diff --git a/src/lib/utility/scheduling/TaskGroup.h b/src/lib/utility/scheduling/TaskGroup.h new file mode 100644 index 00000000..cd355f94 --- /dev/null +++ b/src/lib/utility/scheduling/TaskGroup.h @@ -0,0 +1,22 @@ +#ifndef TASK_GROUP_H +#define TASK_GROUP_H + +#include +#include + +#include "utility/scheduling/Task.h" + +class TaskGroup + : public Task +{ +public: + TaskGroup(); + virtual ~TaskGroup(); + + void addTask(std::shared_ptr task); + +protected: + std::vector> m_tasks; +}; + +#endif // TASK_GROUP_H diff --git a/src/lib/utility/scheduling/TaskGroupSequential.cpp b/src/lib/utility/scheduling/TaskGroupSequential.cpp new file mode 100644 index 00000000..34a8a3f3 --- /dev/null +++ b/src/lib/utility/scheduling/TaskGroupSequential.cpp @@ -0,0 +1,61 @@ +#include "utility/scheduling/TaskGroupSequential.h" + +TaskGroupSequential::TaskGroupSequential() + : m_taskIndex(-1) +{ +} + +TaskGroupSequential::~TaskGroupSequential() +{ +} + +void TaskGroupSequential::enter() +{ +} + +Task::TaskState TaskGroupSequential::update() +{ + if (!m_tasks.size()) + { + return Task::STATE_FINISHED; + } + + if (m_taskIndex < 0 || m_tasks[m_taskIndex]->getState() != Task::STATE_RUNNING) + { + m_taskIndex++; + } + + std::shared_ptr task = m_tasks[m_taskIndex]; + + TaskState state = task->process(false); + + if (state == Task::STATE_FINISHED && size_t(m_taskIndex + 1) == m_tasks.size()) + { + return Task::STATE_FINISHED; + } + + return Task::STATE_RUNNING; +} + +void TaskGroupSequential::exit() +{ +} + +void TaskGroupSequential::interrupt() +{ + if (m_taskIndex > 0 && size_t(m_taskIndex) < m_tasks.size()) + { + for (int i = m_taskIndex; i >= 0; i--) + { + m_tasks[m_taskIndex]->process(true); + } + } +} + +void TaskGroupSequential::revert() +{ + for (int i = m_tasks.size() - 1; i >= 0; i--) + { + m_tasks[m_taskIndex]->process(true); + } +} diff --git a/src/lib/utility/scheduling/TaskGroupSequential.h b/src/lib/utility/scheduling/TaskGroupSequential.h new file mode 100644 index 00000000..f71461ed --- /dev/null +++ b/src/lib/utility/scheduling/TaskGroupSequential.h @@ -0,0 +1,24 @@ +#ifndef TASK_GROUP_SEQUENTIAL_H +#define TASK_GROUP_SEQUENTIAL_H + +#include "utility/scheduling/TaskGroup.h" + +class TaskGroupSequential + : public TaskGroup +{ +public: + TaskGroupSequential(); + virtual ~TaskGroupSequential(); + + virtual void enter(); + virtual TaskState update(); + virtual void exit(); + + virtual void interrupt(); + virtual void revert(); + +private: + int m_taskIndex; +}; + +#endif // TASK_GROUP_SEQUENTIAL_H diff --git a/src/lib/utility/scheduling/TaskScheduler.cpp b/src/lib/utility/scheduling/TaskScheduler.cpp new file mode 100644 index 00000000..3269d0bb --- /dev/null +++ b/src/lib/utility/scheduling/TaskScheduler.cpp @@ -0,0 +1,132 @@ +#include "utility/scheduling/TaskScheduler.h" + +#include +#include + +#include "utility/logging/logging.h" +#include "utility/messaging/type/MessageStatus.h" + +std::shared_ptr TaskScheduler::getInstance() +{ + if (!s_instance) + { + s_instance = std::shared_ptr(new TaskScheduler()); + } + + return s_instance; +} + +void TaskScheduler::pushTask(std::shared_ptr task) +{ + std::lock_guard lock(m_tasksMutex); + m_tasks.push(task); +} + +void TaskScheduler::interruptCurrentTask() +{ + std::lock_guard lock(m_tasksMutex); + m_interruptTask = true; +} + +void TaskScheduler::startSchedulerLoopThreaded() +{ + std::thread(&TaskScheduler::startSchedulerLoop, this).detach(); +} + +void TaskScheduler::startSchedulerLoop() +{ + { + std::lock_guard lock(m_loopMutex); + + if (m_loopIsRunning) + { + LOG_ERROR("Loop is already running"); + return; + } + + m_loopIsRunning = true; + } + + while (true) + { + { + std::lock_guard lock(m_loopMutex); + + if (!m_loopIsRunning) + { + return; + } + } + + updateTasks(); + + const int SLEEP_TIME_MS = 25; + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_MS)); + } +} + +void TaskScheduler::stopSchedulerLoop() +{ + { + std::lock_guard lock(m_loopMutex); + + if (!m_loopIsRunning) + { + LOG_WARNING("Loop is not running"); + } + + m_loopIsRunning = false; + } + + interruptCurrentTask(); +} + +bool TaskScheduler::loopIsRunning() const +{ + std::lock_guard lock(m_loopMutex); + return m_loopIsRunning; +} + +std::shared_ptr TaskScheduler::s_instance; + +TaskScheduler::TaskScheduler() + : m_loopIsRunning(false) + , m_interruptTask(false) +{ +} + +void TaskScheduler::updateTasks() +{ + std::lock_guard lock(m_tasksMutex); + + bool interrupt = m_interruptTask; + + while (m_tasks.size()) + { + std::shared_ptr task = m_tasks.front(); + + m_tasksMutex.unlock(); + Task::TaskState state = task->process(interrupt); + m_tasksMutex.lock(); + + if (state == Task::STATE_FINISHED || state == Task::STATE_CANCELED) + { + m_tasks.pop(); + } + + interrupt = m_interruptTask; + } + + m_interruptTask = false; +} + +void TaskScheduler::handleMessage(MessageInterruptTasks* message) +{ + interruptCurrentTask(); + + std::lock_guard lock(m_tasksMutex); + if (m_tasks.size()) + { + MessageStatus("Stop running tasks...").dispatch(); + } +} diff --git a/src/lib/utility/scheduling/TaskScheduler.h b/src/lib/utility/scheduling/TaskScheduler.h new file mode 100644 index 00000000..8957fb11 --- /dev/null +++ b/src/lib/utility/scheduling/TaskScheduler.h @@ -0,0 +1,47 @@ +#ifndef TASK_SCHEDULER_H +#define TASK_SCHEDULER_H + +#include +#include +#include + +#include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageInterruptTasks.h" +#include "utility/scheduling/Task.h" + +class TaskScheduler + : public MessageListener +{ +public: + static std::shared_ptr getInstance(); + + void pushTask(std::shared_ptr task); + void interruptCurrentTask(); + + void startSchedulerLoopThreaded(); + void startSchedulerLoop(); + void stopSchedulerLoop(); + + bool loopIsRunning() const; + +private: + static std::shared_ptr s_instance; + + TaskScheduler(); + TaskScheduler(const TaskScheduler&); + void operator=(const TaskScheduler&); + + void updateTasks(); + + virtual void handleMessage(MessageInterruptTasks* message); + + bool m_loopIsRunning; + + std::queue> m_tasks; + bool m_interruptTask; + + mutable std::mutex m_tasksMutex; + mutable std::mutex m_loopMutex; +}; + +#endif // TASK_SCHEDULER_H diff --git a/src/lib/utility/utility.cpp b/src/lib/utility/utility.cpp index 18c9eb47..3078f296 100644 --- a/src/lib/utility/utility.cpp +++ b/src/lib/utility/utility.cpp @@ -1,16 +1,26 @@ #include "utility/utility.h" -float utility::duration(std::function func) +utility::TimePoint utility::durationStart() { - std::chrono::time_point start = std::chrono::system_clock::now(); - - func(); + return std::chrono::system_clock::now(); +} +float utility::duration(const TimePoint& start) +{ std::chrono::duration duration = std::chrono::duration_cast(std::chrono::system_clock::now() - start); return duration.count(); } +float utility::duration(std::function func) +{ + const TimePoint start = durationStart(); + + func(); + + return duration(start); +} + bool utility::intersectionPoint(Vec2f a1, Vec2f b1, Vec2f a2, Vec2f b2, Vec2f* i) { Vec2f p = a1; diff --git a/src/lib/utility/utility.h b/src/lib/utility/utility.h index 785b7b7a..263d16ce 100644 --- a/src/lib/utility/utility.h +++ b/src/lib/utility/utility.h @@ -8,6 +8,10 @@ namespace utility { + typedef std::chrono::time_point TimePoint; + + TimePoint durationStart(); + float duration(const TimePoint& start); float duration(std::function func); template diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index a757a990..8d3ed80d 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -2405,7 +2405,7 @@ public: TS_ASSERT_EQUALS(client.usages.size(), 3); TS_ASSERT_EQUALS(client.typeUses.size(), 8); - TS_ASSERT_EQUALS(client.files.size(), 2); + TS_ASSERT_EQUALS(client.files.size(), 3); TS_ASSERT_EQUALS(client.includes.size(), 1); } @@ -2429,6 +2429,11 @@ private: errors.push_back(addLocationSuffix(message, location)); } + virtual size_t getErrorCount() const + { + return 0; + } + virtual Id onTypedefParsed( const ParseLocation& location, const NameHierarchy& nameHierarchy, const ParseTypeUsage& underlyingType, AccessType access