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

View File

@ -158,6 +158,7 @@ protected:
bool isNumeric(const QQmlJSScope::ConstPtr &type) const;
bool checkEnums(const QQmlJSScope::ConstPtr &scope, const QString &name,
QQmlJSRegisterContent *result, BaseOrExtension mode) const;
QQmlJSRegisterContent lengthProperty(bool isWritable, const QQmlJSScope::ConstPtr &scope) const;
QQmlJSScope::ConstPtr m_voidType;
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 additionalImplicitImport();
void listIndices();
private:
QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult,
@ -950,5 +951,10 @@ void TestQmllint::additionalImplicitImport()
.isEmpty());
}
void TestQmllint::listIndices()
{
QVERIFY(runQmllint("listIndices.qml", true, {"--compiler=warning"}, false).isEmpty());
}
QTEST_MAIN(TestQmllint)
#include "tst_qmllint.moc"