diff options
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 44 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsmodelmanagerinterface.h | 7 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsplugindumper.cpp | 9 | ||||
-rw-r--r-- | src/plugins/qmljstools/qmljstools_test.cpp | 2 |
4 files changed, 48 insertions, 14 deletions
diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index c7c034975d..3376cc3762 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -306,6 +306,7 @@ void ModelManagerInterface::updateSourceFiles(const QStringList &files, void ModelManagerInterface::cleanupFutures() { + QMutexLocker lock(&m_futuresMutex); const int maxFutures = 10; if (m_futures.size() > maxFutures) { const QList<QFuture<void>> futures = m_futures; @@ -327,8 +328,7 @@ QFuture<void> ModelManagerInterface::refreshSourceFiles(const QStringList &sourc workingCopyInternal(), sourceFiles, this, Dialect(Dialect::Qml), emitDocumentOnDiskChanged); - cleanupFutures(); - m_futures.append(result); + addFuture(result); if (sourceFiles.count() > 1) addTaskInternal(result, tr("Parsing QML Files"), Constants::TASK_INDEX); @@ -1137,9 +1137,7 @@ void ModelManagerInterface::maybeScan(const PathsAndLanguages &importPaths) QFuture<void> result = Utils::runAsync(&ModelManagerInterface::importScan, workingCopyInternal(), pathToScan, this, true, true, false); - cleanupFutures(); - m_futures.append(result); - + addFuture(result); addTaskInternal(result, tr("Scanning QML Imports"), Constants::TASK_IMPORT_SCAN); } } @@ -1536,13 +1534,43 @@ void ModelManagerInterface::setDefaultVContext(const ViewerContext &vContext) m_defaultVContexts[vContext.language] = vContext; } -void ModelManagerInterface::joinAllThreads() +void ModelManagerInterface::test_joinAllThreads() { - for (QFuture<void> &future : m_futures) - future.waitForFinished(); + // Loop since futures can spawn more futures as they finish. + while (true) { + QFuture<void> f; + // get one future + { + QMutexLocker lock(&m_futuresMutex); + for (QFuture<void> &future : m_futures) { + if (!future.isFinished() && !future.isCanceled()) { + f = future; + break; + } + } + } + if (!f.isFinished() && !f.isCanceled()) { + f.waitForFinished(); + + // Some futures trigger more futures from connected signals + // and in tests, we care about finishing all of these too. + QEventLoop().processEvents(); + } else { + break; + } + } m_futures.clear(); } +void ModelManagerInterface::addFuture(const QFuture<void> &future) +{ + { + QMutexLocker lock(&m_futuresMutex); + m_futures.append(future); + } + cleanupFutures(); +} + Document::Ptr ModelManagerInterface::ensuredGetDocumentForPath(const QString &filePath) { QmlJS::Document::Ptr document = newestSnapshot().document(filePath); diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.h b/src/libs/qmljs/qmljsmodelmanagerinterface.h index 4337adcb79..8e8b9d2a24 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.h +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.h @@ -179,8 +179,9 @@ public: virtual ProjectInfo defaultProjectInfoForProject(ProjectExplorer::Project *project) const; - // Blocks until all parsing threads are done. Used for testing. - void joinAllThreads(); + // Blocks until all parsing threads are done. Use for testing only! + void test_joinAllThreads(); + void addFuture(const QFuture<void> &future); QmlJS::Document::Ptr ensuredGetDocumentForPath(const QString &filePath); static void importScan(QFutureInterface<void> &future, const WorkingCopy& workingCopyInternal, @@ -271,7 +272,9 @@ private: PluginDumper *m_pluginDumper = nullptr; + mutable QMutex m_futuresMutex; QList<QFuture<void>> m_futures; + bool m_indexerDisabled = false; }; diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp index b945c58f3a..de26d7435a 100644 --- a/src/libs/qmljs/qmljsplugindumper.cpp +++ b/src/libs/qmljs/qmljsplugindumper.cpp @@ -305,7 +305,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode) future.reportFinished(&infos); }); - Utils::onFinished(future, this, + auto finalFuture = Utils::onFinished(future, this, [this, libraryInfo, privatePlugin, libraryPath] (const QFuture<CppQmlTypesInfo>& future) { CppQmlTypesInfo infos = future.result(); @@ -329,6 +329,7 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode) m_modelManager->updateLibraryInfo(libraryPath, libInfo); }); + m_modelManager->addFuture(finalFuture); } else { libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpDone); libraryInfo.updateFingerprint(); @@ -525,12 +526,12 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, const QString &libraryPath, QmlJS::LibraryInfo libraryInfo) { - Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this, [=](const QFuture<PluginDumper::QmlTypeDescription> &typesFuture) + auto future = Utils::onFinished(loadQmlTypeDescription(qmltypesFilePaths), this, [=](const QFuture<PluginDumper::QmlTypeDescription> &typesFuture) { PluginDumper::QmlTypeDescription typesResult = typesFuture.result(); if (!typesResult.dependencies.isEmpty()) { - Utils::onFinished(loadDependencies(typesResult.dependencies, QSharedPointer<QSet<QString>>()), this, + auto depFuture = Utils::onFinished(loadDependencies(typesResult.dependencies, QSharedPointer<QSet<QString>>()), this, [typesResult, libraryInfo, libraryPath, this] (const QFuture<PluginDumper::DependencyInfo> &loadFuture) { PluginDumper::DependencyInfo loadResult = loadFuture.result(); @@ -548,6 +549,7 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, typesResult.moduleApis, objects); m_modelManager->updateLibraryInfo(libraryPath, libInfo); }); + m_modelManager->addFuture(depFuture); } else { QmlJS::LibraryInfo libInfo = libraryInfo; prepareLibraryInfo(libInfo, libraryPath, typesResult.dependencies, @@ -556,6 +558,7 @@ void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, m_modelManager->updateLibraryInfo(libraryPath, libInfo); } }); + m_modelManager->addFuture(future); } void PluginDumper::runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, diff --git a/src/plugins/qmljstools/qmljstools_test.cpp b/src/plugins/qmljstools/qmljstools_test.cpp index 9db7c7ef7a..ab8a09abae 100644 --- a/src/plugins/qmljstools/qmljstools_test.cpp +++ b/src/plugins/qmljstools/qmljstools_test.cpp @@ -45,7 +45,7 @@ void QmlJSToolsPlugin::test_basic() const QString qmlFilePath = Core::ICore::resourcePath() + QLatin1String("/qmldesigner/itemLibraryQmlSources/ItemDelegate.qml"); modelManager->updateSourceFiles(QStringList(qmlFilePath), false); - modelManager->joinAllThreads(); + modelManager->test_joinAllThreads(); Snapshot snapshot = modelManager->snapshot(); Document::Ptr doc = snapshot.document(qmlFilePath); |