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 extension
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 hasCustomParser: false
property bool extensionIsNamespace: false

View File

@ -1286,6 +1286,15 @@ bool QQmlJSScope::isCreatable() const
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 element;

View File

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

View File

@ -213,6 +213,8 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
scope->setIsSingleton(readBoolBinding(script));
} else if (name == QLatin1String("isCreatable")) {
scope->setCreatableFlag(readBoolBinding(script));
} else if (name == QLatin1String("isStructured")) {
scope->setStructuredFlag(readBoolBinding(script));
} else if (name == QLatin1String("isComposite")) {
scope->setIsComposite(readBoolBinding(script));
} else if (name == QLatin1String("hasCustomParser")) {
@ -243,8 +245,9 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast)
addWarning(script->firstSourceLocation(),
tr("Expected only name, prototype, defaultProperty, attachedType, "
"valueType, exports, interfaces, isSingleton, isCreatable, "
"isComposite, hasCustomParser, exportMetaObjectRevisions, "
"deferredNames, and immediateNames in script bindings, not \"%1\".")
"isStructured, isComposite, hasCustomParser, "
"exportMetaObjectRevisions, deferredNames, and immediateNames "
"in script bindings, not \"%1\".")
.arg(name));
}
} 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_NAME { "className" };
static constexpr QLatin1StringView S_CONSTANT { "constant" };
static constexpr QLatin1StringView S_CONSTRUCT { "construct" };
static constexpr QLatin1StringView S_CONSTRUCTORS { "constructors" };
static constexpr QLatin1StringView S_DEFAULT_PROPERTY { "DefaultProperty" };
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_SIGNALS { "signals" };
static constexpr QLatin1StringView S_SLOTS { "slots" };
static constexpr QLatin1StringView S_STRUCTURED { "structured" };
static constexpr QLatin1StringView S_SUPER_CLASSES { "superClasses" };
static constexpr QLatin1StringView S_TRUE { "true" };
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_ATTACHED { "QML.Attached" };
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_EXTENDED { "QML.Extended" };
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 QAnyStringView classDefName = toStringView(*classDef, S_CLASS_NAME);
QAnyStringView foreignTypeName;
bool explicitCreatable = false;
bool isConstructible = false;
for (const QCborValue classInfo : classInfos) {
const QCborMap obj = classInfo.toMap();
const QAnyStringView name = toStringView(obj, S_NAME);
@ -151,7 +151,9 @@ void QmlTypesClassDescription::collect(
removedInRevision = QTypeRevision::fromEncodedVersion(toInt(value));
} else if (name == S_CREATABLE) {
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) {
attachedType = value;
collectRelated(value, types, foreign, defaultRevision);
@ -270,8 +272,7 @@ void QmlTypesClassDescription::collect(
} else if (classDef && classDef->value(S_OBJECT).toBool()) {
accessSemantics = DotQmltypes::S_REFERENCE;
} else {
if (!explicitCreatable)
isCreatable = false;
isCreatable = isConstructible;
if (!classDef) {
if (elementName.isEmpty() || elementName.front().isLower()) {

View File

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

View File

@ -115,6 +115,9 @@ void QmlTypesCreator::writeClassProperties(const QmlTypesClassDescription &colle
if (!collector.isCreatable || collector.isSingleton)
m_qml.writeBooleanBinding(S_IS_CREATABLE, false);
if (collector.isStructured)
m_qml.writeScriptBinding(QLatin1String("isStructured"), QLatin1String("true"));
if (collector.isSingleton)
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()
{
QVERIFY(qmltypesData.contains(

View File

@ -513,6 +513,17 @@ private:
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
{
Q_OBJECT
@ -615,6 +626,7 @@ private slots:
void clonedSignal();
void baseVersionInQmltypes();
void constructibleValueType();
void structuredValueType();
void anonymousAndUncreatable();
void omitInvisible();
void typedEnum();