diff options
-rw-r--r-- | src/qmlcompiler/qqmljsimporter.cpp | 51 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimporter_p.h | 4 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypedescriptionreader.cpp | 5 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypedescriptionreader_p.h | 4 | ||||
-rw-r--r-- | src/qmldom/qqmldomtypesreader.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/multiforeign.h | 51 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/multiforeign.qml | 10 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 11 |
9 files changed, 115 insertions, 25 deletions
diff --git a/src/qmlcompiler/qqmljsimporter.cpp b/src/qmlcompiler/qqmljsimporter.cpp index f8adeb79c2..c491e6d86e 100644 --- a/src/qmlcompiler/qqmljsimporter.cpp +++ b/src/qmlcompiler/qqmljsimporter.cpp @@ -35,7 +35,7 @@ static QQmlDirParser createQmldirParserForFile(const QString &filename) } void QQmlJSImporter::readQmltypes( - const QString &filename, QHash<QString, QQmlJSExportedScope> *objects, + const QString &filename, QList<QQmlJSExportedScope> *objects, QList<QQmlDirParser::Import> *dependencies) { const QFileInfo fileInfo(filename); @@ -198,7 +198,7 @@ QQmlJSImporter::Import QQmlJSImporter::readQmldir(const QString &path) reader.typeNamespace(), it.key(), it->version, QTypeRevision())); } for (auto it = qmlComponents.begin(), end = qmlComponents.end(); it != end; ++it) - result.objects.insert(it.key(), it.value()); + result.objects.append(it.value()); const auto scripts = reader.scripts(); for (const auto &script : scripts) { @@ -224,7 +224,7 @@ QQmlJSImporter::Import QQmlJSImporter::readDirectory(const QString &directory) for (const auto &entry : resources) { const QString name = QFileInfo(entry.resourcePath).baseName(); if (name.front().isUpper()) { - import.objects.insert(name, { + import.objects.append({ localFile2ScopeTree(entry.filePath), { QQmlJSScope::Export(QString(), name, QTypeRevision(), QTypeRevision()) } }); @@ -244,12 +244,21 @@ QQmlJSImporter::Import QQmlJSImporter::readDirectory(const QString &directory) QDir::NoFilter }; while (it.hasNext()) { - it.next(); - if (!it.fileName().front().isUpper()) - continue; // Non-uppercase names cannot be imported anyway. + QString name = it.nextFileInfo().completeBaseName(); - const QString name = QFileInfo(it.filePath()).baseName(); - import.objects.insert(name, { + // Non-uppercase names cannot be imported anyway. + if (!name.front().isUpper()) + continue; + + // .ui.qml is fine + if (name.endsWith(u".ui")) + name = name.chopped(3); + + // Names with dots in them cannot be imported either. + if (name.contains(u'.')) + continue; + + import.objects.append({ localFile2ScopeTree(it.filePath()), { QQmlJSScope::Export(QString(), name, QTypeRevision(), QTypeRevision()) } }); @@ -415,9 +424,7 @@ void QQmlJSImporter::processImport(const QQmlJSScope::Import &importDescription, } // add objects - for (auto it = import.objects.begin(); it != import.objects.end(); ++it) { - const auto &val = it.value(); - + for (const auto &val : import.objects) { const QString cppName = isComposite(val.scope) ? prefixedName(anonPrefix, internalName(val.scope)) : internalName(val.scope); @@ -470,9 +477,7 @@ void QQmlJSImporter::processImport(const QQmlJSScope::Import &importDescription, } } - for (auto it = import.objects.begin(); it != import.objects.end(); ++it) { - const auto &val = it.value(); - + for (const auto &val : qAsConst(import.objects)) { // Otherwise we have already done it in localFile2ScopeTree() if (!val.scope.factory() && val.scope->baseType().isNull()) { @@ -546,10 +551,22 @@ QQmlJSImporter::AvailableTypes QQmlJSImporter::builtinImportHelper() const QQmlJSScope::Import builtinImport( QString(), QStringLiteral("QML"), QTypeRevision::fromVersion(1, 0), false, true); - const QQmlJSScope::ConstPtr intType = result.objects[u"int"_s].scope; - Q_ASSERT(intType); + QQmlJSScope::ConstPtr intType; + QQmlJSScope::ConstPtr arrayType; + + for (const QQmlJSExportedScope &exported : result.objects) { + if (exported.scope->internalName() == u"int"_s) { + intType = exported.scope; + if (!arrayType.isNull()) + break; + } else if (exported.scope->internalName() == u"Array"_s) { + arrayType = exported.scope; + if (!intType.isNull()) + break; + } + } - const QQmlJSScope::ConstPtr arrayType = result.objects[u"Array"_s].scope; + Q_ASSERT(intType); Q_ASSERT(arrayType); m_builtins = AvailableTypes(ImportedTypes( diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h index 017917d3cf..792e26a291 100644 --- a/src/qmlcompiler/qqmljsimporter_p.h +++ b/src/qmlcompiler/qqmljsimporter_p.h @@ -115,7 +115,7 @@ private: bool isStaticModule = false; bool isSystemModule = false; - QHash<QString, QQmlJSExportedScope> objects; + QList<QQmlJSExportedScope> objects; QHash<QString, QQmlJSExportedScope> scripts; QList<QQmlDirParser::Import> imports; QList<QQmlDirParser::Import> dependencies; @@ -130,7 +130,7 @@ private: void importDependencies(const QQmlJSImporter::Import &import, AvailableTypes *types, const QString &prefix = QString(), QTypeRevision version = QTypeRevision(), bool isDependency = false); - void readQmltypes(const QString &filename, QHash<QString, QQmlJSExportedScope> *objects, + void readQmltypes(const QString &filename, QList<QQmlJSExportedScope> *objects, QList<QQmlDirParser::Import> *dependencies); Import readQmldir(const QString &dirname); Import readDirectory(const QString &directory); diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp index 8c6368dfde..9360119c5c 100644 --- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp +++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp @@ -31,8 +31,7 @@ QString toString(const UiQualifiedId *qualifiedId, QChar delimiter = QLatin1Char } bool QQmlJSTypeDescriptionReader::operator()( - QHash<QString, QQmlJSExportedScope> *objects, - QStringList *dependencies) + QList<QQmlJSExportedScope> *objects, QStringList *dependencies) { Engine engine; @@ -260,7 +259,7 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast) if (metaObjectRevisions) checkMetaObjectRevisions(metaObjectRevisions, &exports); - m_objects->insert(scope->internalName(), {scope, exports}); + m_objects->append({scope, exports}); } void QQmlJSTypeDescriptionReader::readSignalOrMethod(UiObjectDefinition *ast, bool isMethod, diff --git a/src/qmlcompiler/qqmljstypedescriptionreader_p.h b/src/qmlcompiler/qqmljstypedescriptionreader_p.h index 58a01d6fb8..37dd388308 100644 --- a/src/qmlcompiler/qqmljstypedescriptionreader_p.h +++ b/src/qmlcompiler/qqmljstypedescriptionreader_p.h @@ -33,7 +33,7 @@ public: explicit QQmlJSTypeDescriptionReader(QString fileName, QString data) : m_fileName(std::move(fileName)), m_source(std::move(data)) {} - bool operator()(QHash<QString, QQmlJSExportedScope> *objects, QStringList *dependencies); + bool operator()(QList<QQmlJSExportedScope> *objects, QStringList *dependencies); QString errorMessage() const { return m_errorMessage; } QString warningMessage() const { return m_warningMessage; } @@ -73,7 +73,7 @@ private: QString m_source; QString m_errorMessage; QString m_warningMessage; - QHash<QString, QQmlJSExportedScope> *m_objects = nullptr; + QList<QQmlJSExportedScope> *m_objects = nullptr; QStringList *m_dependencies = nullptr; }; diff --git a/src/qmldom/qqmldomtypesreader.cpp b/src/qmldom/qqmldomtypesreader.cpp index 355ef99eba..69fba60047 100644 --- a/src/qmldom/qqmldomtypesreader.cpp +++ b/src/qmldom/qqmldomtypesreader.cpp @@ -246,7 +246,7 @@ bool QmltypesReader::parse() QQmlJSTypeDescriptionReader reader(qmltypesFilePtr()->canonicalFilePath(), qmltypesFilePtr()->code()); QStringList dependencies; - QHash<QString, QQmlJSExportedScope> objects; + QList<QQmlJSExportedScope> objects; m_isValid = reader(&objects, &dependencies); for (const auto &obj : std::as_const(objects)) insertComponent(obj.scope, obj.exports); diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index b7f8f28aeb..5bb30f1969 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -8,6 +8,7 @@ set(cpp_sources dynamicmeta.h gadgetwithenum.h invisible.h + multiforeign.h objectwithmethod.h person.cpp person.h state.h @@ -119,6 +120,7 @@ set(qml_files methods.qml modulePrefix.qml moveRegVoid.qml + multiforeign.qml noBindingLoop.qml noQQmlData.qml nonNotifyable.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/multiforeign.h b/tests/auto/qml/qmlcppcodegen/data/multiforeign.h new file mode 100644 index 0000000000..290b6370f5 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/multiforeign.h @@ -0,0 +1,51 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef MULTIFOREIGN_H +#define MULTIFOREIGN_H + +#include <QtCore/qobject.h> +#include <QtQml/qqml.h> + +class Autochthon : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString location READ location WRITE setLocation NOTIFY locationChanged FINAL) + +public: + const QString &location() const + { + return m_location; + } + + void setLocation(const QString &newLocation) + { + if (m_location == newLocation) + return; + m_location = newLocation; + emit locationChanged(); + } + +signals: + void locationChanged(); + +private: + QString m_location; +}; + +struct Foreign1 +{ + Q_GADGET + QML_FOREIGN(Autochthon) + QML_ELEMENT +}; + +struct Foreign2 +{ + Q_GADGET + QML_FOREIGN(Autochthon) + QML_ELEMENT +}; + + +#endif // MULTIFOREIGN_H diff --git a/tests/auto/qml/qmlcppcodegen/data/multiforeign.qml b/tests/auto/qml/qmlcppcodegen/data/multiforeign.qml new file mode 100644 index 0000000000..0db62fe875 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/multiforeign.qml @@ -0,0 +1,10 @@ +pragma Strict +import TestTypes +import QtQml + +QtObject { + objectName: f1.location + " and " + f2.location + property Foreign1 f1: Foreign1 { location: "not here" } + property Foreign2 f2: Foreign2 { location: "not there" } + +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 4b4cc6042a..1dd4c0fcf0 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -147,6 +147,7 @@ private slots: void callWithSpread(); void nullComparison(); void consoleObject(); + void multiForeign(); }; void tst_QmlCppCodegen::initTestCase() @@ -2859,6 +2860,16 @@ void tst_QmlCppCodegen::consoleObject() QVERIFY(!o.isNull()); } +void tst_QmlCppCodegen::multiForeign() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiforeign.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + QCOMPARE(o->objectName(), u"not here and not there"_s); +} + QTEST_MAIN(tst_QmlCppCodegen) #include "tst_qmlcppcodegen.moc" |