diff options
author | Marco Benelli <marco.benelli@theqtcompany.com> | 2016-02-26 17:28:30 +0100 |
---|---|---|
committer | Marco Benelli <marco.benelli@theqtcompany.com> | 2016-04-19 11:18:21 +0000 |
commit | 22acc52d71120bccb7fe9bb4390801e44a8ab379 (patch) | |
tree | d6068f0e2032d1e52c3b20d5344808ee5795e499 /src/libs/qmljs/qmljsplugindumper.cpp | |
parent | 94cba885bde551cad5d58da0b6a70049c924ec2a (diff) | |
download | qt-creator-22acc52d71120bccb7fe9bb4390801e44a8ab379.tar.gz |
Qml code model: handle modules dependencies.
Fix the broken hierarchies between qml objects.
Change-Id: Id36c735cab0129af382fab7b9dd90c228304168c
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Reviewed-by: Alessandro Portale <alessandro.portale@theqtcompany.com>
Diffstat (limited to 'src/libs/qmljs/qmljsplugindumper.cpp')
-rw-r--r-- | src/libs/qmljs/qmljsplugindumper.cpp | 133 |
1 files changed, 114 insertions, 19 deletions
diff --git a/src/libs/qmljs/qmljsplugindumper.cpp b/src/libs/qmljs/qmljsplugindumper.cpp index aa08ec044d..555b77671a 100644 --- a/src/libs/qmljs/qmljsplugindumper.cpp +++ b/src/libs/qmljs/qmljsplugindumper.cpp @@ -27,6 +27,7 @@ #include "qmljsmodelmanagerinterface.h" #include <qmljs/qmljsinterpreter.h> +#include <qmljs/qmljsviewercontext.h> //#include <projectexplorer/session.h> //#include <coreplugin/messagemanager.h> #include <utils/filesystemwatcher.h> @@ -309,7 +310,9 @@ void PluginDumper::qmlPluginTypeDumpDone(int exitCode) QString warning; CppQmlTypesLoader::BuiltinObjects objectsList; QList<ModuleApiInfo> moduleApis; - CppQmlTypesLoader::parseQmlTypeDescriptions(output, &objectsList, &moduleApis, &error, &warning, + QStringList dependencies; + CppQmlTypesLoader::parseQmlTypeDescriptions(output, &objectsList, &moduleApis, &dependencies, + &error, &warning, QLatin1String("<dump of ") + libraryPath + QLatin1Char('>')); if (exitCode == 0) { if (!error.isEmpty()) { @@ -361,39 +364,131 @@ void PluginDumper::pluginChanged(const QString &pluginLibrary) dump(plugin); } -void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, - const QString &libraryPath, - QmlJS::LibraryInfo libraryInfo) -{ - QStringList errors; - QStringList warnings; - QList<FakeMetaObject::ConstPtr> objects; - QList<ModuleApiInfo> moduleApis; - - foreach (const QString &qmltypesFilePath, qmltypesFilePaths) { +void PluginDumper::loadQmlTypeDescription(const QStringList &paths, + QStringList &errors, + QStringList &warnings, + QList<FakeMetaObject::ConstPtr> &objects, + QList<ModuleApiInfo> *moduleApi, + QStringList *dependencies) const { + for (const QString &p: paths) { Utils::FileReader reader; - if (!reader.fetch(qmltypesFilePath, QFile::Text)) { + if (!reader.fetch(p, QFile::Text)) { errors += reader.errorString(); continue; } - QString error; QString warning; - CppQmlTypesLoader::BuiltinObjects newObjects; - QList<ModuleApiInfo> newModuleApis; - CppQmlTypesLoader::parseQmlTypeDescriptions(reader.data(), &newObjects, &newModuleApis, &error, &warning, qmltypesFilePath); + CppQmlTypesLoader::BuiltinObjects objs; + QList<ModuleApiInfo> 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(qmltypesFilePath, error); + errors += tr("Failed to parse \"%1\".\nError: %2").arg(p, error); } else { - objects += newObjects.values(); - moduleApis += newModuleApis; + objects += objs.values(); + if (moduleApi) + *moduleApi += apis; + if (!deps.isEmpty()) + *dependencies += deps; } if (!warning.isEmpty()) warnings += warning; } +} +/*! + * \brief Build the path of an existing qmltypes file from a module name. + * \param name + * \return the module's qmltypes file path + * + * Look for \a name qmltypes file in model manager's import paths. + * For each import path the following files are searched, in this order: + * + * - <name>.<major>.<minor>/plugins.qmltypes + * - <name>.<major>/plugins.qmltypes + * - <name>/plugins.qmltypes + * + * That means that a more qualified directory name has precedence over a + * less qualified one. Be aware that the import paths order has a stronger + * precedence, so a less qualified name could shadow a more qualified one if + * it resides in a different import path. + * + * \sa LinkPrivate::importNonFile + */ +QString PluginDumper::buildQmltypesPath(const QString &name) const +{ + QStringList importName = name.split(QLatin1Char(' ')); + QString qualifiedName = importName[0]; + QString majorVersion; + QString minorVersion; + if (importName.length() == 2) { + QString versionString = importName[1]; + QStringList version = versionString.split(QLatin1Char('.')); + if (version.length() == 2) { + majorVersion = version[0]; + minorVersion = version[1]; + } + } + + for (const PathAndLanguage &p: m_modelManager->importPaths()) { + QString moduleName(qualifiedName.replace(QLatin1Char('.'), QLatin1Char('/'))); + QString moduleNameMajor(moduleName + QLatin1Char('.') + majorVersion); + QString moduleNameMajorMinor(moduleNameMajor + QLatin1Char('.') + minorVersion); + + for (const auto n: QStringList{moduleNameMajorMinor, moduleNameMajor, moduleName}) { + QString filename(p.path().toString() + QLatin1Char('/') + n + + QLatin1String("/plugins.qmltypes")); + if (QFile::exists(filename)) + return filename; + } + } + return QString(); +} + +/*! + * \brief Recursively load dependencies. + * \param dependencies + * \param errors + * \param warnings + * \param objects + * + * Recursively load type descriptions of dependencies, collecting results + * in \a objects. + */ +void PluginDumper::loadDependencies(const QStringList &dependencies, + QStringList &errors, + QStringList &warnings, + QList<FakeMetaObject::ConstPtr> &objects) const +{ + QStringList dependenciesPaths; + QString path; + for (const QString &name: dependencies) { + path = buildQmltypesPath(name); + if (!path.isNull()) + dependenciesPaths << path; + } + QStringList newDependencies; + loadQmlTypeDescription(dependenciesPaths, errors, warnings, objects, 0, &newDependencies); + if (!newDependencies.isEmpty()) + loadDependencies(newDependencies, errors, warnings, objects); +} + +void PluginDumper::loadQmltypesFile(const QStringList &qmltypesFilePaths, + const QString &libraryPath, + QmlJS::LibraryInfo libraryInfo) +{ + QStringList errors; + QStringList warnings; + QList<FakeMetaObject::ConstPtr> objects; + QList<ModuleApiInfo> moduleApis; + QStringList dependencies; + + loadQmlTypeDescription(qmltypesFilePaths, errors, warnings, objects, &moduleApis, &dependencies); + loadDependencies(dependencies, errors, warnings, objects); libraryInfo.setMetaObjects(objects); libraryInfo.setModuleApis(moduleApis); + libraryInfo.setDependencies(dependencies); if (errors.isEmpty()) { libraryInfo.setPluginTypeInfoStatus(LibraryInfo::TypeInfoFileDone); } else { |