aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.cpp44
-rw-r--r--src/libs/qmljs/qmljsmodelmanagerinterface.h7
-rw-r--r--src/libs/qmljs/qmljsplugindumper.cpp9
-rw-r--r--src/plugins/qmljstools/qmljstools_test.cpp2
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);