QmlCompiler: Check builtin type aliases after list resolution

This way we can determine that QList<qreal> is the same as
QList<double>.

Pick-to: 6.4
Fixes: QTBUG-104129
Change-Id: I96df19da1a613558b950aa6cee46159024c19cc9
Reviewed-by: Evgeniy Dushistov <dushistov@mail.ru>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
Ulf Hermann 2022-06-13 09:25:40 +02:00
parent fb3a81623a
commit e18919d3f2
4 changed files with 41 additions and 26 deletions

View File

@ -142,6 +142,32 @@ void QmlTypesCreator::writeType(const QJsonObject &property, const QString &key)
bool isList = false;
bool isPointer = false;
auto handleList = [&](QLatin1String list) {
if (!type.startsWith(list) || !type.endsWith(QLatin1Char('>')))
return false;
const int listSize = list.size();
const QString elementType = type.mid(listSize, type.size() - listSize - 1).trimmed();
// QQmlListProperty internally constructs the pointer. Passing an explicit '*' will
// produce double pointers. QList is only for value types. We can't handle QLists
// of pointers (unless specially registered, but then they're not isList).
if (elementType.endsWith(QLatin1Char('*')))
return false;
isList = true;
type = elementType;
return true;
};
if (!handleList(QLatin1String("QQmlListProperty<"))
&& !handleList(QLatin1String("QList<"))) {
if (type.endsWith(QLatin1Char('*'))) {
isPointer = true;
type = type.left(type.size() - 1);
}
}
if (type == QLatin1String("qreal")) {
#ifdef QT_COORD_TYPE_STRING
type = QLatin1String(QT_COORD_TYPE_STRING)
@ -156,32 +182,6 @@ void QmlTypesCreator::writeType(const QJsonObject &property, const QString &key)
type = QLatin1String("qlonglong");
} else if (type == QLatin1String("quint64")) {
type = QLatin1String("qulonglong");
} else {
auto handleList = [&](QLatin1String list) {
if (!type.startsWith(list) || !type.endsWith(QLatin1Char('>')))
return false;
const int listSize = list.size();
const QString elementType = type.mid(listSize, type.size() - listSize - 1).trimmed();
// QQmlListProperty internally constructs the pointer. Passing an explicit '*' will
// produce double pointers. QList is only for value types. We can't handle QLists
// of pointers (unless specially registered, but then they're not isList).
if (elementType.endsWith(QLatin1Char('*')))
return false;
isList = true;
type = elementType;
return true;
};
if (!handleList(QLatin1String("QQmlListProperty<"))
&& !handleList(QLatin1String("QList<"))) {
if (type.endsWith(QLatin1Char('*'))) {
isPointer = true;
type = type.left(type.size() - 1);
}
}
}
m_qml.writeScriptBinding(typeKey, enquote(type));

View File

@ -21,4 +21,10 @@ CppBaseClass {
function incA() : void {
self.a = self.boo[1];
}
property real b: hoo[0]
function incB() : void {
self.b = self.hoo[1];
}
}

View File

@ -14,6 +14,7 @@ class CppBaseClass : public QObject
Q_PROPERTY(int cppProp MEMBER cppProp BINDABLE cppPropBindable FINAL)
Q_PROPERTY(int cppProp2 MEMBER cppProp2 BINDABLE cppProp2Bindable FINAL)
Q_PROPERTY(QList<int> boo MEMBER boo FINAL CONSTANT)
Q_PROPERTY(QList<qreal> hoo MEMBER hoo FINAL CONSTANT)
QML_ELEMENT
public:
CppBaseClass(QObject *parent = nullptr)
@ -21,6 +22,9 @@ public:
{
boo.append(16);
boo.append(17);
hoo.append(0.25);
hoo.append(13.5);
}
QProperty<int> cppProp;
@ -33,6 +37,7 @@ public:
private:
QList<int> boo;
QList<qreal> hoo;
};
inline void CppBaseClass::doCall(QObject *foo)

View File

@ -153,6 +153,10 @@ void tst_QmlCppCodegen::cppValueTypeList()
QCOMPARE(object->property("a").toInt(), 16);
QMetaObject::invokeMethod(object.data(), "incA");
QCOMPARE(object->property("a").toInt(), 17);
QCOMPARE(object->property("b").toDouble(), 0.25);
QMetaObject::invokeMethod(object.data(), "incB");
QCOMPARE(object->property("b").toDouble(), 13.5);
}
void tst_QmlCppCodegen::anchorsFill()