qmltyperegistrar: Record creation method of value types

We need this to tell the compilers how to create value types.

Change-Id: Iaef60eef64552df1a155a780aa2c4f4c44533184
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
This commit is contained in:
Ulf Hermann 2023-06-30 10:13:28 +02:00
parent dba7d84843
commit 97d698f6e7
10 changed files with 61 additions and 7 deletions

View File

@ -18,7 +18,8 @@ QtObject {
property string valueType property string valueType
property string extension property string extension
property bool isSingleton: false property bool isSingleton: false
property bool isCreatable: name.length > 0 property bool isCreatable: accessSemantics === "reference" && name.length > 0
property bool isStructured: false
property bool isComposite: false property bool isComposite: false
property bool hasCustomParser: false property bool hasCustomParser: false
property bool extensionIsNamespace: false property bool extensionIsNamespace: false

View File

@ -1286,6 +1286,15 @@ bool QQmlJSScope::isCreatable() const
return false; return false;
} }
bool QQmlJSScope::isStructured() const
{
for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().get()) {
if (!scope->isComposite())
return scope->hasStructuredFlag();
}
return false;
}
QQmlSA::Element QQmlJSScope::createQQmlSAElement(const ConstPtr &ptr) QQmlSA::Element QQmlJSScope::createQQmlSAElement(const ConstPtr &ptr)
{ {
QQmlSA::Element element; QQmlSA::Element element;

View File

@ -131,6 +131,7 @@ public:
HasBaseTypeError = 0x100, HasBaseTypeError = 0x100,
HasExtensionNamespace = 0x200, HasExtensionNamespace = 0x200,
IsListProperty = 0x400, IsListProperty = 0x400,
Structured = 0x800,
}; };
Q_DECLARE_FLAGS(Flags, Flag) Q_DECLARE_FLAGS(Flags, Flag)
Q_FLAGS(Flags); Q_FLAGS(Flags);
@ -531,8 +532,13 @@ QT_WARNING_POP
} }
bool isSingleton() const { return m_flags & Singleton; } bool isSingleton() const { return m_flags & Singleton; }
bool isCreatable() const; bool isCreatable() const;
bool hasCreatableFlag() const { return m_flags & Creatable; } bool hasCreatableFlag() const { return m_flags & Creatable; }
bool isStructured() const;
bool hasStructuredFlag() const { return m_flags & Structured; }
/*! /*!
* \internal * \internal
* *
@ -547,6 +553,7 @@ QT_WARNING_POP
bool extensionIsNamespace() const { return m_flags & HasExtensionNamespace; } bool extensionIsNamespace() const { return m_flags & HasExtensionNamespace; }
void setIsSingleton(bool v) { m_flags.setFlag(Singleton, v); } void setIsSingleton(bool v) { m_flags.setFlag(Singleton, v); }
void setCreatableFlag(bool v) { m_flags.setFlag(Creatable, v); } void setCreatableFlag(bool v) { m_flags.setFlag(Creatable, v); }
void setStructuredFlag(bool v) { m_flags.setFlag(Structured, v); }
void setIsComposite(bool v) { m_flags.setFlag(Composite, v); } void setIsComposite(bool v) { m_flags.setFlag(Composite, v); }
void setIsScript(bool v) { m_flags.setFlag(Script, v); } void setIsScript(bool v) { m_flags.setFlag(Script, v); }
void setHasCustomParser(bool v) void setHasCustomParser(bool v)

View File

@ -213,6 +213,8 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
scope->setIsSingleton(readBoolBinding(script)); scope->setIsSingleton(readBoolBinding(script));
} else if (name == QLatin1String("isCreatable")) { } else if (name == QLatin1String("isCreatable")) {
scope->setCreatableFlag(readBoolBinding(script)); scope->setCreatableFlag(readBoolBinding(script));
} else if (name == QLatin1String("isStructured")) {
scope->setStructuredFlag(readBoolBinding(script));
} else if (name == QLatin1String("isComposite")) { } else if (name == QLatin1String("isComposite")) {
scope->setIsComposite(readBoolBinding(script)); scope->setIsComposite(readBoolBinding(script));
} else if (name == QLatin1String("hasCustomParser")) { } else if (name == QLatin1String("hasCustomParser")) {
@ -243,8 +245,9 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
addWarning(script->firstSourceLocation(), addWarning(script->firstSourceLocation(),
tr("Expected only name, prototype, defaultProperty, attachedType, " tr("Expected only name, prototype, defaultProperty, attachedType, "
"valueType, exports, interfaces, isSingleton, isCreatable, " "valueType, exports, interfaces, isSingleton, isCreatable, "
"isComposite, hasCustomParser, exportMetaObjectRevisions, " "isStructured, isComposite, hasCustomParser, "
"deferredNames, and immediateNames in script bindings, not \"%1\".") "exportMetaObjectRevisions, deferredNames, and immediateNames "
"in script bindings, not \"%1\".")
.arg(name)); .arg(name));
} }
} else { } else {

View File

@ -88,6 +88,7 @@ static constexpr QLatin1StringView S_CLASSES { "classes" };
static constexpr QLatin1StringView S_CLASS_INFOS { "classInfos" }; static constexpr QLatin1StringView S_CLASS_INFOS { "classInfos" };
static constexpr QLatin1StringView S_CLASS_NAME { "className" }; static constexpr QLatin1StringView S_CLASS_NAME { "className" };
static constexpr QLatin1StringView S_CONSTANT { "constant" }; static constexpr QLatin1StringView S_CONSTANT { "constant" };
static constexpr QLatin1StringView S_CONSTRUCT { "construct" };
static constexpr QLatin1StringView S_CONSTRUCTORS { "constructors" }; static constexpr QLatin1StringView S_CONSTRUCTORS { "constructors" };
static constexpr QLatin1StringView S_DEFAULT_PROPERTY { "DefaultProperty" }; static constexpr QLatin1StringView S_DEFAULT_PROPERTY { "DefaultProperty" };
static constexpr QLatin1StringView S_DEFERRED_PROPERTY_NAMES { "DeferredPropertyNames" }; static constexpr QLatin1StringView S_DEFERRED_PROPERTY_NAMES { "DeferredPropertyNames" };
@ -123,6 +124,7 @@ static constexpr QLatin1StringView S_RETURN_TYPE { "returnType"
static constexpr QLatin1StringView S_REVISION { "revision" }; static constexpr QLatin1StringView S_REVISION { "revision" };
static constexpr QLatin1StringView S_SIGNALS { "signals" }; static constexpr QLatin1StringView S_SIGNALS { "signals" };
static constexpr QLatin1StringView S_SLOTS { "slots" }; static constexpr QLatin1StringView S_SLOTS { "slots" };
static constexpr QLatin1StringView S_STRUCTURED { "structured" };
static constexpr QLatin1StringView S_SUPER_CLASSES { "superClasses" }; static constexpr QLatin1StringView S_SUPER_CLASSES { "superClasses" };
static constexpr QLatin1StringView S_TRUE { "true" }; static constexpr QLatin1StringView S_TRUE { "true" };
static constexpr QLatin1StringView S_TYPE { "type" }; static constexpr QLatin1StringView S_TYPE { "type" };
@ -135,6 +137,7 @@ namespace Qml {
static constexpr QLatin1StringView S_ADDED_IN_VERSION { "QML.AddedInVersion" }; static constexpr QLatin1StringView S_ADDED_IN_VERSION { "QML.AddedInVersion" };
static constexpr QLatin1StringView S_ATTACHED { "QML.Attached" }; static constexpr QLatin1StringView S_ATTACHED { "QML.Attached" };
static constexpr QLatin1StringView S_CREATABLE { "QML.Creatable" }; static constexpr QLatin1StringView S_CREATABLE { "QML.Creatable" };
static constexpr QLatin1StringView S_CREATION_METHOD { "QML.CreationMethod" };
static constexpr QLatin1StringView S_ELEMENT { "QML.Element" }; static constexpr QLatin1StringView S_ELEMENT { "QML.Element" };
static constexpr QLatin1StringView S_EXTENDED { "QML.Extended" }; static constexpr QLatin1StringView S_EXTENDED { "QML.Extended" };
static constexpr QLatin1StringView S_EXTENSION_IS_NAMESPACE { "QML.ExtensionIsNamespace" }; static constexpr QLatin1StringView S_EXTENSION_IS_NAMESPACE { "QML.ExtensionIsNamespace" };

View File

@ -116,7 +116,7 @@ void QmlTypesClassDescription::collect(
const auto classInfos = classDef->value(S_CLASS_INFOS).toArray(); const auto classInfos = classDef->value(S_CLASS_INFOS).toArray();
const QAnyStringView classDefName = toStringView(*classDef, S_CLASS_NAME); const QAnyStringView classDefName = toStringView(*classDef, S_CLASS_NAME);
QAnyStringView foreignTypeName; QAnyStringView foreignTypeName;
bool explicitCreatable = false; bool isConstructible = false;
for (const QCborValue classInfo : classInfos) { for (const QCborValue classInfo : classInfos) {
const QCborMap obj = classInfo.toMap(); const QCborMap obj = classInfo.toMap();
const QAnyStringView name = toStringView(obj, S_NAME); const QAnyStringView name = toStringView(obj, S_NAME);
@ -151,7 +151,9 @@ void QmlTypesClassDescription::collect(
removedInRevision = QTypeRevision::fromEncodedVersion(toInt(value)); removedInRevision = QTypeRevision::fromEncodedVersion(toInt(value));
} else if (name == S_CREATABLE) { } else if (name == S_CREATABLE) {
isCreatable = (value != S_FALSE); isCreatable = (value != S_FALSE);
explicitCreatable = true; } else if (name == S_CREATION_METHOD) {
isStructured = (value == S_STRUCTURED);
isConstructible = isStructured || (value == S_CONSTRUCT);
} else if (name == S_ATTACHED) { } else if (name == S_ATTACHED) {
attachedType = value; attachedType = value;
collectRelated(value, types, foreign, defaultRevision); collectRelated(value, types, foreign, defaultRevision);
@ -270,8 +272,7 @@ void QmlTypesClassDescription::collect(
} else if (classDef && classDef->value(S_OBJECT).toBool()) { } else if (classDef && classDef->value(S_OBJECT).toBool()) {
accessSemantics = DotQmltypes::S_REFERENCE; accessSemantics = DotQmltypes::S_REFERENCE;
} else { } else {
if (!explicitCreatable) isCreatable = isConstructible;
isCreatable = false;
if (!classDef) { if (!classDef) {
if (elementName.isEmpty() || elementName.front().isLower()) { if (elementName.isEmpty() || elementName.front().isLower()) {

View File

@ -43,6 +43,7 @@ struct QmlTypesClassDescription
QTypeRevision addedInRevision; QTypeRevision addedInRevision;
QTypeRevision removedInRevision; QTypeRevision removedInRevision;
bool isCreatable = true; bool isCreatable = true;
bool isStructured = false;
bool isSingleton = false; bool isSingleton = false;
bool hasCustomParser = false; bool hasCustomParser = false;
bool omitFromQmlTypes = false; bool omitFromQmlTypes = false;

View File

@ -115,6 +115,9 @@ void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &colle
if (!collector.isCreatable || collector.isSingleton) if (!collector.isCreatable || collector.isSingleton)
m_qml.writeBooleanBinding(S_IS_CREATABLE, false); m_qml.writeBooleanBinding(S_IS_CREATABLE, false);
if (collector.isStructured)
m_qml.writeScriptBinding(QLatin1String("isStructured"), QLatin1String("true"));
if (collector.isSingleton) if (collector.isSingleton)
m_qml.writeBooleanBinding(S_IS_SINGLETON, true); m_qml.writeBooleanBinding(S_IS_SINGLETON, true);

View File

@ -593,6 +593,20 @@ void tst_qmltyperegistrar::constructibleValueType()
})")); })"));
} }
void tst_qmltyperegistrar::structuredValueType()
{
QVERIFY(qmltypesData.contains(
R"(Component {
file: "tst_qmltyperegistrar.h"
name: "Structured"
accessSemantics: "value"
exports: ["QmlTypeRegistrarTest/structured 1.0"]
isStructured: true
exportMetaObjectRevisions: [256]
Property { name: "i"; type: "int"; index: 0; isFinal: true }
})"));
}
void tst_qmltyperegistrar::anonymousAndUncreatable() void tst_qmltyperegistrar::anonymousAndUncreatable()
{ {
QVERIFY(qmltypesData.contains( QVERIFY(qmltypesData.contains(

View File

@ -513,6 +513,17 @@ private:
int m_i; int m_i;
}; };
class Structured
{
Q_GADGET
QML_VALUE_TYPE(structured)
QML_STRUCTURED_VALUE
Q_PROPERTY(int i MEMBER m_i FINAL)
private:
int m_i;
};
class AnonymousAndUncreatable : public QObject class AnonymousAndUncreatable : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -615,6 +626,7 @@ private slots:
void clonedSignal(); void clonedSignal();
void baseVersionInQmltypes(); void baseVersionInQmltypes();
void constructibleValueType(); void constructibleValueType();
void structuredValueType();
void anonymousAndUncreatable(); void anonymousAndUncreatable();
void omitInvisible(); void omitInvisible();
void typedEnum(); void typedEnum();