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 <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2023-03-17 11:42:50 +01:00
parent bf12f5efa4
commit c2fd73b516
3 changed files with 44 additions and 5 deletions

View File

@ -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");
}
}
}

View File

@ -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)

View File

@ -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;