qmllint: Support "length" property of sequence types

In particular, you can set and get the length of QQmlListProperty.

Change-Id: I5c8e03a752aad9bf9789faf85a0c3e280f0cbb4b
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
This commit is contained in:
Ulf Hermann 2021-09-22 14:48:58 +02:00
parent 5a8b5f59e4
commit a4893077c6
4 changed files with 39 additions and 11 deletions

View File

@ -90,7 +90,7 @@ QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer, const QmlIR::Do
QQmlJSScope::Ptr listPropertyType = QQmlJSScope::create(); QQmlJSScope::Ptr listPropertyType = QQmlJSScope::create();
listPropertyType->setInternalName(u"QQmlListProperty<QObject>"_qs); listPropertyType->setInternalName(u"QQmlListProperty<QObject>"_qs);
listPropertyType->setFileName(u"qqmllist.h"_qs); listPropertyType->setFileName(u"qqmllist.h"_qs);
listPropertyType->setAccessSemantics(QQmlJSScope::AccessSemantics::Value); listPropertyType->setAccessSemantics(QQmlJSScope::AccessSemantics::Sequence);
m_listPropertyType = listPropertyType; m_listPropertyType = listPropertyType;
// This is pre-sorted. Don't mess it up. // This is pre-sorted. Don't mess it up.
@ -754,6 +754,17 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS
return false; return false;
} }
QQmlJSRegisterContent QQmlJSTypeResolver::lengthProperty(
bool isWritable, const QQmlJSScope::ConstPtr &scope) const
{
QQmlJSMetaProperty prop;
prop.setPropertyName(u"length"_qs);
prop.setTypeName(u"int"_qs);
prop.setType(intType());
prop.setIsWritable(isWritable);
return QQmlJSRegisterContent::create(intType(), prop, QQmlJSRegisterContent::Builtin, scope);
}
QQmlJSRegisterContent QQmlJSTypeResolver::memberType(const QQmlJSScope::ConstPtr &type, QQmlJSRegisterContent QQmlJSTypeResolver::memberType(const QQmlJSScope::ConstPtr &type,
const QString &name) const const QString &name) const
{ {
@ -769,13 +780,9 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType(const QQmlJSScope::ConstPtr
QQmlJSRegisterContent::JavaScriptObjectProperty, type); QQmlJSRegisterContent::JavaScriptObjectProperty, type);
} }
if (type == stringType() && name == u"length"_qs) { if ((type == stringType() || type->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
QQmlJSMetaProperty prop; && name == u"length"_qs) {
prop.setPropertyName(name); return lengthProperty(type != stringType(), type);
prop.setTypeName(u"int"_qs);
prop.setType(intType());
prop.setIsWritable(false);
return QQmlJSRegisterContent::create(intType(), prop, QQmlJSRegisterContent::Builtin, type);
} }
const auto check = [&](const QQmlJSScope::ConstPtr &scope, BaseOrExtension mode) { const auto check = [&](const QQmlJSScope::ConstPtr &scope, BaseOrExtension mode) {
@ -859,8 +866,8 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType(const QQmlJSRegisterContent
} }
if (type.isProperty()) { if (type.isProperty()) {
const auto prop = type.property(); const auto prop = type.property();
if (prop.isList()) if (prop.isList() && name == u"length"_qs)
return {}; return lengthProperty(true, listPropertyType());
return memberType(prop.type(), name); return memberType(prop.type(), name);
} }
if (type.isEnumeration()) { if (type.isEnumeration()) {

View File

@ -158,6 +158,7 @@ protected:
bool isNumeric(const QQmlJSScope::ConstPtr &type) const; bool isNumeric(const QQmlJSScope::ConstPtr &type) const;
bool checkEnums(const QQmlJSScope::ConstPtr &scope, const QString &name, bool checkEnums(const QQmlJSScope::ConstPtr &scope, const QString &name,
QQmlJSRegisterContent *result, BaseOrExtension mode) const; QQmlJSRegisterContent *result, BaseOrExtension mode) const;
QQmlJSRegisterContent lengthProperty(bool isWritable, const QQmlJSScope::ConstPtr &scope) const;
QQmlJSScope::ConstPtr m_voidType; QQmlJSScope::ConstPtr m_voidType;
QQmlJSScope::ConstPtr m_numberType; QQmlJSScope::ConstPtr m_numberType;

View File

@ -0,0 +1,14 @@
pragma Strict
import QtQml
QtObject {
id: self
property list<QtObject> items
property int numItems: items.length
Component.onCompleted: {
items.length = 3
for (var i = 0; i < 3; ++i)
items[i] = self
}
}

View File

@ -71,6 +71,7 @@ private Q_SLOTS:
void settingsFile(); void settingsFile();
void additionalImplicitImport(); void additionalImplicitImport();
void listIndices();
private: private:
QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult, QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult,
@ -947,7 +948,12 @@ void TestQmllint::additionalImplicitImport()
QVERIFY(runQmllint("additionalImplicitImport.qml", true, QVERIFY(runQmllint("additionalImplicitImport.qml", true,
QStringList() << "--resource" << testFile("implicitImportResource.qrc"), QStringList() << "--resource" << testFile("implicitImportResource.qrc"),
false) false)
.isEmpty()); .isEmpty());
}
void TestQmllint::listIndices()
{
QVERIFY(runQmllint("listIndices.qml", true, {"--compiler=warning"}, false).isEmpty());
} }
QTEST_MAIN(TestQmllint) QTEST_MAIN(TestQmllint)