From c2fd73b516f6021f0ebb9f5cfd4de79f3f437f51 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 17 Mar 2023 11:42:50 +0100 Subject: [PATCH] qmltyperegistrar: Do not guess types with upper case names We generally need to guess value types since there are value types without metaobjects of their own, such as QRectF and QSizeF. However, if they have upper case element names, they are clearly not in that category. Guessing those as value types will make further tools produce follow-up mistakes. Pick-to: 6.2 6.5 6.5.0 Fixes: QTBUG-111986 Change-Id: Ic15ef8c726eb3913c87eb4a300794f321f59fafa Reviewed-by: Fabian Kosmale --- .../qqmltypesclassdescription.cpp | 30 +++++++++++++++---- .../qmltyperegistrar/tst_qmltyperegistrar.cpp | 7 +++++ .../qmltyperegistrar/tst_qmltyperegistrar.h | 12 ++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/qmltyperegistrar/qqmltypesclassdescription.cpp b/src/qmltyperegistrar/qqmltypesclassdescription.cpp index 6337ae5dac..bc3eb948a4 100644 --- a/src/qmltyperegistrar/qqmltypesclassdescription.cpp +++ b/src/qmltyperegistrar/qqmltypesclassdescription.cpp @@ -265,11 +265,31 @@ void QmlTypesClassDescription::collect( } else { if (!explicitCreatable) isCreatable = false; - // If no classDef, we assume it's a value type defined by the foreign/extended trick. - // Objects and namespaces always have metaobjects and therefore classDefs. - accessSemantics = (!classDef || classDef->value(QLatin1String("gadget")).toBool()) - ? QLatin1String("value") - : QLatin1String("none"); + + if (!classDef) { + if (elementName.isEmpty() || elementName[0].isLower()) { + // If no classDef, we generally assume it's a value type defined by the + // foreign/extended trick. + accessSemantics = QLatin1String("value"); + } else { + // Objects and namespaces always have metaobjects and therefore classDefs. + // However, we may not be able to resolve the metaobject at compile time. See + // the "Invisible" test case. In that case, we must not assume anything about + // access semantics. + + qWarning() << "Warning: Refusing to generate non-lowercase name" + << elementName << "for unknown foreign type"; + elementName.clear(); + + // Make it completely inaccessible. + // We cannot get enums from anonymous types after all. + accessSemantics = QLatin1String("none"); + } + } else if (classDef->value(QLatin1String("gadget")).toBool()) { + accessSemantics = QLatin1String("value"); + } else { + accessSemantics = QLatin1String("none"); + } } } diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index 70a86793fb..65d954d07f 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -602,4 +602,11 @@ void tst_qmltyperegistrar::anonymousAndUncreatable() })")); } +void tst_qmltyperegistrar::omitInvisible() +{ + // If it cannot resolve the type a QML_FOREIGN refers to, it should not generate anything. + QVERIFY(qmltypesData.contains( + R"(Component { file: "tst_qmltyperegistrar.h"; name: "Invisible"; accessSemantics: "none" })")); +} + QTEST_MAIN(tst_qmltyperegistrar) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index ba1d5a8768..e53926f22e 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -520,6 +520,17 @@ class AnonymousAndUncreatable : public QObject QML_UNCREATABLE("Pointless uncreatable message") }; +class Invisible : public QObject +{ +}; + +struct InvisibleForeign +{ + Q_GADGET + QML_FOREIGN(Invisible) + QML_NAMED_ELEMENT(Invisible) +}; + class tst_qmltyperegistrar : public QObject { Q_OBJECT @@ -570,6 +581,7 @@ private slots: void baseVersionInQmltypes(); void constructibleValueType(); void anonymousAndUncreatable(); + void omitInvisible(); private: QByteArray qmltypesData;