5#ifndef QQMLPROPERTYCACHECREATOR_P_H
6#define QQMLPROPERTYCACHECREATOR_P_H
19#include <private/qqmlvaluetype_p.h>
20#include <private/qqmlengine_p.h>
21#include <private/qqmlmetaobject_p.h>
22#include <private/qqmltypedata_p.h>
23#include <private/inlinecomponentutils_p.h>
24#include <private/qqmlsourcecoordinate_p.h>
25#include <private/qqmlsignalnames_p.h>
26#include <private/qexpected_p.h>
28#include <QtCore/qloggingcategory.h>
29#include <QtCore/qscopedvaluerollback.h>
31#if QT_CONFIG(regularexpression)
32#include <QtCore/qregularexpression.h>
42 const QString &description)
45 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(location.line()));
46 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(location.column()));
47 error.setDescription(description);
54 int referencingObjectIndex,
const QV4::CompiledData::Binding *instantiatingBinding,
55 const QString &instantiatingPropertyName,
56 const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache);
71 QQmlPropertyCacheVector *propertyCaches)
const;
83 case QV4::CompiledData::CommonType::Void:
return QMetaType();
84 case QV4::CompiledData::CommonType::Var:
return QMetaType::fromType<QVariant>();
85 case QV4::CompiledData::CommonType::Int:
return QMetaType::fromType<
int>();
86 case QV4::CompiledData::CommonType::Bool:
return QMetaType::fromType<
bool>();
87 case QV4::CompiledData::CommonType::Real:
return QMetaType::fromType<qreal>();
88 case QV4::CompiledData::CommonType::String:
return QMetaType::fromType<QString>();
89 case QV4::CompiledData::CommonType::Url:
return QMetaType::fromType<QUrl>();
90 case QV4::CompiledData::CommonType::Time:
return QMetaType::fromType<QTime>();
91 case QV4::CompiledData::CommonType::Date:
return QMetaType::fromType<QDate>();
92 case QV4::CompiledData::CommonType::DateTime:
return QMetaType::fromType<QDateTime>();
93#if QT_CONFIG(regularexpression)
94 case QV4::CompiledData::CommonType::RegExp:
return QMetaType::fromType<QRegularExpression>();
96 case QV4::CompiledData::CommonType::RegExp:
return QMetaType();
98 case QV4::CompiledData::CommonType::Rect:
return QMetaType::fromType<QRectF>();
99 case QV4::CompiledData::CommonType::Point:
return QMetaType::fromType<QPointF>();
100 case QV4::CompiledData::CommonType::Size:
return QMetaType::fromType<QSizeF>();
101 case QV4::CompiledData::CommonType::Invalid:
break;
109 case QV4::CompiledData::CommonType::Void:
return QMetaType();
110 case QV4::CompiledData::CommonType::Var:
return QMetaType::fromType<QList<QVariant>>();
111 case QV4::CompiledData::CommonType::Int:
return QMetaType::fromType<QList<
int>>();
112 case QV4::CompiledData::CommonType::Bool:
return QMetaType::fromType<QList<
bool>>();
113 case QV4::CompiledData::CommonType::Real:
return QMetaType::fromType<QList<qreal>>();
114 case QV4::CompiledData::CommonType::String:
return QMetaType::fromType<QList<QString>>();
115 case QV4::CompiledData::CommonType::Url:
return QMetaType::fromType<QList<QUrl>>();
116 case QV4::CompiledData::CommonType::Time:
return QMetaType::fromType<QList<QTime>>();
117 case QV4::CompiledData::CommonType::Date:
return QMetaType::fromType<QList<QDate>>();
118 case QV4::CompiledData::CommonType::DateTime:
return QMetaType::fromType<QList<QDateTime>>();
119#if QT_CONFIG(regularexpression)
120 case QV4::CompiledData::CommonType::RegExp:
return QMetaType::fromType<QList<QRegularExpression>>();
122 case QV4::CompiledData::CommonType::RegExp:
return QMetaType();
124 case QV4::CompiledData::CommonType::Rect:
return QMetaType::fromType<QList<QRectF>>();
125 case QV4::CompiledData::CommonType::Point:
return QMetaType::fromType<QList<QPointF>>();
126 case QV4::CompiledData::CommonType::Size:
return QMetaType::fromType<QList<QSizeF>>();
127 case QV4::CompiledData::CommonType::Invalid:
break;
133 if (!metaType.isValid())
134 return QV4::CompiledData::CommonType::Void;
136 switch (metaType.id()) {
137 case QMetaType::QVariant:
138 return QV4::CompiledData::CommonType::Var;
140 return QV4::CompiledData::CommonType::Int;
141 case QMetaType::Bool:
142 return QV4::CompiledData::CommonType::Bool;
143 case QMetaType::QReal:
144 return QV4::CompiledData::CommonType::Real;
145 case QMetaType::QString:
146 return QV4::CompiledData::CommonType::String;
147 case QMetaType::QUrl:
148 return QV4::CompiledData::CommonType::Url;
149 case QMetaType::QTime:
150 return QV4::CompiledData::CommonType::Time;
151 case QMetaType::QDate:
152 return QV4::CompiledData::CommonType::Date;
153 case QMetaType::QDateTime:
154 return QV4::CompiledData::CommonType::DateTime;
155#if QT_CONFIG(regularexpression)
156 case QMetaType::QRegularExpression:
157 return QV4::CompiledData::CommonType::RegExp;
159 case QMetaType::QRectF:
160 return QV4::CompiledData::CommonType::Rect;
161 case QMetaType::QPointF:
162 return QV4::CompiledData::CommonType::Point;
163 case QMetaType::QSizeF:
164 return QV4::CompiledData::CommonType::Size;
168 return QV4::CompiledData::CommonType::Invalid;
188 case OverrideSemantics::Status::MissingBase:
189 return tr(
"Nothing to override. Remove \"override\" keyword");
190 case OverrideSemantics::Status::OverridingFinal:
191 return tr(
"Cannot override FINAL property");
192 case OverrideSemantics::Status::OverridingNonVirtualError:
193 return tr(
"Cannot override non virtual property. Add \"virtual\" to the property of "
196 return tr(
"unknown");
201template <
typename ObjectContainer>
210 QQmlTypeLoader *typeLoader,
211 const ObjectContainer *objectContainer,
const QQmlImports *imports,
212 const QByteArray &typeClassName);
217
218
219
220
221
222
223
227
228
229
230
234
235
236
237
238
239
242 QByteArray dynamicClassName = QByteArray())
const;
245
246
247
248
249
250
251
252
253
256 int notifyIndex)
const;
268 QString *customTypeName =
nullptr)
const;
276 QTypeRevision revision = QTypeRevision::zero();
277 QV4::CompiledData::CommonType commonType = QV4::CompiledData::CommonType::Invalid;
280 [[nodiscard]] q23::expected<PropertyType, QQmlError>
281 tryResolvePropertyType(
const QV4::CompiledData::Property &propertyIR)
const;
284 [[nodiscard]]
static QQmlPropertyData::Flags
285 propertyDataFlags(
const QV4::CompiledData::Property &propertyIR,
286 const PropertyType &resolvedPropertyType);
304template <
typename ObjectContainer>
306 QQmlPropertyCacheVector *propertyCaches,
308 QQmlTypeLoader *typeLoader,
309 const ObjectContainer *objectContainer,
const QQmlImports *imports,
310 const QByteArray &typeClassName)
319 propertyCaches->resetAndResize(objectContainer->objectCount());
321 using namespace icutils;
325 for (
int i=0; i != objectContainer->objectCount(); ++i) {
327 for (
auto it = obj->inlineComponentsBegin(); it != obj->inlineComponentsEnd(); ++it) {
328 allICs.push_back(*it);
333 std::vector<icutils::Node> nodes;
334 nodes.resize(allICs.size());
335 std::iota(nodes.begin(), nodes.end(), 0);
336 AdjacencyList adjacencyList;
337 adjacencyList.resize(nodes.size());
338 fillAdjacencyListForInlineComponents(objectContainer, adjacencyList, nodes, allICs);
340 nodesSorted = topoSort(nodes, adjacencyList, hasCycle);
341 nodeIt = nodesSorted.rbegin();
344template <
typename ObjectContainer>
349 diag.setDescription(QLatin1String(
"Inline components form a cycle!"));
355template <
typename ObjectContainer>
363 if (nodeIt != nodesSorted.rend()) {
364 const auto &ic = allICs[nodeIt->index()];
365 QV4::ResolvedTypeReference *typeRef =
objectContainer->resolvedType(ic.nameIndex);
366 Q_ASSERT(propertyCaches->at(ic.objectIndex).isNull());
367 Q_ASSERT(typeRef->typePropertyCache().isNull());
369 QByteArray icTypeName {
objectContainer->stringAt(ic.nameIndex).toUtf8() };
370 QScopedValueRollback<QByteArray> nameChange {typeClassName, icTypeName};
371 QScopedValueRollback<
unsigned int> rootChange {
currentRoot, ic.objectIndex};
373 QQmlError diag = buildMetaObjectRecursively(ic.objectIndex, m_context, VMEMetaObjectIsRequired::Always);
374 if (diag.isValid()) {
375 return {diag,
false, 0};
377 typeRef->setTypePropertyCache(propertyCaches->at(ic.objectIndex));
378 Q_ASSERT(!typeRef->typePropertyCache().isNull());
379 return { QQmlError(),
true,
int(ic.objectIndex) };
382 auto diag = buildMetaObjectRecursively(0, m_context, VMEMetaObjectIsRequired::Maybe);
383 return {diag,
false, 0};
386template <
typename ObjectContainer>
389 const CompiledObject *obj,
const QQmlPropertyCache::ConstPtr &baseTypeCache,
390 QByteArray dynamicClassName)
const
392 QQmlPropertyCache::Ptr cache = baseTypeCache->copyAndReserve(
393 obj->propertyCount() + obj->aliasCount(),
394 obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
395 obj->signalCount() + obj->propertyCount() + obj->aliasCount(), obj->enumCount());
396 cache->_dynamicClassName =
std::move(dynamicClassName);
398 int effectiveMethodIndex = cache->methodIndexCacheStart;
404 enum class AllowOverride { No, Yes };
405 QHash<QString, AllowOverride> seenSignals{
406 { QStringLiteral(
"destroyed"), AllowOverride::No },
407 { QStringLiteral(
"parentChanged"), AllowOverride::No },
408 { QStringLiteral(
"objectNameChanged"), AllowOverride::No }
410 const QQmlPropertyCache *parentCache = cache.data();
411 while ((parentCache = parentCache->parent().data())) {
412 if (
int pSigCount = parentCache->signalCount()) {
413 int pSigOffset = parentCache->signalOffset();
414 for (
int i = pSigOffset; i < pSigCount; ++i) {
415 const QQmlPropertyData *currPSig = parentCache->signal(i);
417 for (QQmlPropertyCache::StringCache::ConstIterator iter =
418 parentCache->stringCache.begin();
419 iter != parentCache->stringCache.end(); ++iter) {
420 if (currPSig == (*iter).second) {
421 if (currPSig->isOverridableSignal()) {
422 const qsizetype oldSize = seenSignals.size();
423 AllowOverride &entry = seenSignals[iter.key()];
424 if (seenSignals.size() != oldSize)
425 entry = AllowOverride::Yes;
427 seenSignals[iter.key()] = AllowOverride::No;
438 auto p = obj->propertiesBegin();
439 auto pend = obj->propertiesEnd();
440 for (; p != pend; ++p) {
441 auto flags = QQmlPropertyData::defaultSignalFlags();
443 const QString changedSigName =
444 QQmlSignalNames::propertyNameToChangedSignalName(stringAt(p->nameIndex()));
445 seenSignals[changedSigName] = AllowOverride::No;
447 cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
450 auto a = obj->aliasesBegin();
451 auto aend = obj->aliasesEnd();
452 for (; a != aend; ++a) {
453 auto flags = QQmlPropertyData::defaultSignalFlags();
455 const QString changedSigName =
456 QQmlSignalNames::propertyNameToChangedSignalName(stringAt(a->nameIndex()));
457 seenSignals[changedSigName] = AllowOverride::No;
459 cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
462 auto e = obj->enumsBegin();
463 auto eend = obj->enumsEnd();
464 for (; e != eend; ++e) {
465 const int enumValueCount = e->enumValueCount();
466 QList<QQmlEnumValue> values;
467 values.reserve(enumValueCount);
469 auto enumValue = e->enumValuesBegin();
470 auto end = e->enumValuesEnd();
471 for (; enumValue != end; ++enumValue)
472 values.append(QQmlEnumValue(stringAt(enumValue->nameIndex), enumValue->value));
474 cache->appendEnum(stringAt(e->nameIndex), values);
478 auto s = obj->signalsBegin();
479 auto send = obj->signalsEnd();
480 for (; s != send; ++s) {
481 const int paramCount = s->parameterCount();
483 QList<QByteArray> names;
484 names.reserve(paramCount);
485 QVarLengthArray<QMetaType, 10> paramTypes(paramCount);
490 auto param = s->parametersBegin();
491 auto end = s->parametersEnd();
492 for (; param != end; ++param, ++i) {
493 names.append(stringAt(param->nameIndex).toUtf8());
495 QString customTypeName;
496 QMetaType type = metaTypeForParameter(param->type, &customTypeName);
498 return q23::make_unexpected(qQmlCompileError(
500 QQmlPropertyCacheCreatorBase::tr(
"Invalid signal parameter type: %1")
501 .arg(customTypeName)));
503 paramTypes[i] = type;
507 auto flags = QQmlPropertyData::defaultSignalFlags();
509 flags.setHasArguments(
true);
511 QString signalName = stringAt(s->nameIndex);
512 const auto it = seenSignals.find(signalName);
513 if (it == seenSignals.end()) {
514 seenSignals[signalName] = AllowOverride::No;
517 QQmlError message = qQmlCompileError(
519 QQmlPropertyCacheCreatorBase::tr(
520 "Duplicate signal name: "
521 "invalid override of property change signal or superclass signal"));
523 case AllowOverride::No:
524 return q23::make_unexpected(std::move(message));
525 case AllowOverride::Yes:
527 qCWarning(invalidOverride).noquote() << message.toString();
528 *it = AllowOverride::No;
532 cache->appendSignal(signalName, flags, effectiveMethodIndex++,
533 paramCount ? paramTypes.constData() :
nullptr, names);
539 for (; function != fend; ++function) {
540 auto flags = QQmlPropertyData::defaultSlotFlags();
542 const QString slotName = stringAt(function->nameIndex);
543 const auto it = seenSignals.constFind(slotName);
544 if (it != seenSignals.constEnd()) {
546 QQmlError message = qQmlCompileError(
548 QQmlPropertyCacheCreatorBase::tr(
549 "Duplicate method name: "
550 "invalid override of property change signal or superclass signal"));
552 case AllowOverride::No:
553 return q23::make_unexpected(std::move(message));
554 case AllowOverride::Yes:
556 qCWarning(invalidOverride).noquote() << message.toString();
563 QList<QByteArray> parameterNames;
564 QList<QMetaType> parameterTypes;
565 auto formal = function->formalsBegin();
566 auto end = function->formalsEnd();
567 for (; formal != end; ++formal) {
568 flags.setHasArguments(
true);
569 parameterNames << stringAt(formal->nameIndex).toUtf8();
570 QMetaType type = metaTypeForParameter(formal->type);
572 type = QMetaType::fromType<QVariant>();
573 parameterTypes << type;
576 QMetaType returnType = metaTypeForParameter(function->returnType);
577 if (!returnType.isValid())
578 returnType = QMetaType::fromType<QVariant>();
580 cache->appendMethod(slotName, flags, effectiveMethodIndex++, returnType, parameterNames,
585 int propertyIndex = cache->propertyIndexCacheStart;
586 int notifyIndex = cache->signalHandlerIndexCacheStart;
587 int objPropertyIdx = 0;
588 p = obj->propertiesBegin();
589 pend = obj->propertiesEnd();
590 for (; p != pend; ++p, ++objPropertyIdx, propertyIndex++, notifyIndex++) {
591 auto propertyDataOrError = tryCreateQQmlPropertyData(*p, propertyIndex, notifyIndex);
592 if (!propertyDataOrError.has_value()) {
593 return q23::make_unexpected(propertyDataOrError.error());
596 QString propertyName = stringAt(p->nameIndex());
597 if (!obj->hasAliasAsDefaultProperty()
598 && objPropertyIdx == obj->indexOfDefaultPropertyOrAlias)
599 cache->_defaultPropertyName = propertyName;
601 const auto &appendResult =
602 cache->appendPropertyAttr(propertyName,
std::move(propertyDataOrError).value());
604 return q23::make_unexpected(
605 qQmlCompileError(p->location, explain(appendResult.error())));
611template <
typename ObjectContainer>
614 const QV4::CompiledData::Property &propertyIR,
int coreIndex,
int notifyIndex)
const
616 const auto propertyTypeOrError = tryResolvePropertyType(propertyIR);
617 if (!propertyTypeOrError.has_value()) {
618 return q23::make_unexpected(propertyTypeOrError.error());
620 const auto propertyType = propertyTypeOrError.value();
622 QQmlPropertyData propertyData;
623 propertyData.setPropType(propertyType.metaType);
624 propertyData.setCoreIndex(coreIndex);
625 propertyData.setNotifyIndex(notifyIndex);
626 propertyData.setFlags(QQmlPropertyCacheCreator::propertyDataFlags(propertyIR, propertyType));
627 propertyData.setTypeVersion(propertyType.revision);
631template <
typename ObjectContainer>
634 auto isAddressable = [](
const QUrl &url) {
635 const QString fileName = url.fileName();
636 return !fileName.isEmpty() && fileName.front().isUpper();
641 || obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0
642 || obj->functionCount() != 0 || obj->enumCount() != 0
643 || obj->inlineComponentCount() != 0
644 || ((obj->hasFlag(QV4::CompiledData::Object::IsComponent)
646 && !
objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType());
648 if (!needVMEMetaObject) {
649 auto binding = obj->bindingsBegin();
650 auto end = obj->bindingsEnd();
651 for ( ; binding != end; ++binding) {
652 if (binding->type() == QV4::CompiledData::Binding::Type_Object
653 && (binding->flags() & QV4::CompiledData::Binding::IsOnAssignment)) {
658 if (context.instantiatingProperty && QQmlMetaType::isValueType(context.instantiatingProperty->propType())) {
659 if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
661 auto *typeRef =
objectContainer->resolvedType(obj->inheritedTypeNameIndex);
663 QQmlPropertyCache::ConstPtr baseTypeCache = typeRef->createPropertyCache();
664 QQmlError error = baseTypeCache
665 ? createMetaObject(context.referencingObjectIndex, obj, baseTypeCache)
666 : qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr(
667 "Type cannot be used for 'on' assignment"));
673 needVMEMetaObject =
true;
680 QQmlPropertyCache::ConstPtr baseTypeCache;
683 baseTypeCache = propertyCacheForObject(obj, context, &error);
689 if (needVMEMetaObject) {
690 QQmlError error = createMetaObject(objectIndex, obj, baseTypeCache);
694 propertyCaches->set(objectIndex, baseTypeCache);
698 QQmlPropertyCache::ConstPtr thisCache = propertyCaches->at(objectIndex);
699 auto binding = obj->bindingsBegin();
700 auto end = obj->bindingsEnd();
701 for (; binding != end; ++binding) {
702 switch (binding->type()) {
703 case QV4::CompiledData::Binding::Type_Object:
704 case QV4::CompiledData::Binding::Type_GroupProperty:
705 case QV4::CompiledData::Binding::Type_AttachedProperty:
714 objectIndex, &(*binding), stringAt(binding->propertyNameIndex), thisCache);
723 QQmlError error = buildMetaObjectRecursively(
724 binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe);
733template <
typename ObjectContainer>
736 if (context.instantiatingProperty) {
737 return context.instantiatingPropertyCache();
738 }
else if (obj->inheritedTypeNameIndex != 0) {
739 auto *typeRef =
objectContainer->resolvedType(obj->inheritedTypeNameIndex);
742 if (typeRef->isFullyDynamicType()) {
743 if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
744 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr(
"Fully dynamic types cannot declare new properties."));
747 if (obj->signalCount() > 0) {
748 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr(
"Fully dynamic types cannot declare new signals."));
751 if (obj->functionCount() > 0) {
752 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr(
"Fully Dynamic types cannot declare new functions."));
757 if (QQmlPropertyCache::ConstPtr propertyCache = typeRef->createPropertyCache())
758 return propertyCache;
759 *error = qQmlCompileError(
761 QQmlPropertyCacheCreatorBase::tr(
"Type '%1' cannot declare new members.")
762 .arg(stringAt(obj->inheritedTypeNameIndex)));
764 }
else if (
const QV4::CompiledData::Binding *binding = context.instantiatingBinding) {
765 if (binding->isAttachedProperty()) {
767 binding->propertyNameIndex);
769 QQmlType qmltype = typeRef->type();
770 if (!qmltype.isValid()) {
771 imports->resolveType(
772 typeLoader, stringAt(binding->propertyNameIndex),
773 &qmltype,
nullptr,
nullptr);
776 const QMetaObject *attachedMo = qmltype.attachedPropertiesType(typeLoader);
778 *error = qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr(
"Non-existent attached object"));
781 return QQmlMetaType::propertyCache(attachedMo);
787template <
typename ObjectContainer>
790 const QQmlPropertyCache::ConstPtr &baseTypeCache)
792 const auto dynamicClassName = [
this](
int objectIndex,
const auto &baseTypeCache) -> QByteArray {
793 const auto isComponentRoot = objectIndex == 0
794 || objectIndex ==
int(currentRoot) ;
795 if (isComponentRoot && !typeClassName.isEmpty()) {
796 return typeClassName;
798 return QByteArray(QQmlMetaObject(baseTypeCache).className())
800 .append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
803 const auto cacheOrError =
804 tryDeriveCacheFrom(obj, baseTypeCache, dynamicClassName(objectIndex, baseTypeCache));
805 if (!cacheOrError.has_value()) {
806 return cacheOrError.error();
808 auto &cache = cacheOrError.value();
810 using ListPropertyAssignBehavior =
typename ObjectContainer::ListPropertyAssignBehavior;
812 case ListPropertyAssignBehavior::ReplaceIfNotDefault:
813 cache->_listPropertyAssignBehavior =
"ReplaceIfNotDefault";
815 case ListPropertyAssignBehavior::Replace:
816 cache->_listPropertyAssignBehavior =
"Replace";
818 case ListPropertyAssignBehavior::Append:
822 propertyCaches->setOwn(objectIndex, cache);
823 propertyCaches->setNeedsVMEMetaObject(objectIndex);
827template <
typename ObjectContainer>
829 const QV4::CompiledData::ParameterType ¶m, QString *customTypeName)
const
831 const quint32 typeId = param.typeNameIndexOrCommonType();
832 if (param.indexIsCommonType()) {
835 return listTypeForPropertyType(QV4::CompiledData::CommonType(typeId));
836 return metaTypeForPropertyType(QV4::CompiledData::CommonType(typeId));
840 const QString typeName = stringAt(param.typeNameIndexOrCommonType());
842 *customTypeName = typeName;
844 bool selfReference =
false;
845 if (!imports->resolveType(
846 typeLoader, typeName, &qmltype,
nullptr,
nullptr,
nullptr,
847 QQmlType::AnyRegistrationType, &selfReference))
850 if (!qmltype.isComposite()) {
851 const QMetaType typeId = param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
852 if (!typeId.isValid() && qmltype.isInlineComponentType()) {
853 const QQmlType qmlType =
objectContainer->qmlTypeForComponent(qmltype.elementName());
854 return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
862 return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
865 return param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
868template <
typename ObjectContainer>
870 const QV4::CompiledData::Property &propertyIR)
const
871 -> q23::expected<PropertyType, QQmlError>
873 using namespace Qt::StringLiterals;
874 PropertyType propertyType;
875 propertyType.commonType = propertyIR.commonType();
877 if (propertyType.commonType != QV4::CompiledData::CommonType::Invalid) {
879 propertyType.metaType = propertyIR.isList()
880 ? listTypeForPropertyType(propertyType.commonType)
881 : metaTypeForPropertyType(propertyType.commonType);
888 Q_ASSERT(!propertyIR.isCommonType());
890 bool selfReference =
false;
891 QList<QQmlError> errors;
892 const QString typeName = stringAt(propertyIR.commonTypeOrTypeNameIndex());
893 if (!imports->resolveType(typeLoader, typeName, &qmltype,
nullptr,
nullptr, &errors,
894 QQmlType::AnyRegistrationType, &selfReference)) {
895 Q_ASSERT(!errors.isEmpty());
897 if (typeName ==
"list"_L1 && errors[0].description() ==
"is not a type"_L1) {
898 errors[0].setDescription(errors[0].description().append(
899 ". It requires an element type argument (eg. list<int>)"_L1));
902 return q23::make_unexpected(
903 qQmlCompileError(propertyIR.location, typeName + u' ' + errors[0].description()));
906 Q_ASSERT(qmltype.isValid());
908 propertyType.metaType = propertyIR.isList() ? qmltype.qListTypeId() : qmltype.typeId();
910 if (!qmltype.isComposite() && !qmltype.isInlineComponentType())
911 propertyType.revision = qmltype.version();
916template <
typename ObjectContainer>
918 const QV4::CompiledData::Property &propertyIR,
const PropertyType &resolvedPropertyType)
920 QQmlPropertyData::Flags flags;
923 if (propertyIR.isList()) {
924 flags.setType(QQmlPropertyData::Flags::QListType);
925 }
else if (resolvedPropertyType.commonType == QV4::CompiledData::CommonType::Var) {
926 flags.setType(QQmlPropertyData::Flags::VarPropertyType);
927 }
else if (resolvedPropertyType.metaType.flags().testFlag(QMetaType::PointerToQObject)) {
928 flags.setType(QQmlPropertyData::Flags::QObjectDerivedType);
932 if (!propertyIR.isReadOnly()
933 && !resolvedPropertyType.metaType.flags().testFlag(QMetaType::IsQmlList))
934 flags.setIsWritable(
true);
935 if (propertyIR.isFinal())
936 flags.setIsFinal(
true);
937 if (propertyIR.isVirtual())
938 flags.setIsVirtual(
true);
939 if (propertyIR.isOverride())
940 flags.setDoesOverride(
true);
945template <
typename ObjectContainer,
typename CompiledObject>
946int objectForId(
const ObjectContainer *objectContainer,
const CompiledObject &component,
int id)
948 for (quint32 i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
949 const int candidateIndex = component.namedObjectsInComponentTable()[i];
950 const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex);
951 if (candidate.objectId() == id)
952 return candidateIndex;
957template <
typename ObjectContainer>
964 QQmlPropertyCacheVector *propertyCaches,
const ObjectContainer *objectContainer);
966 const CompiledObject &component,
const QV4::CompiledData::Alias &alias,
int objectIndex,
967 int aliasIndex,
int encodedMetaPropertyIndex,
int resolvedTargetObjectId);
970 QQmlError propertyDataForAlias(
971 const CompiledObject &component,
const QV4::CompiledData::Alias &alias, QMetaType *type,
972 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
973 int targetPropertyIndex,
int resolvedTargetObjectId);
975 QQmlPropertyCacheVector *propertyCaches;
976 const ObjectContainer *objectContainer;
979template <
typename ObjectContainer>
981 QQmlPropertyCacheVector *propertyCaches,
const ObjectContainer *objectContainer)
983 , objectContainer(objectContainer)
987template <
typename ObjectContainer>
989 const CompiledObject &component,
const QV4::CompiledData::Alias &alias, QMetaType *type,
990 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
991 int targetPropertyIndex,
int resolvedTargetObjectId)
994 bool writable =
false;
995 bool resettable =
false;
996 bool notifiesViaBindable =
false;
998 propertyFlags->setIsAlias(
true);
1000 const int targetObjectIndex = objectForId(objectContainer, component, resolvedTargetObjectId);
1001 Q_ASSERT(targetObjectIndex >= 0);
1002 const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
1004 if (targetPropertyIndex == -1) {
1005 Q_ASSERT(objectContainer->stringAt(alias.propertyNameIndex()).isEmpty());
1006 auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
1011 return qQmlCompileError(targetObject.location,
1012 QQmlPropertyCacheCreatorBase::tr(
"Invalid alias target"));
1015 const auto referencedType = typeRef->type();
1016 Q_ASSERT(referencedType.isValid());
1017 *type = referencedType.typeId();
1018 if (!type->isValid() && referencedType.isInlineComponentType()) {
1019 *type = objectContainer->qmlTypeForComponent(referencedType.elementName()).typeId();
1020 Q_ASSERT(type->isValid());
1023 *version = typeRef->version();
1025 propertyFlags->setType(QQmlPropertyData::Flags::QObjectDerivedType);
1027 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
1029 = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).valueTypeIndex();
1031 QQmlPropertyCache::ConstPtr targetCache = propertyCaches->at(targetObjectIndex);
1032 Q_ASSERT(targetCache);
1034 const QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
1035 Q_ASSERT(targetProperty);
1037 const QMetaType targetPropType = targetProperty->propType();
1039 const auto populateWithPropertyData = [&](
const QQmlPropertyData *property) {
1040 *type = property->propType();
1041 writable = property->isWritable();
1042 resettable = property->isResettable();
1043 notifiesViaBindable = property->notifiesViaBindable();
1045 if (property->isVarProperty())
1046 propertyFlags->setType(QQmlPropertyData::Flags::QVariantType);
1048 propertyFlags->copyPropertyTypeFlags(property->flags());
1052 if (!QQmlMetaType::isValueType(targetPropType) && valueTypeIndex != -1) {
1055 QQmlPropertyCache::ConstPtr typeCache
1056 = QQmlMetaType::propertyCacheForType(targetPropType);
1060 if (
const QV4::ResolvedTypeReference *typeRef
1061 = objectContainer->resolvedType(targetPropType)) {
1062 typeCache = typeRef->typePropertyCache();
1066 const QQmlPropertyData *typeProperty = typeCache
1067 ? typeCache->property(valueTypeIndex)
1069 if (typeProperty ==
nullptr) {
1070 return qQmlCompileError(
1071 alias.referenceLocation(),
1072 QQmlPropertyCacheCreatorBase::tr(
"Invalid alias target"));
1074 populateWithPropertyData(typeProperty);
1077 populateWithPropertyData(targetProperty);
1079 if (valueTypeIndex != -1) {
1080 const QMetaObject *valueTypeMetaObject
1081 = QQmlMetaType::metaObjectForValueType(*type);
1082 const QMetaProperty valueTypeMetaProperty
1083 = valueTypeMetaObject->property(valueTypeIndex);
1084 *type = valueTypeMetaProperty.metaType();
1088 resettable = writable && valueTypeMetaProperty.isResettable();
1089 writable = writable && valueTypeMetaProperty.isWritable();
1092 propertyFlags->setIsDeepAlias(
true);
1097 propertyFlags->setIsWritable(writable && !alias.isReadOnly());
1098 propertyFlags->setIsResettable(resettable);
1099 propertyFlags->setIsBindable(notifiesViaBindable);
1103template <
typename ObjectContainer>
1105 const CompiledObject &component,
const QV4::CompiledData::Alias &alias,
int objectIndex,
1106 int aliasIndex,
int encodedMetaPropertyIndex,
int resolvedTargetObjectId)
1108 const CompiledObject &object = *objectContainer->objectAt(objectIndex);
1110 Q_ASSERT(object.aliasCount() > aliasIndex);
1112 QTypeRevision version = QTypeRevision::zero();
1113 QQmlPropertyData::Flags propertyFlags;
1114 QQmlError error = propertyDataForAlias(
1115 component, alias, &type, &version, &propertyFlags, encodedMetaPropertyIndex,
1116 resolvedTargetObjectId);
1117 if (error.isValid())
1120 const QString propertyName = objectContainer->stringAt(alias.nameIndex());
1122 const QQmlPropertyCache::Ptr propertyCache = propertyCaches->ownAt(objectIndex);
1123 Q_ASSERT(propertyCache);
1125 const int effectiveSignalIndex
1126 = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.size();
1127 const int effectivePropertyIndex
1128 = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.size();
1130 if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias)
1131 propertyCache->_defaultPropertyName = propertyName;
1133 const auto &appendResult =
1134 propertyCache->appendAlias(propertyName, propertyFlags, effectivePropertyIndex, type,
1135 version, effectiveSignalIndex, encodedMetaPropertyIndex,
1136 resolvedTargetObjectId);
1137 if (!appendResult) {
1138 return qQmlCompileError(
1139 alias.location(), QQmlPropertyCacheCreatorBase::explain(appendResult.error()));
QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
QQmlError appendAliasToPropertyCache(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex, int aliasIndex, int encodedMetaPropertyIndex, int resolvedTargetObjectId)
ObjectContainer::CompiledObject CompiledObject
IncrementalResult buildMetaObjectsIncrementally()
typename ObjectContainer::CompiledObject CompiledObject
QString stringAt(int index) const
QQmlPropertyCacheCreator(QQmlPropertyCacheVector *propertyCaches, QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings, QQmlTypeLoader *typeLoader, const ObjectContainer *objectContainer, const QQmlImports *imports, const QByteArray &typeClassName)
QQmlBindingInstantiationContext m_context
QQmlPendingGroupPropertyBindings * pendingGroupPropertyBindings
q23::expected< QQmlPropertyCache::Ptr, QQmlError > tryDeriveCacheFrom(const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache, QByteArray dynamicClassName=QByteArray()) const
~QQmlPropertyCacheCreator()
QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache)
QMetaType metaTypeForParameter(const QV4::CompiledData::ParameterType ¶m, QString *customTypeName=nullptr) const
typename std::remove_reference< decltype(*(std::declval< CompiledObject >().inlineComponentsBegin()))>::type InlineComponent
QQmlTypeLoader *const typeLoader
const ObjectContainer *const objectContainer
std::vector< icutils::Node >::reverse_iterator nodeIt
QQmlError buildMetaObjectRecursively(int objectIndex, const QQmlBindingInstantiationContext &context, VMEMetaObjectIsRequired isVMERequired)
q23::expected< QQmlPropertyData, QQmlError > tryCreateQQmlPropertyData(const QV4::CompiledData::Property &propertyIR, int coreIndex, int notifyIndex) const
QQmlError verifyNoICCycle()
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
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQIORing)
auto processUrlForClassName(const QUrl &url, BaseNameHandler &&baseNameHandler, FailHandler &&failHandler)
QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
int objectForId(const ObjectContainer *objectContainer, const CompiledObject &component, int id)
QQmlBindingInstantiationContext(int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding, const QString &instantiatingPropertyName, const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache)
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 QString explain(OverrideSemantics::Status reason)
static bool canCreateClassNameTypeByUrl(const QUrl &url)
static QV4::CompiledData::CommonType propertyTypeForMetaType(QMetaType metaType)
static QByteArray createClassNameForInlineComponent(const QUrl &url)
static QMetaType listTypeForPropertyType(QV4::CompiledData::CommonType type)
static QByteArray createClassNameTypeByUrl(const QUrl &url)
static QMetaType metaTypeForPropertyType(QV4::CompiledData::CommonType type)