forked from qt-creator/qt-creator
QmlJS: Scan app.qmltypes and lib.qmltypes for type information
app.qmltypes is being added as a new convention to Qt 5.15. These files are to be found next to application binaries, and contain the QML types those application register themselves, in contrast to QML types registered from plugins loaded via the regular import mechanism. lib.qmltypes works the same way, in principle, for libraries. This change only adds it to the possible names for qmltypes files, though. Change-Id: I1d7c5835c8c3e988d214c5cdb949ca677b48dfc5 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -370,6 +370,13 @@ LibraryInfo::LibraryInfo(Status status)
|
||||
updateFingerprint();
|
||||
}
|
||||
|
||||
LibraryInfo::LibraryInfo(const QmlDirParser::TypeInfo &typeInfo)
|
||||
: _status(Found)
|
||||
{
|
||||
_typeinfos.append(typeInfo);
|
||||
updateFingerprint();
|
||||
}
|
||||
|
||||
LibraryInfo::LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerprint)
|
||||
: _status(Found)
|
||||
, _components(parser.components().values())
|
||||
|
@@ -166,6 +166,7 @@ private:
|
||||
public:
|
||||
LibraryInfo();
|
||||
explicit LibraryInfo(Status status);
|
||||
explicit LibraryInfo(const QmlDirParser::TypeInfo &typeInfo);
|
||||
explicit LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerprint = QByteArray());
|
||||
~LibraryInfo() = default;
|
||||
LibraryInfo(const LibraryInfo &other) = default;
|
||||
|
@@ -111,6 +111,7 @@ private:
|
||||
Snapshot m_snapshot;
|
||||
ValueOwner *m_valueOwner = nullptr;
|
||||
QStringList m_importPaths;
|
||||
QStringList m_applicationDirectories;
|
||||
LibraryInfo m_builtins;
|
||||
ViewerContext m_vContext;
|
||||
|
||||
@@ -140,6 +141,7 @@ Link::Link(const Snapshot &snapshot, const ViewerContext &vContext, const Librar
|
||||
d->m_valueOwner = new ValueOwner;
|
||||
d->m_snapshot = snapshot;
|
||||
d->m_importPaths = vContext.paths;
|
||||
d->m_applicationDirectories = vContext.applicationDirectories;
|
||||
d->m_builtins = builtins;
|
||||
d->m_vContext = vContext;
|
||||
|
||||
@@ -381,6 +383,14 @@ Import LinkPrivate::importNonFile(const Document::Ptr &doc, const ImportInfo &im
|
||||
QString libraryPath = modulePath(packageName, version.toString(), m_importPaths);
|
||||
bool importFound = !libraryPath.isEmpty() && importLibrary(doc, libraryPath, &import);
|
||||
|
||||
if (!importFound) {
|
||||
for (const QString &dir : qAsConst(m_applicationDirectories)) {
|
||||
// This adds the types to the C++ types, to be found below if applicable.
|
||||
if (QFile::exists(dir + "/app.qmltypes"))
|
||||
importLibrary(doc, dir, &import);
|
||||
}
|
||||
}
|
||||
|
||||
// if there are cpp-based types for this package, use them too
|
||||
if (m_valueOwner->cppQmlTypes().hasModule(packageName)) {
|
||||
importFound = true;
|
||||
|
@@ -605,9 +605,11 @@ ModelManagerInterface::ProjectInfo ModelManagerInterface::projectInfoForPath(
|
||||
for (const ProjectInfo &pInfo : allProjectInfos) {
|
||||
if (res.qtQmlPath.isEmpty())
|
||||
res.qtQmlPath = pInfo.qtQmlPath;
|
||||
res.applicationDirectories.append(pInfo.applicationDirectories);
|
||||
for (const auto &importPath : pInfo.importPaths)
|
||||
res.importPaths.maybeInsert(importPath);
|
||||
}
|
||||
res.applicationDirectories = Utils::filteredUnique(res.applicationDirectories);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -745,6 +747,55 @@ static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapsho
|
||||
}
|
||||
}
|
||||
|
||||
enum class LibraryStatus {
|
||||
Accepted,
|
||||
Rejected,
|
||||
Unknown
|
||||
};
|
||||
|
||||
static LibraryStatus libraryStatus(const QString &path, const Snapshot &snapshot,
|
||||
QSet<QString> *newLibraries)
|
||||
{
|
||||
if (path.isEmpty())
|
||||
return LibraryStatus::Rejected;
|
||||
// if we know there is a library, done
|
||||
const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
|
||||
if (existingInfo.isValid())
|
||||
return LibraryStatus::Accepted;
|
||||
if (newLibraries->contains(path))
|
||||
return LibraryStatus::Accepted;
|
||||
// if we looked at the path before, done
|
||||
return existingInfo.wasScanned()
|
||||
? LibraryStatus::Rejected
|
||||
: LibraryStatus::Unknown;
|
||||
}
|
||||
|
||||
static bool findNewQmlApplicationInPath(const QString &path,
|
||||
const Snapshot &snapshot,
|
||||
ModelManagerInterface *modelManager,
|
||||
QSet<QString> *newLibraries)
|
||||
{
|
||||
switch (libraryStatus(path, snapshot, newLibraries)) {
|
||||
case LibraryStatus::Accepted: return true;
|
||||
case LibraryStatus::Rejected: return false;
|
||||
default: break;
|
||||
}
|
||||
|
||||
const QDir dir(path);
|
||||
const QLatin1String appQmltypes("app.qmltypes");
|
||||
QFile appQmltypesFile(dir.filePath(appQmltypes));
|
||||
if (!appQmltypesFile.exists())
|
||||
return false;
|
||||
|
||||
LibraryInfo libraryInfo = LibraryInfo(QmlDirParser::TypeInfo(appQmltypes));
|
||||
const QString libraryPath = dir.absolutePath();
|
||||
newLibraries->insert(libraryPath);
|
||||
modelManager->updateLibraryInfo(path, libraryInfo);
|
||||
modelManager->loadPluginTypes(QFileInfo(libraryPath).canonicalFilePath(), libraryPath,
|
||||
QString(), QString());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool findNewQmlLibraryInPath(const QString &path,
|
||||
const Snapshot &snapshot,
|
||||
ModelManagerInterface *modelManager,
|
||||
@@ -753,15 +804,11 @@ static bool findNewQmlLibraryInPath(const QString &path,
|
||||
QSet<QString> *newLibraries,
|
||||
bool ignoreMissing)
|
||||
{
|
||||
// if we know there is a library, done
|
||||
const LibraryInfo &existingInfo = snapshot.libraryInfo(path);
|
||||
if (existingInfo.isValid())
|
||||
return true;
|
||||
if (newLibraries->contains(path))
|
||||
return true;
|
||||
// if we looked at the path before, done
|
||||
if (existingInfo.wasScanned())
|
||||
return false;
|
||||
switch (libraryStatus(path, snapshot, newLibraries)) {
|
||||
case LibraryStatus::Accepted: return true;
|
||||
case LibraryStatus::Rejected: return false;
|
||||
default: break;
|
||||
}
|
||||
|
||||
const QDir dir(path);
|
||||
QFile qmldirFile(dir.filePath(QLatin1String("qmldir")));
|
||||
@@ -1097,6 +1144,7 @@ void ModelManagerInterface::updateImportPaths()
|
||||
if (m_indexerDisabled)
|
||||
return;
|
||||
PathsAndLanguages allImportPaths;
|
||||
QStringList allApplicationDirectories;
|
||||
QmlLanguageBundles activeBundles;
|
||||
QmlLanguageBundles extendedBundles;
|
||||
for (const ProjectInfo &pInfo : qAsConst(m_projects)) {
|
||||
@@ -1107,11 +1155,13 @@ void ModelManagerInterface::updateImportPaths()
|
||||
importPath.language());
|
||||
}
|
||||
}
|
||||
allApplicationDirectories.append(pInfo.applicationDirectories);
|
||||
}
|
||||
|
||||
for (const ViewerContext &vContext : qAsConst(m_defaultVContexts)) {
|
||||
for (const QString &path : vContext.paths)
|
||||
allImportPaths.maybeInsert(Utils::FilePath::fromString(path), vContext.language);
|
||||
allApplicationDirectories.append(vContext.applicationDirectories);
|
||||
}
|
||||
|
||||
for (const ProjectInfo &pInfo : qAsConst(m_projects)) {
|
||||
@@ -1143,6 +1193,7 @@ void ModelManagerInterface::updateImportPaths()
|
||||
for (const QString &path : qAsConst(m_defaultImportPaths))
|
||||
allImportPaths.maybeInsert(Utils::FilePath::fromString(path), Dialect::Qml);
|
||||
allImportPaths.compact();
|
||||
allApplicationDirectories = Utils::filteredUnique(allApplicationDirectories);
|
||||
|
||||
{
|
||||
QMutexLocker l(&m_mutex);
|
||||
@@ -1159,6 +1210,8 @@ void ModelManagerInterface::updateImportPaths()
|
||||
QSet<QString> newLibraries;
|
||||
for (const Document::Ptr &doc : qAsConst(snapshot))
|
||||
findNewLibraryImports(doc, snapshot, this, &importedFiles, &scannedPaths, &newLibraries);
|
||||
for (const QString &path : allApplicationDirectories)
|
||||
findNewQmlApplicationInPath(path, snapshot, this, &newLibraries);
|
||||
|
||||
updateSourceFiles(importedFiles, true);
|
||||
|
||||
@@ -1366,6 +1419,8 @@ ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx,
|
||||
ProjectInfo defaultInfo = defaultProjectInfo();
|
||||
if (info.qtQmlPath.isEmpty())
|
||||
info.qtQmlPath = defaultInfo.qtQmlPath;
|
||||
info.applicationDirectories = Utils::filteredUnique(info.applicationDirectories
|
||||
+ defaultInfo.applicationDirectories);
|
||||
switch (res.flags) {
|
||||
case ViewerContext::Complete:
|
||||
break;
|
||||
@@ -1433,6 +1488,7 @@ ViewerContext ModelManagerInterface::completeVContext(const ViewerContext &vCtx,
|
||||
break;
|
||||
}
|
||||
res.flags = ViewerContext::Complete;
|
||||
res.applicationDirectories = info.applicationDirectories;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -71,6 +71,7 @@ public:
|
||||
QStringList activeResourceFiles;
|
||||
QStringList allResourceFiles;
|
||||
QHash<QString, QString> resourceFileContents;
|
||||
QStringList applicationDirectories;
|
||||
|
||||
// whether trying to run qmldump makes sense
|
||||
bool tryQmlDump = false;
|
||||
|
@@ -41,6 +41,12 @@
|
||||
using namespace LanguageUtils;
|
||||
using namespace QmlJS;
|
||||
|
||||
static const QStringList qmltypesFileNames = {
|
||||
QLatin1String("plugins.qmltypes"),
|
||||
QLatin1String("app.qmltypes"),
|
||||
QLatin1String("lib.qmltypes")
|
||||
};
|
||||
|
||||
PluginDumper::PluginDumper(ModelManagerInterface *modelManager)
|
||||
: QObject(modelManager)
|
||||
, m_modelManager(modelManager)
|
||||
@@ -146,10 +152,11 @@ void PluginDumper::onLoadPluginTypes(const QString &libraryPath, const QString &
|
||||
plugin.importVersion = importVersion;
|
||||
|
||||
// add default qmltypes file if it exists
|
||||
const QLatin1String defaultQmltypesFileName("plugins.qmltypes");
|
||||
const QString defaultQmltypesPath = makeAbsolute(defaultQmltypesFileName, canonicalLibraryPath);
|
||||
for (const QString &qmltypesFileName : qmltypesFileNames) {
|
||||
const QString defaultQmltypesPath = makeAbsolute(qmltypesFileName, canonicalLibraryPath);
|
||||
if (!plugin.typeInfoPaths.contains(defaultQmltypesPath) && QFile::exists(defaultQmltypesPath))
|
||||
plugin.typeInfoPaths += defaultQmltypesPath;
|
||||
}
|
||||
|
||||
// add typeinfo files listed in qmldir
|
||||
foreach (const QmlDirParser::TypeInfo &typeInfo, libraryInfo.typeInfos()) {
|
||||
@@ -398,10 +405,11 @@ QString PluginDumper::buildQmltypesPath(const QString &name) const
|
||||
if (path.isEmpty())
|
||||
return QString();
|
||||
|
||||
const QString filename = path + QLatin1String("/plugins.qmltypes");
|
||||
|
||||
for (const QString &qmltypesFileName : qmltypesFileNames) {
|
||||
const QString filename = path + QLatin1Char('/') + qmltypesFileName;
|
||||
if (QFile::exists(filename))
|
||||
return filename;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
@@ -44,6 +44,7 @@ struct QMLJS_EXPORT ViewerContext
|
||||
|
||||
QStringList selectors;
|
||||
QStringList paths;
|
||||
QStringList applicationDirectories;
|
||||
Dialect language = Dialect::Qml;
|
||||
Flags flags = AddAllPaths;
|
||||
};
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qmljs/qmljsbind.h>
|
||||
@@ -139,6 +140,13 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
|
||||
// plugins that are not installed in default Qt qml installation directory.
|
||||
projectInfo.qmlDumpEnvironment.appendOrSet("QML2_IMPORT_PATH", bc->environment().expandedValueForKey("QML2_IMPORT_PATH"), ":");
|
||||
}
|
||||
|
||||
const auto appTargets = activeTarget->applicationTargets();
|
||||
for (const auto &target : appTargets) {
|
||||
if (target.targetFilePath.isEmpty())
|
||||
continue;
|
||||
projectInfo.applicationDirectories.append(target.targetFilePath.parentDir().toString());
|
||||
}
|
||||
}
|
||||
if (!setPreferDump && qtVersion)
|
||||
preferDebugDump = (qtVersion->defaultBuildConfig() & QtSupport::BaseQtVersion::DebugBuild);
|
||||
|
Reference in New Issue
Block a user