3#ifndef QQMLPROPERTYCACHECREATOR_P_H
4#define QQMLPROPERTYCACHECREATOR_P_H
17#include <private/qqmlvaluetype_p.h>
18#include <private/qqmlengine_p.h>
19#include <private/qqmlmetaobject_p.h>
20#include <private/qqmlpropertyresolver_p.h>
21#include <private/qqmltypedata_p.h>
22#include <private/inlinecomponentutils_p.h>
23#include <private/qqmlsourcecoordinate_p.h>
25#include <QScopedValueRollback>
36 error.setDescription(description);
87template <
typename ObjectContainer>
92 using InlineComponent =
typename std::remove_reference<decltype (*(std::declval<CompiledObject>().inlineComponentsBegin()))>
::type;
147template <
typename ObjectContainer>
151 const ObjectContainer *objectContainer,
const QQmlImports *imports,
153 : enginePrivate(enginePrivate)
154 , objectContainer(objectContainer)
156 , propertyCaches(propertyCaches)
157 , pendingGroupPropertyBindings(pendingGroupPropertyBindings)
158 , typeClassName(typeClassName)
169 for (
auto it =
obj->inlineComponentsBegin();
it !=
obj->inlineComponentsEnd(); ++
it) {
175 std::vector<icutils::Node> nodes;
176 nodes.resize(
allICs.size());
177 std::iota(nodes.begin(), nodes.end(), 0);
179 adjacencyList.resize(nodes.size());
186template <
typename ObjectContainer>
197template <
typename ObjectContainer>
205 if (nodeIt != nodesSorted.rend()) {
206 const auto &ic = allICs[nodeIt->index()];
211 QByteArray icTypeName { objectContainer->stringAt(ic.nameIndex).toUtf8() };
215 QQmlError diag = buildMetaObjectRecursively(ic.objectIndex, m_context, VMEMetaObjectIsRequired::Always);
217 return {diag,
false, 0};
221 return {
QQmlError(),
true, int(ic.objectIndex) };
224 auto diag = buildMetaObjectRecursively(0, m_context, VMEMetaObjectIsRequired::Maybe);
225 return {diag,
false, 0};
228template <
typename ObjectContainer>
231 auto isAddressable = [](
const QUrl &
url) {
237 bool needVMEMetaObject = isVMERequired == VMEMetaObjectIsRequired::Always ||
obj->propertyCount() != 0 ||
obj->aliasCount() != 0
238 ||
obj->signalCount() != 0 ||
obj->functionCount() != 0 ||
obj->enumCount() != 0
240 || (objectIndex == 0 && isAddressable(objectContainer->url())))
241 && !objectContainer->resolvedType(
obj->inheritedTypeNameIndex)->isFullyDynamicType());
243 if (!needVMEMetaObject) {
244 auto binding =
obj->bindingsBegin();
245 auto end =
obj->bindingsEnd();
246 for ( ; binding !=
end; ++binding) {
256 auto *typeRef = objectContainer->resolvedType(
obj->inheritedTypeNameIndex);
260 ? createMetaObject(
context.referencingObjectIndex,
obj, baseTypeCache)
262 "Type cannot be used for 'on' assignment"));
268 needVMEMetaObject =
true;
284 if (needVMEMetaObject) {
289 propertyCaches->
set(objectIndex, baseTypeCache);
294 auto binding =
obj->bindingsBegin();
295 auto end =
obj->bindingsEnd();
296 for (; binding !=
end; ++binding) {
297 switch (binding->type()) {
309 objectIndex, &(*binding), stringAt(binding->propertyNameIndex), thisCache);
315 if (!thisCache || !
context.resolveInstantiatingProperty())
319 binding->value.objectIndex,
context, VMEMetaObjectIsRequired::Maybe);
328template <
typename ObjectContainer>
331 if (
context.instantiatingProperty) {
332 return context.instantiatingPropertyCache();
333 }
else if (
obj->inheritedTypeNameIndex != 0) {
334 auto *typeRef = objectContainer->resolvedType(
obj->inheritedTypeNameIndex);
337 if (typeRef->isFullyDynamicType()) {
338 if (
obj->propertyCount() > 0 ||
obj->aliasCount() > 0) {
339 *
error =
qQmlCompileError(
obj->location, QQmlPropertyCacheCreatorBase::tr(
"Fully dynamic types cannot declare new properties."));
342 if (
obj->signalCount() > 0) {
343 *
error =
qQmlCompileError(
obj->location, QQmlPropertyCacheCreatorBase::tr(
"Fully dynamic types cannot declare new signals."));
346 if (
obj->functionCount() > 0) {
347 *
error =
qQmlCompileError(
obj->location, QQmlPropertyCacheCreatorBase::tr(
"Fully Dynamic types cannot declare new functions."));
353 return propertyCache;
356 QQmlPropertyCacheCreatorBase::tr(
"Type '%1' cannot declare new members.")
357 .arg(stringAt(
obj->inheritedTypeNameIndex)));
360 if (binding->isAttachedProperty()) {
361 auto *typeRef = objectContainer->resolvedType(
362 binding->propertyNameIndex);
366 imports->
resolveType(stringAt(binding->propertyNameIndex),
367 &qmltype,
nullptr,
nullptr,
nullptr);
372 *
error =
qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr(
"Non-existent attached object"));
376 }
else if (binding->isGroupProperty()) {
377 const auto *
obj = objectContainer->objectAt(binding->value.objectIndex);
378 if (!stringAt(
obj->inheritedTypeNameIndex).isEmpty())
381 for (
int i = 0,
end = objectContainer->objectCount();
i !=
end; ++
i) {
382 const auto *
ext = objectContainer->objectAt(
i);
383 if (
ext->idNameIndex != binding->propertyNameIndex)
386 if (
ext->inheritedTypeNameIndex == 0)
390 pendingGroupPropertyBindings->
append(pendingContext);
398template <
typename ObjectContainer>
404 obj->propertyCount() +
obj->aliasCount(),
405 obj->functionCount() +
obj->propertyCount() +
obj->aliasCount() +
obj->signalCount(),
406 obj->signalCount() +
obj->propertyCount() +
obj->aliasCount(),
414 if (objectIndex == 0 ||
int(currentRoot) == objectIndex) {
415 newClassName = typeClassName;
419 newClassName.
append(
"_QML_");
423 cache->_dynamicClassName = newClassName;
425 using ListPropertyAssignBehavior =
typename ObjectContainer::ListPropertyAssignBehavior;
426 switch (objectContainer->listPropertyAssignBehavior()) {
427 case ListPropertyAssignBehavior::ReplaceIfNotDefault:
428 cache->_listPropertyAssignBehavior =
"ReplaceIfNotDefault";
430 case ListPropertyAssignBehavior::Replace:
431 cache->_listPropertyAssignBehavior =
"Replace";
433 case ListPropertyAssignBehavior::Append:
439 auto p =
obj->propertiesBegin();
440 auto pend =
obj->propertiesEnd();
441 for ( ;
p != pend; ++
p) {
442 bool notInRevision =
false;
444 if (
d &&
d->isFinal())
445 return qQmlCompileError(
p->location, QQmlPropertyCacheCreatorBase::tr(
"Cannot override FINAL property"));
448 auto a =
obj->aliasesBegin();
449 auto aend =
obj->aliasesEnd();
450 for ( ;
a != aend; ++
a) {
451 bool notInRevision =
false;
453 if (
d &&
d->isFinal())
454 return qQmlCompileError(
a->location, QQmlPropertyCacheCreatorBase::tr(
"Cannot override FINAL property"));
457 int effectivePropertyIndex =
cache->propertyIndexCacheStart;
458 int effectiveMethodIndex =
cache->methodIndexCacheStart;
466 while ((parentCache = parentCache->
parent().
data())) {
469 for (
int i = pSigOffset;
i < pSigCount; ++
i) {
474 if (currPSig == (*iter).second) {
484 p =
obj->propertiesBegin();
485 pend =
obj->propertiesEnd();
486 for ( ;
p != pend; ++
p) {
490 seenSignals.
insert(changedSigName);
492 cache->appendSignal(changedSigName,
flags, effectiveMethodIndex++);
495 a =
obj->aliasesBegin();
496 aend =
obj->aliasesEnd();
497 for ( ;
a != aend; ++
a) {
501 seenSignals.
insert(changedSigName);
503 cache->appendSignal(changedSigName,
flags, effectiveMethodIndex++);
506 auto e =
obj->enumsBegin();
507 auto eend =
obj->enumsEnd();
508 for ( ;
e != eend; ++
e) {
509 const int enumValueCount =
e->enumValueCount();
511 values.reserve(enumValueCount);
513 auto enumValue =
e->enumValuesBegin();
514 auto end =
e->enumValuesEnd();
515 for ( ; enumValue !=
end; ++enumValue)
522 auto s =
obj->signalsBegin();
523 auto send =
obj->signalsEnd();
524 for ( ;
s != send; ++
s) {
525 const int paramCount =
s->parameterCount();
528 names.reserve(paramCount);
534 auto param =
s->parametersBegin();
535 auto end =
s->parametersEnd();
537 names.append(stringAt(
param->nameIndex).toUtf8());
542 return qQmlCompileError(
s->location, QQmlPropertyCacheCreatorBase::tr(
"Invalid signal parameter type: %1").arg(customTypeName));
544 paramTypes[
i] =
type;
550 flags.setHasArguments(
true);
552 QString signalName = stringAt(
s->nameIndex);
553 if (seenSignals.
contains(signalName))
554 return qQmlCompileError(
s->location, QQmlPropertyCacheCreatorBase::tr(
"Duplicate signal name: invalid override of property change signal or superclass signal"));
555 seenSignals.
insert(signalName);
557 cache->appendSignal(signalName,
flags, effectiveMethodIndex++,
563 auto function = objectContainer->objectFunctionsBegin(
obj);
564 auto fend = objectContainer->objectFunctionsEnd(
obj);
570 return qQmlCompileError(
function->location, QQmlPropertyCacheCreatorBase::tr(
"Duplicate method name: invalid override of property change signal or superclass signal"));
576 auto formal =
function->formalsBegin();
578 for ( ; formal !=
end; ++formal) {
579 flags.setHasArguments(
true);
580 parameterNames << stringAt(formal->nameIndex).toUtf8();
583 type = QMetaType::fromType<QVariant>();
584 parameterTypes <<
type;
589 returnType = QMetaType::fromType<QVariant>();
591 cache->appendMethod(slotName,
flags, effectiveMethodIndex++, returnType, parameterNames, parameterTypes);
596 int effectiveSignalIndex =
cache->signalHandlerIndexCacheStart;
598 p =
obj->propertiesBegin();
599 pend =
obj->propertiesEnd();
600 for ( ;
p != pend; ++
p, ++propertyIdx) {
608 propertyFlags.
type = QQmlPropertyData::Flags::QListType;
610 propertyFlags.
type = QQmlPropertyData::Flags::VarPropertyType;
613 propertyType =
p->isList()
614 ? listTypeForPropertyType(
type)
615 : metaTypeForPropertyType(
type);
620 bool selfReference =
false;
622 stringAt(
p->commonTypeOrTypeNameIndex()), &qmltype,
nullptr,
nullptr,
624 return qQmlCompileError(
p->location, QQmlPropertyCacheCreatorBase::tr(
"Invalid property type"));
636 compositeType = objectContainer->qmlTypeForComponent(icName);
638 }
else if (selfReference) {
639 compositeType = objectContainer->qmlTypeForComponent();
645 auto compilationUnit = tdata->compilationUnit();
646 compositeType = compilationUnit->qmlTypeForComponent();
652 propertyType = compositeType.
typeId();
658 propertyType = qmltype.
typeId();
659 propertyTypeVersion = qmltype.
version();
663 propertyFlags.
type = QQmlPropertyData::Flags::QListType;
665 propertyFlags.
type = QQmlPropertyData::Flags::QObjectDerivedType;
667 propertyFlags.
type = QQmlPropertyData::Flags::ValueType;
674 QString propertyName = stringAt(
p->nameIndex);
675 if (!
obj->hasAliasAsDefaultProperty() && propertyIdx ==
obj->indexOfDefaultPropertyOrAlias)
676 cache->_defaultPropertyName = propertyName;
677 cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
678 propertyType, propertyTypeVersion, effectiveSignalIndex);
680 effectiveSignalIndex++;
687template <
typename ObjectContainer>
691 const quint32 typeId =
param.typeNameIndexOrCommonType();
692 if (
param.indexIsCommonType()) {
704 bool selfReference =
false;
720 const QQmlType qmlType = objectContainer->qmlTypeForComponent();
728 auto compilationUnit = tdata->compilationUnit();
730 return param.isList()
731 ? compilationUnit->qmlType.qListTypeId()
732 : compilationUnit->qmlType.typeId();
735template <
typename ObjectContainer>
754 const ObjectContainer *objectContainer;
757template <
typename ObjectContainer>
760 : propertyCaches(propertyCaches)
761 , objectContainer(objectContainer)
765template <
typename ObjectContainer>
772 bool writable =
false;
773 bool resettable =
false;
774 bool bindable =
false;
785 const CompiledObject *targetObject = objectContainer->objectAt(targetObjectIndex);
788 auto nextAlias = targetObject->aliasesBegin();
793 if (seenAliases.contains(targetAlias)) {
795 QQmlPropertyCacheCreatorBase::tr(
"Cyclic alias"));
798 seenAliases.append(targetAlias);
799 lastAlias = targetAlias;
802 return propertyDataForAlias(
803 component, *lastAlias,
type, version, propertyFlags, enginePriv);
808 const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
812 auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
818 QQmlPropertyCacheCreatorBase::tr(
"Invalid alias target"));
821 const auto referencedType = typeRef->type();
822 if (referencedType.isValid()) {
823 *
type = referencedType.typeId();
824 if (!
type->isValid() && referencedType.isInlineComponentType()) {
825 *
type = objectContainer->qmlTypeForComponent(referencedType.elementName()).typeId();
829 *
type = typeRef->compilationUnit()->qmlType.typeId();
832 *version = typeRef->version();
854 if (typeProperty ==
nullptr) {
856 QQmlPropertyCacheCreatorBase::tr(
"Invalid alias target"));
871 if (valueTypeIndex != -1) {
874 *
type = QMetaType::fromType<int>();
878 if (targetProperty->
isEnum()) {
879 *
type = QMetaType::fromType<int>();
898template <
typename ObjectContainer>
902 const CompiledObject &
object = *objectContainer->objectAt(objectIndex);
903 if (!
object.aliasCount())
909 int effectiveSignalIndex = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.
size();
910 int effectivePropertyIndex = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.
size();
913 auto alias =
object.aliasesBegin();
914 auto end =
object.aliasesEnd();
915 for ( ; alias !=
end; ++alias, ++aliasIndex) {
922 &propertyFlags, enginePriv);
928 if (
object.hasAliasAsDefaultProperty() && aliasIndex ==
object.indexOfDefaultPropertyOrAlias)
929 propertyCache->_defaultPropertyName = propertyName;
931 propertyCache->
appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
932 type, version, effectiveSignalIndex++);
938template <
typename ObjectContainer>
942 const int candidateIndex =
component.namedObjectsInComponentTable()[
i];
943 const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex);
944 if (candidate.objectId() ==
id)
945 return candidateIndex;
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
ConstIterator end() const
ConstIterator begin() const
typename QLinkedStringHash< QPair< int, QQmlPropertyData * > >::ConstIterator ConstIterator
qsizetype size() const noexcept
void append(parameter_type t)
QQmlTypeLoader typeLoader
The QQmlError class encapsulates a QML error.
void setDescription(const QString &)
Sets the error description.
bool isValid() const
Returns true if this error is valid, otherwise false.
The QQmlImports class encapsulates one QML document's import statements.
bool resolveType(const QHashedStringRef &type, QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDetected=nullptr) const
QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
QQmlError appendAliasesToPropertyCache(const CompiledObject &component, int objectIndex, QQmlEnginePrivate *enginePriv)
ObjectContainer::CompiledObject CompiledObject
QMetaType metaTypeForParameter(const QV4::CompiledData::ParameterType ¶m, QString *customTypeName=nullptr)
IncrementalResult buildMetaObjectsIncrementally()
typename ObjectContainer::CompiledObject CompiledObject
QString stringAt(int index) const
QQmlEnginePrivate *const enginePrivate
QQmlBindingInstantiationContext m_context
QQmlPendingGroupPropertyBindings * pendingGroupPropertyBindings
~QQmlPropertyCacheCreator()
QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache)
typename std::remove_reference< decltype(*(std::declval< CompiledObject >().inlineComponentsBegin()))>::type InlineComponent
const ObjectContainer *const objectContainer
std::vector< icutils::Node >::reverse_iterator nodeIt
QQmlError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired)
QQmlError verifyNoICCycle()
QQmlPropertyCacheCreator(QQmlPropertyCacheVector *propertyCaches, QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings, QQmlEnginePrivate *enginePrivate, const ObjectContainer *objectContainer, const QQmlImports *imports, const QByteArray &typeClassName)
const QQmlImports *const imports
std::vector< InlineComponent > allICs
QQmlPropertyCacheVector * propertyCaches
std::vector< icutils::Node > nodesSorted
QQmlPropertyCache::ConstPtr propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
bool needsVMEMetaObject(int index) const
void setNeedsVMEMetaObject(int index)
void resetAndResize(int size)
QQmlPropertyCache::ConstPtr at(int index) const
void set(int index, const QQmlPropertyCache::ConstPtr &replacement)
void setOwn(int index, const QQmlPropertyCache::Ptr &replacement)
QQmlPropertyCache::Ptr ownAt(int index) const
const QQmlPropertyData * signal(int index) const
const QQmlPropertyCache::ConstPtr & parent() const
void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex, QMetaType propType, QTypeRevision revision, int notifyIndex)
bool isResettable() const
bool isVarProperty() const
QMetaType propType() const
static Flags defaultSlotFlags()
static Flags defaultSignalFlags()
static QQmlPropertyIndex fromEncoded(qint32 encodedIndex)
int valueTypeIndex() const
QQmlRefPointer< QQmlTypeData > getType(const QUrl &unNormalizedUrl, Mode mode=PreferSynchronous)
Returns a QQmlTypeData for the specified url.
QTypeRevision version() const
const QMetaObject * attachedPropertiesType(QQmlEnginePrivate *engine) const
QMetaType qListTypeId() const
bool isInlineComponentType() const
QString elementName() const
bool contains(const T &value) const
iterator insert(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static constexpr QTypeRevision zero()
Produces a QTypeRevision with major and minor version {0}.
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
QQmlPropertyCache::ConstPtr typePropertyCache() const
void setTypePropertyCache(QQmlPropertyCache::ConstPtr cache)
const T * constData() const
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
std::vector< std::vector< Node * > > AdjacencyList
#define Q_DECLARE_TR_FUNCTIONS(context)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
GLenum GLsizei GLsizei GLint * values
[15]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLenum const GLint * param
static qreal component(const QPointF &point, unsigned int i)
QT_BEGIN_NAMESPACE QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
#define Q_AUTOTEST_EXPORT
QUrl url("example.com")
[constructor-url-reference]
int referencingObjectIndex
QQmlPropertyCache::ConstPtr referencingObjectPropertyCache
const QV4::CompiledData::Binding * instantiatingBinding
bool resolveInstantiatingProperty()
const QQmlPropertyData * instantiatingProperty
QQmlBindingInstantiationContext()
QQmlPropertyCache::ConstPtr instantiatingPropertyCache() const
QString instantiatingPropertyName
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const
static bool canCreateClassNameTypeByUrl(const QUrl &url)
static QByteArray createClassNameTypeByUrl(const QUrl &url)
static QMetaType listTypeForPropertyType(QV4::CompiledData::CommonType type)
static QAtomicInt Q_AUTOTEST_EXPORT classIndexCounter
static QByteArray createClassNameForInlineComponent(const QUrl &baseUrl, const QString &name)
static QMetaType metaTypeForPropertyType(QV4::CompiledData::CommonType type)
void copyPropertyTypeFlags(Flags from)
void setIsResettable(bool b)
void setIsWritable(bool b)
void setIsBindable(bool b)
const QQmlPropertyData * property(int index) const
Location referenceLocation
@ AliasPointsToPointerObject
qint32_le encodedMetaPropertyIndex
quint32 targetObjectId() const
bool hasFlag(Flag flag) const
bool isAliasToLocalAlias() const
quint32 nameIndex() const
quint32_le localAliasIndex