diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2019-08-06 14:46:37 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2019-08-09 12:45:29 +0000 |
commit | 09530d6dcc0fdbdf27d04c63149eb285e122d9dc (patch) | |
tree | 5f33e1bd1d04fb258251f74057f24ab96fe6fdd7 /src | |
parent | 8868989d5c72cd57e5068481198ffa0af4cb4bb0 (diff) |
ProjectExplorer: Use RAII pattern for parsing start/stop signalling
Change-Id: I13de537140f265db3e3d0ab1cd924d6897cd90c8
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src')
18 files changed, 143 insertions, 69 deletions
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index fa9c33f46a..6173c33415 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -112,7 +112,6 @@ Project::RestoreResult AutotoolsProject::fromMap(const QVariantMap &map, QString void AutotoolsProject::loadProjectTree() { - emitParsingStarted(); if (m_makefileParserThread) { // The thread is still busy parsing a previus configuration. // Wait until the thread has been finished and delete it. @@ -125,7 +124,8 @@ void AutotoolsProject::loadProjectTree() } // Parse the makefile asynchronously in a thread - m_makefileParserThread = new MakefileParserThread(projectFilePath().toString()); + m_makefileParserThread = new MakefileParserThread(projectFilePath().toString(), + guardParsingRun()); connect(m_makefileParserThread, &MakefileParserThread::started, this, &AutotoolsProject::makefileParsingStarted); @@ -212,8 +212,6 @@ void AutotoolsProject::makefileParsingFinished() m_makefileParserThread->deleteLater(); m_makefileParserThread = nullptr; - - emitParsingFinished(true); } void AutotoolsProject::onFileChanged(const QString &file) diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp index a33d39599b..fa225f6945 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp +++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp @@ -31,7 +31,10 @@ using namespace AutotoolsProjectManager::Internal; -MakefileParserThread::MakefileParserThread(const QString &makefile) : m_parser(makefile) +MakefileParserThread::MakefileParserThread(const QString &makefile, + ProjectExplorer::Project::ParseGuard &&guard) + : m_parser(makefile) + , m_guard(std::move(guard)) { connect(&m_parser, &MakefileParser::status, this, &MakefileParserThread::status); @@ -82,7 +85,7 @@ QStringList MakefileParserThread::cxxflags() const bool MakefileParserThread::hasError() const { QMutexLocker locker(&m_mutex); - return m_hasError; + return !m_guard.isSuccess(); } bool MakefileParserThread::isCanceled() const @@ -104,7 +107,8 @@ void MakefileParserThread::run() // this prevents long locks if the caller reads a value before the signal // finished() has been emitted. QMutexLocker locker(&m_mutex); - m_hasError = !success; + if (success) + m_guard.markAsSuccess(); m_executable = m_parser.executable(); m_sources = m_parser.sources(); m_makefiles = m_parser.makefiles(); diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.h b/src/plugins/autotoolsprojectmanager/makefileparserthread.h index fa300e8d35..63d86190e2 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparserthread.h +++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.h @@ -29,6 +29,7 @@ #include "makefileparser.h" +#include <projectexplorer/project.h> #include <projectexplorer/projectmacro.h> #include <QMutex> @@ -53,7 +54,7 @@ class MakefileParserThread : public QThread using Macros = ProjectExplorer::Macros; public: - MakefileParserThread(const QString &makefile); + MakefileParserThread(const QString &makefile, ProjectExplorer::Project::ParseGuard &&guard); /** @see QThread::run() */ void run() override; @@ -134,7 +135,6 @@ private: MakefileParser m_parser; ///< Is not accessible outside the thread mutable QMutex m_mutex; - bool m_hasError = false; ///< Return value for MakefileParserThread::hasError() QString m_executable; ///< Return value for MakefileParserThread::executable() QStringList m_sources; ///< Return value for MakefileParserThread::sources() QStringList m_makefiles; ///< Return value for MakefileParserThread::makefiles() @@ -142,6 +142,8 @@ private: Macros m_macros; ///< Return value for MakefileParserThread::macros() QStringList m_cflags; ///< Return value for MakefileParserThread::cflags() QStringList m_cxxflags; ///< Return value for MakefileParserThread::cxxflags() + + ProjectExplorer::Project::ParseGuard m_guard; }; } // namespace Internal diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index f7fd54feac..bbfcd41f66 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -371,7 +371,7 @@ void CMakeProject::startParsing(int reparseParameters) CMakeBuildConfiguration *bc = activeBc(this); QTC_ASSERT(bc, return ); - emitParsingStarted(); + m_parseGuard = std::move(guardParsingRun()); m_waitingForScan = reparseParameters & BuildDirManager::REPARSE_SCAN; m_waitingForParse = true; @@ -466,12 +466,14 @@ void CMakeProject::combineScanAndParse(CMakeBuildConfiguration *bc) if (m_waitingForParse || m_waitingForScan) return; - if (m_combinedScanAndParseResult) + if (m_combinedScanAndParseResult) { + m_parseGuard.markAsSuccess(); updateProjectData(bc); + } { TraceTimer parsingDoneTimer(" parsing finished signal"); - emitParsingFinished(m_combinedScanAndParseResult); + m_parseGuard = {}; } } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index dd84b2724a..645deacf8d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -121,6 +121,8 @@ private: QTimer m_delayedParsingTimer; int m_delayedParsingParameters = 0; + ParseGuard m_parseGuard; + friend class Internal::CMakeBuildConfiguration; friend class Internal::CMakeBuildSettingsWidget; }; diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index a2d99b276e..a601f3d3a9 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -450,17 +450,18 @@ void CompilationDatabaseProject::reparseProject() if (m_parser) { QTC_CHECK(isParsing()); m_parser->stop(); - emitParsingFinished(false); } - m_parser = new CompilationDbParser(displayName(), projectFilePath(), rootPathFromSettings(), - m_mimeBinaryCache, this); + m_parser = new CompilationDbParser(displayName(), + projectFilePath(), + rootPathFromSettings(), + m_mimeBinaryCache, + guardParsingRun(), + this); connect(m_parser, &CompilationDbParser::finished, this, [this](bool success) { if (success) buildTreeAndProjectParts(); m_parser = nullptr; - emitParsingFinished(success); }); - emitParsingStarted(); m_parser->start(); } diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp index d75bf7be40..6c91311898 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp @@ -43,14 +43,18 @@ using namespace Utils; namespace CompilationDatabaseProjectManager { namespace Internal { -CompilationDbParser::CompilationDbParser(const QString &projectName, const FilePath &projectPath, - const FilePath &rootPath, MimeBinaryCache &mimeBinaryCache, +CompilationDbParser::CompilationDbParser(const QString &projectName, + const FilePath &projectPath, + const FilePath &rootPath, + MimeBinaryCache &mimeBinaryCache, + ProjectExplorer::Project::ParseGuard &&guard, QObject *parent) - : QObject(parent), - m_projectName(projectName), - m_projectFilePath(projectPath), - m_rootPath(rootPath), - m_mimeBinaryCache(mimeBinaryCache) + : QObject(parent) + , m_projectName(projectName) + , m_projectFilePath(projectPath) + , m_rootPath(rootPath) + , m_mimeBinaryCache(mimeBinaryCache) + , m_guard(std::move(guard)) { connect(&m_parserWatcher, &QFutureWatcher<void>::finished, this, [this] { m_dbContents = m_parserWatcher.result(); @@ -112,6 +116,7 @@ void CompilationDbParser::stop() m_treeScanner->disconnect(); m_treeScanner->future().cancel(); } + m_guard = {}; deleteLater(); } diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h index ded713d590..fe3e319076 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.h @@ -27,6 +27,8 @@ #include "compilationdatabaseutils.h" +#include <projectexplorer/project.h> + #include <utils/fileutils.h> #include <QFutureWatcher> @@ -48,15 +50,22 @@ class CompilationDbParser : public QObject { Q_OBJECT public: - explicit CompilationDbParser(const QString &projectName, const Utils::FilePath &projectPath, - const Utils::FilePath &rootPath, MimeBinaryCache &mimeBinaryCache, + explicit CompilationDbParser(const QString &projectName, + const Utils::FilePath &projectPath, + const Utils::FilePath &rootPath, + MimeBinaryCache &mimeBinaryCache, + ProjectExplorer::Project::ParseGuard &&guard, QObject *parent = nullptr); void start(); void stop(); QList<ProjectExplorer::FileNode *> scannedFiles() const; - DbContents dbContents() const { return m_dbContents; } + DbContents dbContents() const + { + m_guard.markAsSuccess(); + return m_dbContents; + } signals: void finished(bool success); @@ -72,6 +81,8 @@ private: ProjectExplorer::TreeScanner *m_treeScanner = nullptr; QFutureWatcher<DbContents> m_parserWatcher; DbContents m_dbContents; + + ProjectExplorer::Project::ParseGuard m_guard; }; } // namespace Internal diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index ce4172abed..e25fa77eb8 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -409,7 +409,7 @@ FilePath GenericProject::findCommonSourceRoot() void GenericProject::refresh(RefreshOptions options) { - emitParsingStarted(); + ParseGuard guard = guardParsingRun(); parseProject(options); if (options & Files) { @@ -442,7 +442,7 @@ void GenericProject::refresh(RefreshOptions options) refreshCppCodeModel(); updateDeploymentData(); - emitParsingFinished(true); + guard.markAsSuccess(); } /** diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index a6cad1657f..9a732f92ae 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -135,7 +135,7 @@ void NimProject::collectProjectFiles() void NimProject::updateProject() { - emitParsingStarted(); + ParseGuard guard = guardParsingRun(); auto newRoot = std::make_unique<NimProjectNode>(*this, projectDirectory()); @@ -147,7 +147,7 @@ void NimProject::updateProject() newRoot->setDisplayName(displayName()); setRootProjectNode(std::move(newRoot)); - emitParsingFinished(true); + guard.markAsSuccess(); } Tasks NimProject::projectIssues(const Kit *k) const diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index b18ba3f6bc..879fedcb0d 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -1014,15 +1014,6 @@ public: setDisplayName(TEST_PROJECT_DISPLAYNAME); } - void testStartParsing() - { - emitParsingStarted(); - } - - void testParsingFinished(bool success) { - emitParsingFinished(success); - } - bool needsConfiguration() const final { return false; } }; @@ -1081,14 +1072,17 @@ void ProjectExplorerPlugin::testProject_parsingSuccess() QSignalSpy startSpy(&project, &Project::parsingStarted); QSignalSpy stopSpy(&project, &Project::parsingFinished); - project.testStartParsing(); - QCOMPARE(startSpy.count(), 1); - QCOMPARE(stopSpy.count(), 0); + { + Project::ParseGuard guard = project.guardParsingRun(); + QCOMPARE(startSpy.count(), 1); + QCOMPARE(stopSpy.count(), 0); - QVERIFY(project.isParsing()); - QVERIFY(!project.hasParsingData()); + QVERIFY(project.isParsing()); + QVERIFY(!project.hasParsingData()); + + guard.markAsSuccess(); + } - project.testParsingFinished(true); QCOMPARE(startSpy.count(), 1); QCOMPARE(stopSpy.count(), 1); QCOMPARE(stopSpy.at(0), {QVariant(true)}); @@ -1104,14 +1098,15 @@ void ProjectExplorerPlugin::testProject_parsingFail() QSignalSpy startSpy(&project, &Project::parsingStarted); QSignalSpy stopSpy(&project, &Project::parsingFinished); - project.testStartParsing(); - QCOMPARE(startSpy.count(), 1); - QCOMPARE(stopSpy.count(), 0); + { + Project::ParseGuard guard = project.guardParsingRun(); + QCOMPARE(startSpy.count(), 1); + QCOMPARE(stopSpy.count(), 0); - QVERIFY(project.isParsing()); - QVERIFY(!project.hasParsingData()); + QVERIFY(project.isParsing()); + QVERIFY(!project.hasParsingData()); + } - project.testParsingFinished(false); QCOMPARE(startSpy.count(), 1); QCOMPARE(stopSpy.count(), 1); QCOMPARE(stopSpy.at(0), {QVariant(false)}); diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 1eeece2646..b5de003a53 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -204,6 +204,51 @@ public: bool needsInitialExpansion() const; void setNeedsInitialExpansion(bool needsInitialExpansion); + class ParseGuard + { + public: + ParseGuard() + : ParseGuard(nullptr) + {} + + ~ParseGuard() + { + if (m_project) + m_project->emitParsingFinished(m_success); + } + + void markAsSuccess() const { m_success = true; } + bool isSuccess() const { return m_success; } + bool isNull() const { return !m_project; } + + ParseGuard(const ParseGuard &other) = delete; + ParseGuard &operator=(const ParseGuard &other) = delete; + ParseGuard(ParseGuard &&other) + { + std::swap(m_project, other.m_project); + std::swap(m_success, other.m_success); + } + ParseGuard &operator=(ParseGuard &&other) + { + std::swap(m_project, other.m_project); + std::swap(m_success, other.m_success); + return *this; + } + + private: + ParseGuard(Project *p) + : m_project(p) + { + if (m_project) + m_project->emitParsingStarted(); + } + + Project *m_project = nullptr; + mutable bool m_success = false; + + friend class Project; + }; + signals: void displayNameChanged(); void fileListChanged(); @@ -235,16 +280,12 @@ signals: void rootProjectDirectoryChanged(); protected: + ParseGuard guardParsingRun() { return ParseGuard(this); } + virtual RestoreResult fromMap(const QVariantMap &map, QString *errorMessage); void createTargetFromMap(const QVariantMap &map, int index); virtual bool setupTarget(Target *t); - // Helper methods to manage parsing state and signalling - // Call in GUI thread before the actual parsing starts - void emitParsingStarted(); - // Call in GUI thread right after the actual parsing is done - void emitParsingFinished(bool success); - void setDisplayName(const QString &name); // Used to pre-check kits in the TargetSetupPage. RequiredKitPredicate // is used to select kits available in the TargetSetupPage @@ -270,6 +311,12 @@ protected: Utils::Environment activeBuildEnvironment() const; private: + // Helper methods to manage parsing state and signalling + // Call in GUI thread before the actual parsing starts + void emitParsingStarted(); + // Call in GUI thread right after the actual parsing is done + void emitParsingFinished(bool success); + void addTarget(std::unique_ptr<Target> &&target); void handleSubTreeChanged(FolderNode *node); diff --git a/src/plugins/python/pythonplugin.cpp b/src/plugins/python/pythonplugin.cpp index 657e6269bc..0aae69d905 100644 --- a/src/plugins/python/pythonplugin.cpp +++ b/src/plugins/python/pythonplugin.cpp @@ -634,7 +634,7 @@ private: void PythonProject::refresh(Target *target) { - emitParsingStarted(); + ParseGuard guard = guardParsingRun(); parseProject(); const QDir baseDir(projectDirectory().toString()); @@ -661,7 +661,7 @@ void PythonProject::refresh(Target *target) if (target) target->setApplicationTargets(appTargets); - emitParsingFinished(true); + guard.markAsSuccess(); } /** diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index f9607429e7..684c83648f 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -463,7 +463,7 @@ bool QbsProject::checkCancelStatus() qCDebug(qbsPmLog) << "Cancel request while parsing, starting re-parse"; m_qbsProjectParser->deleteLater(); m_qbsProjectParser = nullptr; - emitParsingFinished(false); + m_guard = {}; parseCurrentBuildConfiguration(); return true; } @@ -551,7 +551,8 @@ void QbsProject::handleQbsParsingDone(bool success) updateAfterParse(); else if (envChanged) updateCppCodeModel(); - emitParsingFinished(success); + m_guard.markAsSuccess(); + m_guard = {}; } void QbsProject::rebuildProjectTree() @@ -729,6 +730,8 @@ void QbsProject::configureAsExampleProject() void QbsProject::parse(const QVariantMap &config, const Environment &env, const QString &dir, const QString &configName) { + m_guard = guardParsingRun(); + prepareForParsing(); QTC_ASSERT(!m_qbsProjectParser, return); @@ -736,7 +739,6 @@ void QbsProject::parse(const QVariantMap &config, const Environment &env, const QbsManager::updateProfileIfNecessary(activeTarget()->kit()); m_qbsProjectParser->parse(config, env, dir, configName); - emitParsingStarted(); } void QbsProject::prepareForParsing() diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h index fba99a5f90..c4afe84de2 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.h +++ b/src/plugins/qbsprojectmanager/qbsproject.h @@ -167,6 +167,8 @@ private: bool m_extraCompilersPending = false; QHash<QString, Utils::Environment> m_envCache; + + ParseGuard m_guard; }; } // namespace Internal diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 281f88de57..3e5496b546 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -438,15 +438,15 @@ void QmakeProject::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay) m_asyncUpdateTimer.stop(); m_asyncUpdateTimer.setInterval(qMin(m_asyncUpdateTimer.interval(), delay == QmakeProFile::ParseLater ? UPDATE_INTERVAL : 0)); - if (!isParsing()) - emitParsingStarted(); + m_asyncUpdateTimer.start(); } void QmakeProject::incrementPendingEvaluateFutures() { + if (m_pendingEvaluateFuturesCount == 0) + m_guard = guardParsingRun(); ++m_pendingEvaluateFuturesCount; - QTC_ASSERT(isParsing(), emitParsingStarted()); m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(), m_asyncUpdateFutureInterface->progressMaximum() + 1); } @@ -486,7 +486,8 @@ void QmakeProject::decrementPendingEvaluateFutures() updateBuildSystemData(); if (activeTarget()) activeTarget()->updateDefaultDeployConfigurations(); - emitParsingFinished(true); // Qmake always returns (some) data, even when it failed:-) + m_guard.markAsSuccess(); // Qmake always returns (some) data, even when it failed:-) + m_guard = {}; } } } diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h index 4c3169716b..584e16a15e 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.h +++ b/src/plugins/qmakeprojectmanager/qmakeproject.h @@ -179,6 +179,8 @@ private: ProjectExplorer::Target *m_activeTarget = nullptr; mutable ProjectExplorer::ProjectImporter *m_projectImporter = nullptr; + + ParseGuard m_guard; }; } // namespace QmakeProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 2dd251d2a5..8bfc42911e 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -152,7 +152,7 @@ void QmlProject::parseProject(RefreshOptions options) void QmlProject::refresh(RefreshOptions options) { - emitParsingStarted(); + ParseGuard guard = guardParsingRun(); parseProject(options); if (options & Files) @@ -170,7 +170,7 @@ void QmlProject::refresh(RefreshOptions options) modelManager->updateProjectInfo(projectInfo, this); - emitParsingFinished(true); + guard.markAsSuccess(); } QString QmlProject::mainFile() const |