Only in src/libs/qmljs: Makefile --- ../qt-creator-opensource-src-4.10.0/src/libs/qmljs/qmljsinterpreter.h +++ src/libs/qmljs/qmljsinterpreter.h @@ -719,6 +719,14 @@ static BuiltinObjects defaultQtObjects; static BuiltinObjects defaultLibraryObjects; + typedef struct { + BuiltinObjects *newObjects; + QList *newModuleApis; + QStringList *newDependencies; + QString *errorMessage; + QString *warningMessage; + } CppQmlTypesInfo; + // parses the contents of a qmltypes file and fills the newObjects map static void parseQmlTypeDescriptions(const QByteArray &contents, BuiltinObjects *newObjects, --- ../qt-creator-opensource-src-4.10.0/src/libs/qmljs/qmljsplugindumper.cpp +++ src/libs/qmljs/qmljsplugindumper.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -281,32 +282,55 @@ } const QByteArray output = process->readAllStandardOutput(); - QString error; - QString warning; - CppQmlTypesLoader::BuiltinObjects objectsList; - QList moduleApis; - QStringList dependencies; - CppQmlTypesLoader::parseQmlTypeDescriptions(output, &objectsList, &moduleApis, &dependencies, - &error, &warning, - QLatin1String("')); - if (exitCode == 0) { - if (!error.isEmpty()) { - libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, - qmldumpErrorMessage(libraryPath, error)); - if (!privatePlugin) - printParseWarnings(libraryPath, libraryInfo.pluginTypeInfoError()); - } else { - libraryInfo.setMetaObjects(objectsList.values()); - libraryInfo.setModuleApis(moduleApis); - libraryInfo.setPluginTypeInfoStatus(LibraryInfo::DumpDone); + + class Infos { + public: + QString error; + QString warning; + CppQmlTypesLoader::BuiltinObjects objectsList; + QList moduleApis; + QStringList dependencies; + }; + + auto watcher = new QFutureWatcher(this); + + connect(watcher, &QFutureWatcher::finished, this, [this, exitCode, libraryInfo, privatePlugin, libraryPath, watcher] { + Infos infos = watcher->result(); + + LibraryInfo libInfo = libraryInfo; + + if (exitCode == 0) { + + if (!infos.error.isEmpty()) { + libInfo.setPluginTypeInfoStatus(LibraryInfo::DumpError, + qmldumpErrorMessage(libraryPath, infos.error)); + if (!privatePlugin) + printParseWarnings(libraryPath, libInfo.pluginTypeInfoError()); + } else { + libInfo.setMetaObjects(infos.objectsList.values()); + libInfo.setModuleApis(infos.moduleApis); + libInfo.setPluginTypeInfoStatus(LibraryInfo::DumpDone); + } + + if (!infos.warning.isEmpty()) + printParseWarnings(libraryPath, infos.warning); } + libInfo.updateFingerprint(); - if (!warning.isEmpty()) - printParseWarnings(libraryPath, warning); - } - libraryInfo.updateFingerprint(); + m_modelManager->updateLibraryInfo(libraryPath, libInfo); + watcher->deleteLater(); + }); - m_modelManager->updateLibraryInfo(libraryPath, libraryInfo); + auto future = Utils::runAsync([output, libraryPath](QFutureInterface& future) + { + Infos infos; + CppQmlTypesLoader::parseQmlTypeDescriptions(output, &infos.objectsList, &infos.moduleApis, &infos.dependencies, + &infos.error, &infos.warning, + QLatin1String("')); + future.reportFinished(&infos); + }); + + watcher->setFuture(future); } void PluginDumper::qmlPluginTypeDumpError(QProcess::ProcessError) @@ -339,38 +363,42 @@ dump(plugin); } -void PluginDumper::loadQmlTypeDescription(const QStringList &paths, - QStringList &errors, - QStringList &warnings, - QList &objects, - QList *moduleApi, - QStringList *dependencies) const { - for (const QString &p: paths) { - Utils::FileReader reader; - if (!reader.fetch(p, QFile::Text)) { - errors += reader.errorString(); - continue; +QFuture PluginDumper::loadQmlTypeDescription(const QStringList &paths) const { + auto future = Utils::runAsync([=](QFutureInterface& future) + { + PluginDumper::QmlTypeDescription result; + + for (const QString &p: paths) { + Utils::FileReader reader; + if (!reader.fetch(p, QFile::Text)) { + result.errors += reader.errorString(); + continue; + } + QString error; + QString warning; + CppQmlTypesLoader::BuiltinObjects objs; + QList apis; + QStringList deps; + CppQmlTypesLoader::parseQmlTypeDescriptions(reader.data(), &objs, &apis, &deps, + &error, &warning, p); + if (!error.isEmpty()) { + result.errors += tr("Failed to parse \"%1\".\nError: %2").arg(p, error); + } else { + result.objects += objs.values(); + result.moduleApis += apis; + if (!deps.isEmpty()) + result.dependencies += deps; + } + if (!warning.isEmpty()) + result.warnings += warning; } - QString error; - QString warning; - CppQmlTypesLoader::BuiltinObjects objs; - QList apis; - QStringList deps; - CppQmlTypesLoader::parseQmlTypeDescriptions(reader.data(), &objs, &apis, &deps, - &error, &warning, p); - if (!error.isEmpty()) { - errors += tr("Failed to parse \"%1\".\nError: %2").arg(p, error); - } else { - objects += objs.values(); - if (moduleApi) - *moduleApi += apis; - if (!deps.isEmpty()) - *dependencies += deps; - } - if (!warning.isEmpty()) - warnings += warning; - } + + future.reportFinished(&result); + }); + + return future; } + /*! * \brief Build the path of an existing qmltypes file from a module name. * \param name @@ -416,61 +444,97 @@ * Recursively load type descriptions of dependencies, collecting results * in \a objects. */ -void PluginDumper::loadDependencies(const QStringList &dependencies, - QStringList &errors, - QStringList &warnings, - QList &objects, - QSet *visited) const +QFuture PluginDumper::loadDependencies(const QStringList &dependencies, + QSharedPointer> visited) const { - if (dependencies.isEmpty()) - return; + auto iface = QSharedPointer>(new QFutureInterface); - QScopedPointer> visitedPtr(visited ? visited : new QSet()); + if (dependencies.isEmpty()) { + QFutureInterface iface; + DependencyInfo empty; + iface.reportFinished(&empty); + return iface.future(); + }; + if (visited.isNull()) { + visited = QSharedPointer>(new QSet()); + } + QStringList dependenciesPaths; QString path; for (const QString &name: dependencies) { path = buildQmltypesPath(name); if (!path.isNull()) dependenciesPaths << path; - visitedPtr->insert(name); + visited->insert(name); } - QStringList newDependencies; - loadQmlTypeDescription(dependenciesPaths, errors, warnings, objects, 0, &newDependencies); - newDependencies = Utils::toList(Utils::toSet(newDependencies) - *visitedPtr); - if (!newDependencies.isEmpty()) - loadDependencies(newDependencies, errors, warnings, objects, visitedPtr.take()); + auto typesWatcher = new QFutureWatcher(); + connect(typesWatcher, &QFutureWatcher::finished, this, [this, iface, visited, typesWatcher] { + QStringList newDependencies = typesWatcher->result().dependencies; + newDependencies = Utils::toList(Utils::toSet(newDependencies) - *visited.data()); + auto loadWatcher = new QFutureWatcher(); + connect(loadWatcher, &QFutureWatcher::finished, this, [iface, newDependencies, visited, typesWatcher, loadWatcher] { + PluginDumper::DependencyInfo result = loadWatcher->result(); + + result.errors += typesWatcher->result().errors; + result.objects += typesWatcher->result().objects; + result.warnings+= typesWatcher->result().warnings; + + iface->reportFinished(&result); + typesWatcher->deleteLater(); + loadWatcher->deleteLater(); + }); + loadWatcher->setFuture(loadDependencies(newDependencies, visited)); + }); + typesWatcher->setFuture(loadQmlTypeDescription(dependenciesPaths)); + + return iface->future(); } void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, const QString &libraryPath, QmlJS::LibraryInfo libraryInfo) { - QStringList errors; - QStringList warnings; - QList objects; - QList moduleApis; - QStringList dependencies; + auto typesWatcher = new QFutureWatcher(); + connect(typesWatcher, &QFutureWatcher::finished, this, [this, typesWatcher, libraryPath, libraryInfo] { - loadQmlTypeDescription(qmltypesFilePaths, errors, warnings, objects, &moduleApis, &dependencies); - loadDependencies(dependencies, errors, warnings, objects); + auto loadWatcher = new QFutureWatcher(); + connect(loadWatcher, &QFutureWatcher::finished, this, [this, typesWatcher, loadWatcher, libraryPath, libraryInfo] { - libraryInfo.setMetaObjects(objects); - libraryInfo.setModuleApis(moduleApis); - libraryInfo.setDependencies(dependencies); - if (errors.isEmpty()) { - libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileDone); - } else { - printParseWarnings(libraryPath, errors.join(QLatin1Char('\n'))); - errors.prepend(tr("Errors while reading typeinfo files:")); - libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileError, errors.join(QLatin1Char('\n'))); - } + QStringList deps = typesWatcher->result().dependencies; + QStringList errors = typesWatcher->result().errors; + QStringList warnings = typesWatcher->result().errors; + QList objects = typesWatcher->result().objects; - if (!warnings.isEmpty()) - printParseWarnings(libraryPath, warnings.join(QLatin1String("\n"))); + errors += loadWatcher->result().errors; + warnings += loadWatcher->result().warnings; + objects += loadWatcher->result().objects; - libraryInfo.updateFingerprint(); - m_modelManager->updateLibraryInfo(libraryPath, libraryInfo); + QmlJS::LibraryInfo libInfo = libraryInfo; + + libInfo.setMetaObjects(objects); + libInfo.setModuleApis(typesWatcher->result().moduleApis); + libInfo.setDependencies(typesWatcher->result().dependencies); + + if (errors.isEmpty()) { + libInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileDone); + } else { + printParseWarnings(libraryPath, errors.join(QLatin1Char('\n'))); + errors.prepend(tr("Errors while reading typeinfo files:")); + libInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileError, errors.join(QLatin1Char('\n'))); + } + + if (!warnings.isEmpty()) + printParseWarnings(libraryPath, warnings.join(QLatin1String("\n"))); + + libInfo.updateFingerprint(); + m_modelManager->updateLibraryInfo(libraryPath, libInfo); + typesWatcher->deleteLater(); + loadWatcher->deleteLater(); + }); + loadWatcher->setFuture(loadDependencies(typesWatcher->result().dependencies, QSharedPointer>())); + }); + typesWatcher->setFuture(loadQmlTypeDescription(qmltypesFilePaths)); } void PluginDumper::runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, Only in src/libs/qmljs: qmljsplugindumper.cpp.orig --- ../qt-creator-opensource-src-4.10.0/src/libs/qmljs/qmljsplugindumper.h +++ src/libs/qmljs/qmljsplugindumper.h @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ @@ -71,18 +71,30 @@ QStringList typeInfoPaths; }; + class QmlTypeDescription { + public: + QStringList errors; + QStringList warnings; + QList objects; + QList moduleApis; + QStringList dependencies; + }; + + class DependencyInfo { + public: + QStringList errors; + QStringList warnings; + QList objects; + }; + void runQmlDump(const QmlJS::ModelManagerInterface::ProjectInfo &info, const QStringList &arguments, const QString &importPath); void dump(const Plugin &plugin); - void loadQmlTypeDescription(const QStringList &path, QStringList &errors, QStringList &warnings, - QList &objects, - QList *moduleApi, - QStringList *dependencies) const; + QFuture loadQmlTypeDescription(const QStringList &path) const; QString buildQmltypesPath(const QString &name) const; - void loadDependencies(const QStringList &dependencies, - QStringList &errors, - QStringList &warnings, - QList &objects, - QSet *visited = nullptr) const; + + QFuture loadDependencies(const QStringList &dependencies, + QSharedPointer> visited) const; + void loadQmltypesFile(const QStringList &qmltypesFilePaths, const QString &libraryPath, QmlJS::LibraryInfo libraryInfo);