QtQml: Clean up qmldir redirection
We need to perform the redirection before inserting imports into namespaces. Through the redirection we might discover a module that we have already imported before. In that case we must not import it again. Pick-to: 6.9 6.8 Fixes: QTBUG-133587 Change-Id: I47a279461763b5397137002a9e7c7d3bfc7ad15d Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
6104332961
commit
f7e29f7d27
|
@ -769,13 +769,24 @@ bool QQmlImports::resolveType(
|
|||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const
|
||||
QQmlImportInstance *QQmlImportNamespace::findImportByModuleUri(
|
||||
const QString &moduleUri, QTypeRevision version) const
|
||||
{
|
||||
for (QQmlImportInstance *import : imports) {
|
||||
if (import->uri == uri)
|
||||
return import;
|
||||
}
|
||||
return nullptr;
|
||||
const auto end = imports.cend();
|
||||
const auto it = std::find_if(imports.cbegin(), end, [&](const QQmlImportInstance *import) {
|
||||
return import->uri == moduleUri && import->version == version;
|
||||
});
|
||||
return it == end ? nullptr : *it;
|
||||
}
|
||||
|
||||
QQmlImportInstance *QQmlImportNamespace::findImportByLocation(
|
||||
const QString &location, QTypeRevision version) const
|
||||
{
|
||||
const auto end = imports.cend();
|
||||
const auto it = std::find_if(imports.cbegin(), end, [&](const QQmlImportInstance *import) {
|
||||
return import->url == location && import->version == version;
|
||||
});
|
||||
return it == end ? nullptr : *it;
|
||||
}
|
||||
|
||||
bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
|
||||
|
@ -920,8 +931,7 @@ void QQmlImports::registerBuiltinModuleTypes(
|
|||
}
|
||||
|
||||
QString QQmlImports::redirectQmldirContent(
|
||||
QQmlTypeLoader *typeLoader, QQmlTypeLoaderQmldirContent *qmldir,
|
||||
QQmlImportInstance *inserted)
|
||||
QQmlTypeLoader *typeLoader, QQmlTypeLoaderQmldirContent *qmldir)
|
||||
{
|
||||
const QString preferredPath = qmldir->preferredPath();
|
||||
const QString url = preferredPath.startsWith(u':')
|
||||
|
@ -935,9 +945,6 @@ QString QQmlImports::redirectQmldirContent(
|
|||
if (redirected.hasContent() && !redirected.hasError())
|
||||
*qmldir = std::move(redirected);
|
||||
|
||||
if (const QString qmldirUri = qmldir->typeNamespace(); !qmldirUri.isEmpty())
|
||||
inserted->uri = qmldirUri;
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -991,7 +998,7 @@ QString QQmlImports::resolvedUri(const QString &dir_arg, QQmlTypeLoader *typeLoa
|
|||
return stableRelativePath;
|
||||
}
|
||||
|
||||
QTypeRevision QQmlImports::matchingQmldirVersion(
|
||||
static QTypeRevision matchingQmldirVersion(
|
||||
const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, QTypeRevision version,
|
||||
QList<QQmlError> *errors)
|
||||
{
|
||||
|
@ -1065,13 +1072,13 @@ QTypeRevision QQmlImports::matchingQmldirVersion(
|
|||
|| (version.hasMinorVersion()
|
||||
&& (lowestMinorVersion > version.minorVersion()
|
||||
|| highestMinorVersion < version.minorVersion())))) {
|
||||
errors->prepend(moduleNotFoundError(uri, version));
|
||||
errors->prepend(QQmlImports::moduleNotFoundError(uri, version));
|
||||
return QTypeRevision();
|
||||
}
|
||||
|
||||
// ... otherwise, anything is valid.
|
||||
if (bestMajorVersion < 0)
|
||||
return validVersion();
|
||||
return QQmlImports::validVersion();
|
||||
|
||||
return QTypeRevision::fromVersion(
|
||||
bestMajorVersion,
|
||||
|
@ -1132,9 +1139,47 @@ static QString getVersionInfo(QTypeRevision version) {
|
|||
return version.isValid() ? QDebug::toString(version) : u"(latest)"_s;
|
||||
}
|
||||
|
||||
static QTypeRevision matchingModuleVersionForLibraryImport(
|
||||
const QString &uri, QTypeRevision version, QList<QQmlError> *errors)
|
||||
{
|
||||
const QTypeRevision matchingVersion = QQmlMetaType::matchingModuleVersion(uri, version);
|
||||
if (!matchingVersion.isValid())
|
||||
errors->prepend(QQmlImports::moduleNotFoundError(uri, relevantVersion(uri, version)));
|
||||
return matchingVersion;
|
||||
}
|
||||
|
||||
static QTypeRevision finalizeLibraryImport(
|
||||
const QString &uri, QTypeRevision version, const QQmlTypeLoaderQmldirContent &qmldir,
|
||||
QQmlImportInstance *inserted, QList<QQmlError> *errors)
|
||||
{
|
||||
// Ensure that we are actually providing something
|
||||
const QTypeRevision matchingVersion = QQmlMetaType::matchingModuleVersion(uri, version);
|
||||
if (matchingVersion.isValid())
|
||||
return matchingVersion;
|
||||
|
||||
if (inserted->qmlDirComponents.isEmpty() && inserted->qmlDirScripts.isEmpty()) {
|
||||
if (qmldir.plugins().isEmpty()) {
|
||||
if (!qmldir.imports().isEmpty())
|
||||
return QQmlImports::validVersion(); // This is a pure redirection
|
||||
if (qmldir.hasTypeInfo())
|
||||
return QQmlImports::validVersion(); // A pure C++ module without plugin
|
||||
}
|
||||
errors->prepend(QQmlImports::moduleNotFoundError(uri, relevantVersion(uri, version)));
|
||||
return QTypeRevision();
|
||||
} else {
|
||||
// Verify that the qmldir content is valid for this version
|
||||
version = matchingQmldirVersion(qmldir, uri, version, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
}
|
||||
|
||||
Q_ASSERT(version.isValid());
|
||||
return version;
|
||||
}
|
||||
|
||||
QTypeRevision QQmlImports::addLibraryImport(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
|
||||
QTypeRevision version, const QString &qmldirIdentifier, const QString &qmldirUrl,
|
||||
QTypeRevision requestedVersion, const QString &qmldirIdentifier, const QString &qmldirUrl,
|
||||
ImportFlags flags, quint16 precedence, QList<QQmlError> *errors)
|
||||
{
|
||||
Q_ASSERT(typeLoader);
|
||||
|
@ -1143,64 +1188,73 @@ QTypeRevision QQmlImports::addLibraryImport(
|
|||
if (lcQmlImport().isDebugEnabled()) {
|
||||
qCDebug(lcQmlImport)
|
||||
<< "addLibraryImport:" << qPrintable(baseUrl().toString())
|
||||
<< uri << "version" << getVersionInfo(version) << "as" << prefix;
|
||||
<< uri << "version" << getVersionInfo(requestedVersion) << "as" << prefix;
|
||||
}
|
||||
|
||||
QQmlImportNamespace *nameSpace = importNamespace(prefix);
|
||||
Q_ASSERT(nameSpace);
|
||||
|
||||
const bool noQmldir = qmldirIdentifier.isEmpty();
|
||||
const bool isIncomplete = (flags & QQmlImports::ImportIncomplete);
|
||||
if (noQmldir || isIncomplete) {
|
||||
QQmlImportInstance *inserted = addImportToNamespace(
|
||||
nameSpace, uri, qmldirUrl, requestedVersion,
|
||||
QV4::CompiledData::Import::ImportLibrary, errors,
|
||||
precedence);
|
||||
Q_ASSERT(inserted);
|
||||
|
||||
if (noQmldir && !isIncomplete) {
|
||||
// No need to wait for the qmldir to become available if we're not supposed to use it.
|
||||
if (!QQmlMetaType::typeModule(uri, requestedVersion))
|
||||
QQmlMetaType::qmlRegisterModuleTypes(uri);
|
||||
return matchingModuleVersionForLibraryImport(uri, requestedVersion, errors);
|
||||
}
|
||||
|
||||
return validVersion(requestedVersion);
|
||||
}
|
||||
|
||||
QQmlTypeLoaderQmldirContent qmldir;
|
||||
if (!getQmldirContent(typeLoader, qmldirIdentifier, uri, &qmldir, errors)) {
|
||||
// qmldir had errors.
|
||||
return QTypeRevision();
|
||||
}
|
||||
|
||||
// qmldir is remote and can't be loaded synchronously, but we may already know the module.
|
||||
if (!qmldir.hasContent())
|
||||
return matchingModuleVersionForLibraryImport(uri, requestedVersion, errors);
|
||||
|
||||
// Load the plugin before redirecting. Otherwise we might not find the qmldir we're looking for.
|
||||
const QTypeRevision importedVersion = importExtension(
|
||||
typeLoader, uri, requestedVersion, &qmldir, errors);
|
||||
if (!importedVersion.isValid())
|
||||
return QTypeRevision();
|
||||
|
||||
QString resolvedUrl;
|
||||
QString resolvedUri;
|
||||
if (qmldir.hasRedirection()) {
|
||||
resolvedUrl = redirectQmldirContent(typeLoader, &qmldir);
|
||||
resolvedUri = qmldir.typeNamespace();
|
||||
if (QQmlImportInstance *existing
|
||||
= nameSpace->findImportByLocation(resolvedUrl, requestedVersion)) {
|
||||
return finalizeLibraryImport(uri, importedVersion, qmldir, existing, errors);
|
||||
}
|
||||
} else {
|
||||
resolvedUrl = qmldirUrl;
|
||||
resolvedUri = uri;
|
||||
}
|
||||
|
||||
QQmlImportInstance *inserted = addImportToNamespace(
|
||||
nameSpace, uri, qmldirUrl, version,
|
||||
nameSpace, resolvedUri, resolvedUrl, requestedVersion,
|
||||
QV4::CompiledData::Import::ImportLibrary, errors,
|
||||
precedence);
|
||||
Q_ASSERT(inserted);
|
||||
|
||||
if (!(flags & QQmlImports::ImportIncomplete)) {
|
||||
QQmlTypeLoaderQmldirContent qmldir;
|
||||
registerBuiltinModuleTypes(qmldir, importedVersion);
|
||||
|
||||
if (!qmldirIdentifier.isEmpty()) {
|
||||
if (!getQmldirContent(typeLoader, qmldirIdentifier, uri, &qmldir, errors))
|
||||
return QTypeRevision();
|
||||
if (!inserted->setQmldirContent(resolvedUrl, qmldir, nameSpace, errors))
|
||||
return QTypeRevision();
|
||||
|
||||
if (qmldir.hasContent()) {
|
||||
version = importExtension(typeLoader, uri, version, &qmldir, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
|
||||
const QString resolvedUrl = qmldir.hasRedirection()
|
||||
? redirectQmldirContent(typeLoader, &qmldir, inserted)
|
||||
: qmldirUrl;
|
||||
|
||||
registerBuiltinModuleTypes(qmldir, version);
|
||||
|
||||
if (!inserted->setQmldirContent(resolvedUrl, qmldir, nameSpace, errors))
|
||||
return QTypeRevision();
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that we are actually providing something
|
||||
const QTypeRevision matchingVersion = QQmlMetaType::matchingModuleVersion(uri, version);
|
||||
if (matchingVersion.isValid())
|
||||
return matchingVersion;
|
||||
|
||||
if (inserted->qmlDirComponents.isEmpty() && inserted->qmlDirScripts.isEmpty()) {
|
||||
if (qmldir.plugins().isEmpty()) {
|
||||
if (!qmldir.imports().isEmpty())
|
||||
return validVersion(); // This is a pure redirection
|
||||
if (qmldir.hasTypeInfo())
|
||||
return validVersion(); // A pure C++ module without plugin
|
||||
}
|
||||
errors->prepend(moduleNotFoundError(uri, relevantVersion(uri, version)));
|
||||
return QTypeRevision();
|
||||
} else if (qmldir.hasContent()) {
|
||||
// Verify that the qmldir content is valid for this version
|
||||
version = matchingQmldirVersion(qmldir, uri, version, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
}
|
||||
}
|
||||
|
||||
return validVersion(version);
|
||||
return finalizeLibraryImport(uri, importedVersion, qmldir, inserted, errors);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1226,7 +1280,7 @@ QTypeRevision QQmlImports::addLibraryImport(
|
|||
*/
|
||||
QTypeRevision QQmlImports::addFileImport(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
|
||||
QTypeRevision version, ImportFlags flags, quint16 precedence, QString *localQmldir,
|
||||
QTypeRevision requestedVersion, ImportFlags flags, quint16 precedence, QString *localQmldir,
|
||||
QList<QQmlError> *errors)
|
||||
{
|
||||
Q_ASSERT(typeLoader);
|
||||
|
@ -1235,7 +1289,7 @@ QTypeRevision QQmlImports::addFileImport(
|
|||
if (lcQmlImport().isDebugEnabled()) {
|
||||
qCDebug(lcQmlImport)
|
||||
<< "addFileImport:" << qPrintable(baseUrl().toString())
|
||||
<< uri << "version" << getVersionInfo(version) << "as" << prefix;
|
||||
<< uri << "version" << getVersionInfo(requestedVersion) << "as" << prefix;
|
||||
}
|
||||
|
||||
if (uri.startsWith(Slash) || uri.startsWith(Colon)) {
|
||||
|
@ -1329,53 +1383,85 @@ QTypeRevision QQmlImports::addFileImport(
|
|||
it != nameSpace->imports.constEnd(); ++it) {
|
||||
if ((*it)->url == url) {
|
||||
(*it)->implicitlyImported = true;
|
||||
return validVersion(version);
|
||||
return validVersion(requestedVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & QQmlImports::ImportIncomplete) && !qmldirIdentifier.isEmpty()) {
|
||||
QQmlTypeLoaderQmldirContent qmldir;
|
||||
if (!getQmldirContent(typeLoader, qmldirIdentifier, importUri, &qmldir, errors))
|
||||
return QTypeRevision();
|
||||
if ((flags & QQmlImports::ImportIncomplete) || qmldirIdentifier.isEmpty()) {
|
||||
QQmlImportInstance *inserted = addImportToNamespace(
|
||||
nameSpace, importUri, url, requestedVersion, QV4::CompiledData::Import::ImportFile,
|
||||
errors, precedence);
|
||||
Q_ASSERT(inserted);
|
||||
return validVersion(requestedVersion);
|
||||
}
|
||||
|
||||
if (qmldir.hasContent()) {
|
||||
// Prefer the qmldir URI. Unless it doesn't exist.
|
||||
const QString qmldirUri = qmldir.typeNamespace();
|
||||
if (!qmldirUri.isEmpty())
|
||||
importUri = qmldirUri;
|
||||
QQmlTypeLoaderQmldirContent qmldir;
|
||||
if (!getQmldirContent(typeLoader, qmldirIdentifier, importUri, &qmldir, errors))
|
||||
return QTypeRevision();
|
||||
|
||||
QQmlImportInstance *inserted = addImportToNamespace(
|
||||
nameSpace, importUri, url, version, QV4::CompiledData::Import::ImportFile,
|
||||
errors, precedence);
|
||||
Q_ASSERT(inserted);
|
||||
if (!qmldir.hasContent()) {
|
||||
QQmlImportInstance *inserted = addImportToNamespace(
|
||||
nameSpace, importUri, url, requestedVersion, QV4::CompiledData::Import::ImportFile,
|
||||
errors, precedence);
|
||||
Q_ASSERT(inserted);
|
||||
return validVersion(requestedVersion);
|
||||
}
|
||||
|
||||
version = importExtension(typeLoader, importUri, version, &qmldir, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
// Prefer the qmldir URI. Unless it doesn't exist.
|
||||
const QString qmldirUri = qmldir.typeNamespace();
|
||||
if (!qmldirUri.isEmpty())
|
||||
importUri = qmldirUri;
|
||||
|
||||
if (qmldir.hasRedirection())
|
||||
url = redirectQmldirContent(typeLoader, &qmldir, inserted);
|
||||
// Load the plugin before redirecting. Otherwise we might not find the qmldir we're looking for.
|
||||
const QTypeRevision importedVersion
|
||||
= importExtension(typeLoader, importUri, requestedVersion, &qmldir, errors);
|
||||
if (!importedVersion.isValid())
|
||||
return QTypeRevision();
|
||||
|
||||
registerBuiltinModuleTypes(qmldir, version);
|
||||
|
||||
if (!inserted->setQmldirContent(url, qmldir, nameSpace, errors))
|
||||
return QTypeRevision();
|
||||
|
||||
return validVersion(version);
|
||||
QString resolvedUrl;
|
||||
if (qmldir.hasRedirection()) {
|
||||
resolvedUrl = redirectQmldirContent(typeLoader, &qmldir);
|
||||
importUri = qmldir.typeNamespace();
|
||||
if (resolvedUrl != url) {
|
||||
if (QQmlImportInstance *existing
|
||||
= nameSpace->findImportByLocation(resolvedUrl, requestedVersion)) {
|
||||
// We've alraedy seen this import. No need to add another entry.
|
||||
return validVersion(existing->version);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolvedUrl = url;
|
||||
}
|
||||
|
||||
QQmlImportInstance *inserted = addImportToNamespace(
|
||||
nameSpace, importUri, url, version, QV4::CompiledData::Import::ImportFile,
|
||||
errors, precedence);
|
||||
nameSpace, importUri, resolvedUrl, requestedVersion, QV4::CompiledData::Import::ImportFile,
|
||||
errors, precedence);
|
||||
Q_ASSERT(inserted);
|
||||
return validVersion(version);
|
||||
|
||||
registerBuiltinModuleTypes(qmldir, importedVersion);
|
||||
|
||||
if (!inserted->setQmldirContent(resolvedUrl, qmldir, nameSpace, errors))
|
||||
return QTypeRevision();
|
||||
|
||||
Q_ASSERT(importedVersion.isValid());
|
||||
return importedVersion;
|
||||
}
|
||||
|
||||
static QTypeRevision qmldirContentError(const QString &uri, QList<QQmlError> *errors)
|
||||
{
|
||||
if (errors->isEmpty()) {
|
||||
QQmlError error;
|
||||
error.setDescription(QQmlTypeLoader::tr("Cannot update qmldir content for '%1'").arg(uri));
|
||||
errors->prepend(error);
|
||||
}
|
||||
return QTypeRevision();
|
||||
}
|
||||
|
||||
QTypeRevision QQmlImports::updateQmldirContent(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
|
||||
const QString &qmldirIdentifier, const QString &qmldirUrl, QList<QQmlError> *errors)
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, QTypeRevision version,
|
||||
const QString &prefix, const QString &qmldirIdentifier, const QString &qmldirUrl,
|
||||
QList<QQmlError> *errors)
|
||||
{
|
||||
Q_ASSERT(typeLoader);
|
||||
Q_ASSERT(errors);
|
||||
|
@ -1387,48 +1473,61 @@ QTypeRevision QQmlImports::updateQmldirContent(
|
|||
QQmlImportNamespace *nameSpace = importNamespace(prefix);
|
||||
Q_ASSERT(nameSpace);
|
||||
|
||||
if (QQmlImportInstance *import = nameSpace->findImport(uri)) {
|
||||
QQmlTypeLoaderQmldirContent qmldir;
|
||||
if (!getQmldirContent(typeLoader, qmldirIdentifier, uri, &qmldir, errors))
|
||||
return QTypeRevision();
|
||||
QQmlImportInstance *import = nameSpace->findImportByModuleUri(uri, version);
|
||||
if (!import)
|
||||
return qmldirContentError(uri, errors);
|
||||
|
||||
if (qmldir.hasContent()) {
|
||||
QTypeRevision version = importExtension(
|
||||
typeLoader, uri, import->version, &qmldir, errors);
|
||||
QQmlTypeLoaderQmldirContent qmldir;
|
||||
if (!getQmldirContent(typeLoader, qmldirIdentifier, uri, &qmldir, errors))
|
||||
return QTypeRevision();
|
||||
|
||||
if (!qmldir.hasContent())
|
||||
return qmldirContentError(uri, errors);
|
||||
|
||||
// Load the plugin before redirecting. Otherwise we might not find the qmldir we're looking for.
|
||||
version = importExtension(typeLoader, uri, import->version, &qmldir, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
|
||||
QString resolvedUrl;
|
||||
if (qmldir.hasRedirection()) {
|
||||
resolvedUrl = redirectQmldirContent(typeLoader, &qmldir);
|
||||
if (resolvedUrl != import->url) {
|
||||
if (QQmlImportInstance *existing
|
||||
= nameSpace->findImportByLocation(resolvedUrl, import->version)) {
|
||||
// We've re-discovered the same module via a different redirect.
|
||||
// No need to import it again.
|
||||
nameSpace->imports.removeOne(import);
|
||||
delete import;
|
||||
return validVersion(existing->version);
|
||||
}
|
||||
import->url = resolvedUrl;
|
||||
}
|
||||
import->uri = qmldir.typeNamespace();
|
||||
} else {
|
||||
resolvedUrl = qmldirUrl;
|
||||
}
|
||||
|
||||
registerBuiltinModuleTypes(qmldir, version);
|
||||
|
||||
if (import->setQmldirContent(resolvedUrl, qmldir, nameSpace, errors)) {
|
||||
if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) {
|
||||
// The implicit import qmldir can be empty, and plugins have no extra versions
|
||||
if (uri != QLatin1String(".")
|
||||
&& !QQmlMetaType::matchingModuleVersion(import->uri, version).isValid()) {
|
||||
errors->prepend(moduleNotFoundError(uri, relevantVersion(uri, version)));
|
||||
return QTypeRevision();
|
||||
}
|
||||
} else {
|
||||
// Verify that the qmldir content is valid for this version
|
||||
version = matchingQmldirVersion(qmldir, import->uri, version, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
|
||||
const QString resolvedUrl = qmldir.hasRedirection()
|
||||
? redirectQmldirContent(typeLoader, &qmldir, import)
|
||||
: qmldirUrl;
|
||||
|
||||
registerBuiltinModuleTypes(qmldir, version);
|
||||
|
||||
if (import->setQmldirContent(resolvedUrl, qmldir, nameSpace, errors)) {
|
||||
if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) {
|
||||
// The implicit import qmldir can be empty, and plugins have no extra versions
|
||||
if (uri != QLatin1String(".") && !QQmlMetaType::matchingModuleVersion(uri, version).isValid()) {
|
||||
errors->prepend(moduleNotFoundError(uri, relevantVersion(uri, version)));
|
||||
return QTypeRevision();
|
||||
}
|
||||
} else {
|
||||
// Verify that the qmldir content is valid for this version
|
||||
version = matchingQmldirVersion(qmldir, uri, version, errors);
|
||||
if (!version.isValid())
|
||||
return QTypeRevision();
|
||||
}
|
||||
return validVersion(version);
|
||||
}
|
||||
}
|
||||
return validVersion(version);
|
||||
}
|
||||
|
||||
if (errors->isEmpty()) {
|
||||
QQmlError error;
|
||||
error.setDescription(QQmlTypeLoader::tr("Cannot update qmldir content for '%1'").arg(uri));
|
||||
errors->prepend(error);
|
||||
}
|
||||
|
||||
return QTypeRevision();
|
||||
return qmldirContentError(uri, errors);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -91,7 +91,10 @@ public:
|
|||
|
||||
QList<QQmlImportInstance *> imports;
|
||||
|
||||
QQmlImportInstance *findImport(const QString &uri) const;
|
||||
QQmlImportInstance *findImportByModuleUri(
|
||||
const QString &moduleUri, QTypeRevision version) const;
|
||||
QQmlImportInstance *findImportByLocation(
|
||||
const QString &location, QTypeRevision version) const;
|
||||
|
||||
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
|
||||
QTypeRevision *version_return, QQmlType* type_return,
|
||||
|
@ -163,17 +166,19 @@ public:
|
|||
|
||||
QTypeRevision addFileImport(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
|
||||
QTypeRevision version, ImportFlags flags, quint16 precedence, QString *localQmldir,
|
||||
QList<QQmlError> *errors);
|
||||
QTypeRevision requestedVersion, ImportFlags flags, quint16 precedence,
|
||||
QString *localQmldir, QList<QQmlError> *errors);
|
||||
|
||||
QTypeRevision addLibraryImport(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
|
||||
QTypeRevision version, const QString &qmldirIdentifier, const QString &qmldirUrl,
|
||||
ImportFlags flags, quint16 precedence, QList<QQmlError> *errors);
|
||||
QTypeRevision requestedVersion, const QString &qmldirIdentifier,
|
||||
const QString &qmldirUrl, ImportFlags flags, quint16 precedence,
|
||||
QList<QQmlError> *errors);
|
||||
|
||||
QTypeRevision updateQmldirContent(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, const QString &prefix,
|
||||
const QString &qmldirIdentifier, const QString &qmldirUrl, QList<QQmlError> *errors);
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, QTypeRevision version,
|
||||
const QString &prefix, const QString &qmldirIdentifier, const QString &qmldirUrl,
|
||||
QList<QQmlError> *errors);
|
||||
|
||||
void populateCache(QQmlTypeNameCache *cache) const;
|
||||
|
||||
|
@ -230,10 +235,6 @@ private:
|
|||
|
||||
QQmlImportNamespace *findQualifiedNamespace(const QHashedStringRef &) const;
|
||||
|
||||
static QTypeRevision matchingQmldirVersion(
|
||||
const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri,
|
||||
QTypeRevision version, QList<QQmlError> *errors);
|
||||
|
||||
QTypeRevision importExtension(
|
||||
QQmlTypeLoader *typeLoader, const QString &uri, QTypeRevision version,
|
||||
const QQmlTypeLoaderQmldirContent *qmldir, QList<QQmlError> *errors);
|
||||
|
@ -242,8 +243,7 @@ private:
|
|||
const QQmlTypeLoaderQmldirContent &qmldir, QTypeRevision version);
|
||||
|
||||
QString redirectQmldirContent(
|
||||
QQmlTypeLoader *typeLoader, QQmlTypeLoaderQmldirContent *qmldir,
|
||||
QQmlImportInstance *inserted);
|
||||
QQmlTypeLoader *typeLoader, QQmlTypeLoaderQmldirContent *qmldir);
|
||||
|
||||
bool getQmldirContent(
|
||||
QQmlTypeLoader *typeLoader, const QString &qmldirIdentifier, const QString &uri,
|
||||
|
|
|
@ -831,7 +831,8 @@ bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &da
|
|||
typeLoader()->setQmldirContent(qmldirIdentifier, data->content());
|
||||
|
||||
const QTypeRevision version = m_importCache->updateQmldirContent(
|
||||
typeLoader(), import->uri, import->qualifier, qmldirIdentifier, qmldirUrl, errors);
|
||||
typeLoader(), import->uri, import->version, import->qualifier, qmldirIdentifier,
|
||||
qmldirUrl, errors);
|
||||
if (!version.isValid())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ qt_internal_add_test(tst_qmlcppcodegen
|
|||
codegen_test_stringbuilderplugin
|
||||
confused_test_module
|
||||
confused_test_moduleplugin
|
||||
with_subdir_test_module
|
||||
with_subdir_test_moduleplugin
|
||||
DEFINES
|
||||
QT_NO_CAST_FROM_ASCII
|
||||
)
|
||||
|
@ -45,6 +47,8 @@ qt_internal_add_test(tst_qmlcppcodegen_interpreted
|
|||
codegen_test_stringbuilderplugin
|
||||
confused_test_module
|
||||
confused_test_moduleplugin
|
||||
with_subdir_test_module
|
||||
with_subdir_test_moduleplugin
|
||||
DEFINES
|
||||
QT_TEST_FORCE_INTERPRETER
|
||||
)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(Confused)
|
||||
add_subdirectory(WithSubDir)
|
||||
|
||||
set(cpp_sources
|
||||
ambiguous.h
|
||||
|
@ -220,6 +221,7 @@ set(qml_files
|
|||
methods.qml
|
||||
modulePrefix.qml
|
||||
moveRegVoid.qml
|
||||
multiRedirect.qml
|
||||
multiforeign.qml
|
||||
multipleCtors.qml
|
||||
namespaceWithEnum.qml
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
qt_add_library(with_subdir_test_module STATIC)
|
||||
qt_autogen_tools_initial_setup(with_subdir_test_module)
|
||||
|
||||
qt_policy(SET QTP0001 NEW)
|
||||
qt_policy(SET QTP0004 NEW)
|
||||
|
||||
qt_add_qml_module(with_subdir_test_module
|
||||
URI WithSubDir
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
qml/GreenRect.qml
|
||||
qml/MyScript.js
|
||||
|
||||
# Hide it at compile time. Otherwise the "TestTypes" module may see it,
|
||||
# but the "verify" module won't.
|
||||
OUTPUT_DIRECTORY HiddenWithSubdir
|
||||
)
|
||||
|
||||
target_link_libraries(with_subdir_test_module
|
||||
PRIVATE Qt6::Qml
|
||||
)
|
||||
|
||||
qt_autogen_tools_initial_setup(with_subdir_test_moduleplugin)
|
|
@ -0,0 +1,6 @@
|
|||
import QtQml
|
||||
import WithSubDir
|
||||
|
||||
QtObject {
|
||||
objectName: "green"
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
.pragma library
|
||||
function hello() { console.log("World") }
|
|
@ -0,0 +1,7 @@
|
|||
import QtQml
|
||||
import WithSubDir
|
||||
|
||||
QtObject {
|
||||
property GreenRect g: GreenRect {}
|
||||
objectName: g.objectName
|
||||
}
|
|
@ -187,6 +187,7 @@ private slots:
|
|||
void multiDirectory();
|
||||
void multiForeign();
|
||||
void multiLookup();
|
||||
void multiRedirect();
|
||||
void multipleCtors();
|
||||
void namespaceWithEnum();
|
||||
void noBuiltinsImport();
|
||||
|
@ -3804,6 +3805,18 @@ void tst_QmlCppCodegen::multiLookup()
|
|||
QCOMPARE(quitSpy.size(), 1);
|
||||
}
|
||||
|
||||
void tst_QmlCppCodegen::multiRedirect()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiRedirect.qml"_s));
|
||||
QVERIFY2(!component.isError(), qPrintable(component.errorString()));
|
||||
|
||||
QScopedPointer<QObject> object(component.create());
|
||||
QVERIFY(!object.isNull());
|
||||
|
||||
QCOMPARE(object->objectName(), u"green"_s);
|
||||
}
|
||||
|
||||
void tst_QmlCppCodegen::multipleCtors()
|
||||
{
|
||||
QQmlEngine engine;
|
||||
|
|
Loading…
Reference in New Issue