Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpropertycachecreator_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QQMLPROPERTYCACHECREATOR_P_H
4#define QQMLPROPERTYCACHECREATOR_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <private/qqmlvaluetype_p.h>
18#include <private/qqmlengine_p.h>
19#include <private/qqmlmetaobject_p.h>
20#include <private/qqmltypedata_p.h>
21#include <private/inlinecomponentutils_p.h>
22#include <private/qqmlsourcecoordinate_p.h>
23#include <private/qqmlsignalnames_p.h>
24#include <private/qexpected_p.h>
25
26#include <QtCore/qloggingcategory.h>
27#include <QtCore/qscopedvaluerollback.h>
28
29#if QT_CONFIG(regularexpression)
30#include <QtCore/qregularexpression.h>
31#endif
32
33#include <vector>
34
36
38
39inline QQmlError qQmlCompileError(const QV4::CompiledData::Location &location,
40 const QString &description)
41{
42 QQmlError error;
43 error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
44 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
45 error.setDescription(description);
46 return error;
47}
48
52 int referencingObjectIndex, const QV4::CompiledData::Binding *instantiatingBinding,
53 const QString &instantiatingPropertyName,
54 const QQmlPropertyCache::ConstPtr &referencingObjectPropertyCache);
55
58
64};
65
67{
69 QQmlPropertyCacheVector *propertyCaches) const;
70};
71
73{
75public:
77
78 static QMetaType metaTypeForPropertyType(QV4::CompiledData::CommonType type)
79 {
80 switch (type) {
81 case QV4::CompiledData::CommonType::Void: return QMetaType();
82 case QV4::CompiledData::CommonType::Var: return QMetaType::fromType<QVariant>();
83 case QV4::CompiledData::CommonType::Int: return QMetaType::fromType<int>();
84 case QV4::CompiledData::CommonType::Bool: return QMetaType::fromType<bool>();
85 case QV4::CompiledData::CommonType::Real: return QMetaType::fromType<qreal>();
86 case QV4::CompiledData::CommonType::String: return QMetaType::fromType<QString>();
87 case QV4::CompiledData::CommonType::Url: return QMetaType::fromType<QUrl>();
88 case QV4::CompiledData::CommonType::Time: return QMetaType::fromType<QTime>();
89 case QV4::CompiledData::CommonType::Date: return QMetaType::fromType<QDate>();
90 case QV4::CompiledData::CommonType::DateTime: return QMetaType::fromType<QDateTime>();
91#if QT_CONFIG(regularexpression)
92 case QV4::CompiledData::CommonType::RegExp: return QMetaType::fromType<QRegularExpression>();
93#else
94 case QV4::CompiledData::CommonType::RegExp: return QMetaType();
95#endif
96 case QV4::CompiledData::CommonType::Rect: return QMetaType::fromType<QRectF>();
97 case QV4::CompiledData::CommonType::Point: return QMetaType::fromType<QPointF>();
98 case QV4::CompiledData::CommonType::Size: return QMetaType::fromType<QSizeF>();
99 case QV4::CompiledData::CommonType::Invalid: break;
100 };
101 return QMetaType {};
102 }
103
104 static QMetaType listTypeForPropertyType(QV4::CompiledData::CommonType type)
105 {
106 switch (type) {
107 case QV4::CompiledData::CommonType::Void: return QMetaType();
108 case QV4::CompiledData::CommonType::Var: return QMetaType::fromType<QList<QVariant>>();
109 case QV4::CompiledData::CommonType::Int: return QMetaType::fromType<QList<int>>();
110 case QV4::CompiledData::CommonType::Bool: return QMetaType::fromType<QList<bool>>();
111 case QV4::CompiledData::CommonType::Real: return QMetaType::fromType<QList<qreal>>();
112 case QV4::CompiledData::CommonType::String: return QMetaType::fromType<QList<QString>>();
113 case QV4::CompiledData::CommonType::Url: return QMetaType::fromType<QList<QUrl>>();
114 case QV4::CompiledData::CommonType::Time: return QMetaType::fromType<QList<QTime>>();
115 case QV4::CompiledData::CommonType::Date: return QMetaType::fromType<QList<QDate>>();
116 case QV4::CompiledData::CommonType::DateTime: return QMetaType::fromType<QList<QDateTime>>();
117#if QT_CONFIG(regularexpression)
118 case QV4::CompiledData::CommonType::RegExp: return QMetaType::fromType<QList<QRegularExpression>>();
119#else
120 case QV4::CompiledData::CommonType::RegExp: return QMetaType();
121#endif
122 case QV4::CompiledData::CommonType::Rect: return QMetaType::fromType<QList<QRectF>>();
123 case QV4::CompiledData::CommonType::Point: return QMetaType::fromType<QList<QPointF>>();
124 case QV4::CompiledData::CommonType::Size: return QMetaType::fromType<QList<QSizeF>>();
125 case QV4::CompiledData::CommonType::Invalid: break;
126 };
127 return QMetaType {};
128 }
129
130 static QV4::CompiledData::CommonType propertyTypeForMetaType(QMetaType metaType) {
131 if (!metaType.isValid())
132 return QV4::CompiledData::CommonType::Void;
133
134 switch (metaType.id()) {
135 case QMetaType::QVariant:
136 return QV4::CompiledData::CommonType::Var;
137 case QMetaType::Int:
138 return QV4::CompiledData::CommonType::Int;
139 case QMetaType::Bool:
140 return QV4::CompiledData::CommonType::Bool;
141 case QMetaType::QReal:
142 return QV4::CompiledData::CommonType::Real;
143 case QMetaType::QString:
144 return QV4::CompiledData::CommonType::String;
145 case QMetaType::QUrl:
146 return QV4::CompiledData::CommonType::Url;
147 case QMetaType::QTime:
148 return QV4::CompiledData::CommonType::Time;
149 case QMetaType::QDate:
150 return QV4::CompiledData::CommonType::Date;
151 case QMetaType::QDateTime:
152 return QV4::CompiledData::CommonType::DateTime;
153#if QT_CONFIG(regularexpression)
154 case QMetaType::QRegularExpression:
155 return QV4::CompiledData::CommonType::RegExp;
156#endif
157 case QMetaType::QRectF:
158 return QV4::CompiledData::CommonType::Rect;
159 case QMetaType::QPointF:
160 return QV4::CompiledData::CommonType::Point;
161 case QMetaType::QSizeF:
162 return QV4::CompiledData::CommonType::Size;
163 default:
164 break;
165 }
166 return QV4::CompiledData::CommonType::Invalid;
167 }
168
169 static bool canCreateClassNameTypeByUrl(const QUrl &url);
170 static QByteArray createClassNameTypeByUrl(const QUrl &url);
171 static QByteArray createClassNameForInlineComponent(const QUrl &url);
172
174 // valid if and only if an error occurred
176 // true if there was no error and there are still components left to process
177 bool canResume = false;
178 // the object index of the last processed (inline) component root.
180 };
181
182 // TODO just reuse message from the QQmlPropertyCacheCreator::maybeLog
183 static QString explain(OverrideSemantics::Status reason)
184 {
185 switch (reason) {
186 case OverrideSemantics::Status::MissingBase:
187 return tr("Nothing to override. Remove \"override\" keyword");
188 case OverrideSemantics::Status::OverridingFinal:
189 return tr("Cannot override FINAL property");
190 case OverrideSemantics::Status::OverridingNonVirtualError:
191 return tr("Cannot override non virtual property. Add \"virtual\" to the property of "
192 "the base object");
193 default:
194 return tr("unknown");
195 }
196 }
197};
198
199template <typename ObjectContainer>
201{
202public:
203 using CompiledObject = typename ObjectContainer::CompiledObject;
204 using InlineComponent = typename std::remove_reference<decltype (*(std::declval<CompiledObject>().inlineComponentsBegin()))>::type;
205
206 QQmlPropertyCacheCreator(QQmlPropertyCacheVector *propertyCaches,
207 QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings,
208 QQmlTypeLoader *typeLoader,
209 const ObjectContainer *objectContainer, const QQmlImports *imports,
210 const QByteArray &typeClassName);
211 ~QQmlPropertyCacheCreator() { propertyCaches->seal(); }
212
213
214 /*!
215 \internal
216 Creates the property cache for the CompiledObjects of objectContainer,
217 one (inline) root component at a time.
218
219 \note Later compiler passes might modify those property caches. Therefore,
220 the actual metaobjects are not created yet.
221 */
223
224 /*!
225 \internal
226 Returns a valid error if the inline components of the objectContainer
227 form a cycle. Otherwise an invalid error is returned
228 */
230
231 /*!
232 \internal
233 Tries to creates a property cache for the CompiledObject based on the cache of a base type.
234 Returns QQmlError in case of invalid overrides
235
236 \note: Aliases are added separately in appendAliasToPropertyCache
237 */
238 [[nodiscard]] q23::expected<QQmlPropertyCache::Ptr, QQmlError>
239 tryDeriveCacheFrom(const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache,
240 QByteArray dynamicClassName = QByteArray()) const;
241
242 /*!
243 \internal
244 Tries to create a QQmlPropertyData based on IR of a property.
245 This involves property type resolution and property flags creation
246
247 \a notifyIndex MUST be in the signal index range (see QObjectPrivate::signalIndex()).
248 This is different from QMetaMethod::methodIndex()
249
250 return error in case of failed type resolution
251 */
252 [[nodiscard]] q23::expected<QQmlPropertyData, QQmlError>
253 tryCreateQQmlPropertyData(const QV4::CompiledData::Property &propertyIR, int coreIndex,
254 int notifyIndex) const;
255
256protected:
258
260 const QQmlBindingInstantiationContext &context,
261 VMEMetaObjectIsRequired isVMERequired);
262 QQmlPropertyCache::ConstPtr propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const;
263 QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache);
264
265 QMetaType metaTypeForParameter(const QV4::CompiledData::ParameterType &param,
266 QString *customTypeName = nullptr) const;
267
268 QString stringAt(int index) const { return objectContainer->stringAt(index); }
269
270private:
271 struct PropertyType
272 {
273 QMetaType metaType;
274 QTypeRevision revision = QTypeRevision::zero();
275 QV4::CompiledData::CommonType commonType = QV4::CompiledData::CommonType::Invalid;
276 };
277
278 [[nodiscard]] q23::expected<PropertyType, QQmlError>
279 tryResolvePropertyType(const QV4::CompiledData::Property &propertyIR) const;
280
281 // can be made a free function
282 [[nodiscard]] static QQmlPropertyData::Flags
283 propertyDataFlags(const QV4::CompiledData::Property &propertyIR,
284 const PropertyType &resolvedPropertyType);
285
286protected:
288 const ObjectContainer * const objectContainer;
289 const QQmlImports * const imports;
292 QByteArray typeClassName; // not const as we temporarily chang it for inline components
293 unsigned int currentRoot; // set to objectID of inline component root when handling inline components
294
299 bool hasCycle = false;
300};
301
302template <typename ObjectContainer>
304 QQmlPropertyCacheVector *propertyCaches,
305 QQmlPendingGroupPropertyBindings *pendingGroupPropertyBindings,
306 QQmlTypeLoader *typeLoader,
307 const ObjectContainer *objectContainer, const QQmlImports *imports,
308 const QByteArray &typeClassName)
310 , objectContainer(objectContainer)
313 , pendingGroupPropertyBindings(pendingGroupPropertyBindings)
315 , currentRoot(-1)
316{
317 propertyCaches->resetAndResize(objectContainer->objectCount());
318
319 using namespace icutils;
320
321 // get a list of all inline components
322
323 for (int i=0; i != objectContainer->objectCount(); ++i) {
324 const CompiledObject *obj = objectContainer->objectAt(i);
325 for (auto it = obj->inlineComponentsBegin(); it != obj->inlineComponentsEnd(); ++it) {
326 allICs.push_back(*it);
327 }
328 }
329
330 // create a graph on inline components referencing inline components
331 std::vector<icutils::Node> nodes;
332 nodes.resize(allICs.size());
333 std::iota(nodes.begin(), nodes.end(), 0);
334 AdjacencyList adjacencyList;
335 adjacencyList.resize(nodes.size());
336 fillAdjacencyListForInlineComponents(objectContainer, adjacencyList, nodes, allICs);
337
338 nodesSorted = topoSort(nodes, adjacencyList, hasCycle);
339 nodeIt = nodesSorted.rbegin();
340}
341
342template <typename ObjectContainer>
344{
345 if (hasCycle) {
346 QQmlError diag;
347 diag.setDescription(QLatin1String("Inline components form a cycle!"));
348 return diag;
349 }
350 return {};
351}
352
353template <typename ObjectContainer>
356{
357 // needs to be checked with verifyNoICCycle before this function is called
358 Q_ASSERT(!hasCycle);
359
360 // create meta objects for inline components before compiling actual root component
361 if (nodeIt != nodesSorted.rend()) {
362 const auto &ic = allICs[nodeIt->index()];
363 QV4::ResolvedTypeReference *typeRef = objectContainer->resolvedType(ic.nameIndex);
364 Q_ASSERT(propertyCaches->at(ic.objectIndex).isNull());
365 Q_ASSERT(typeRef->typePropertyCache().isNull()); // not set yet
366
367 QByteArray icTypeName { objectContainer->stringAt(ic.nameIndex).toUtf8() };
368 QScopedValueRollback<QByteArray> nameChange {typeClassName, icTypeName};
369 QScopedValueRollback<unsigned int> rootChange {currentRoot, ic.objectIndex};
370 ++nodeIt;
371 QQmlError diag = buildMetaObjectRecursively(ic.objectIndex, m_context, VMEMetaObjectIsRequired::Always);
372 if (diag.isValid()) {
373 return {diag, false, 0};
374 }
375 typeRef->setTypePropertyCache(propertyCaches->at(ic.objectIndex));
376 Q_ASSERT(!typeRef->typePropertyCache().isNull());
377 return { QQmlError(), true, int(ic.objectIndex) };
378 }
379
380 auto diag = buildMetaObjectRecursively(/*root object*/0, m_context, VMEMetaObjectIsRequired::Maybe);
381 return {diag, false, 0};
382}
383
384template <typename ObjectContainer>
387 const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache,
388 QByteArray dynamicClassName) const
389{
390 QQmlPropertyCache::Ptr cache = baseTypeCache->copyAndReserve(
391 obj->propertyCount() + obj->aliasCount(),
392 obj->functionCount() + obj->propertyCount() + obj->aliasCount() + obj->signalCount(),
393 obj->signalCount() + obj->propertyCount() + obj->aliasCount(), obj->enumCount());
394 cache->_dynamicClassName = std::move(dynamicClassName);
395
396 int effectiveMethodIndex = cache->methodIndexCacheStart;
397
398 // For property change signal override detection.
399 // We prepopulate a set of signal names which already exist in the object,
400 // and throw an error if there is a signal/method defined as an override.
401 // TODO: Remove AllowOverride once we can. No override should be allowed.
402 enum class AllowOverride { No, Yes };
403 QHash<QString, AllowOverride> seenSignals{
404 { QStringLiteral("destroyed"), AllowOverride::No },
405 { QStringLiteral("parentChanged"), AllowOverride::No },
406 { QStringLiteral("objectNameChanged"), AllowOverride::No }
407 };
408 const QQmlPropertyCache *parentCache = cache.data();
409 while ((parentCache = parentCache->parent().data())) {
410 if (int pSigCount = parentCache->signalCount()) {
411 int pSigOffset = parentCache->signalOffset();
412 for (int i = pSigOffset; i < pSigCount; ++i) {
413 const QQmlPropertyData *currPSig = parentCache->signal(i);
414 // XXX TODO: find a better way to get signal name from the property data :-/
415 for (QQmlPropertyCache::StringCache::ConstIterator iter =
416 parentCache->stringCache.begin();
417 iter != parentCache->stringCache.end(); ++iter) {
418 if (currPSig == (*iter).second) {
419 if (currPSig->isOverridableSignal()) {
420 const qsizetype oldSize = seenSignals.size();
421 AllowOverride &entry = seenSignals[iter.key()];
422 if (seenSignals.size() != oldSize)
423 entry = AllowOverride::Yes;
424 } else {
425 seenSignals[iter.key()] = AllowOverride::No;
426 }
427
428 break;
429 }
430 }
431 }
432 }
433 }
434
435 // Set up notify signals for properties - first normal, then alias
436 auto p = obj->propertiesBegin();
437 auto pend = obj->propertiesEnd();
438 for (; p != pend; ++p) {
439 auto flags = QQmlPropertyData::defaultSignalFlags();
440
441 const QString changedSigName =
442 QQmlSignalNames::propertyNameToChangedSignalName(stringAt(p->nameIndex()));
443 seenSignals[changedSigName] = AllowOverride::No;
444
445 cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
446 }
447
448 auto a = obj->aliasesBegin();
449 auto aend = obj->aliasesEnd();
450 for (; a != aend; ++a) {
451 auto flags = QQmlPropertyData::defaultSignalFlags();
452
453 const QString changedSigName =
454 QQmlSignalNames::propertyNameToChangedSignalName(stringAt(a->nameIndex()));
455 seenSignals[changedSigName] = AllowOverride::No;
456
457 cache->appendSignal(changedSigName, flags, effectiveMethodIndex++);
458 }
459
460 auto e = obj->enumsBegin();
461 auto eend = obj->enumsEnd();
462 for (; e != eend; ++e) {
463 const int enumValueCount = e->enumValueCount();
464 QList<QQmlEnumValue> values;
465 values.reserve(enumValueCount);
466
467 auto enumValue = e->enumValuesBegin();
468 auto end = e->enumValuesEnd();
469 for (; enumValue != end; ++enumValue)
470 values.append(QQmlEnumValue(stringAt(enumValue->nameIndex), enumValue->value));
471
472 cache->appendEnum(stringAt(e->nameIndex), values);
473 }
474
475 // Dynamic signals
476 auto s = obj->signalsBegin();
477 auto send = obj->signalsEnd();
478 for (; s != send; ++s) {
479 const int paramCount = s->parameterCount();
480
481 QList<QByteArray> names;
482 names.reserve(paramCount);
483 QVarLengthArray<QMetaType, 10> paramTypes(paramCount);
484
485 if (paramCount) {
486
487 int i = 0;
488 auto param = s->parametersBegin();
489 auto end = s->parametersEnd();
490 for (; param != end; ++param, ++i) {
491 names.append(stringAt(param->nameIndex).toUtf8());
492
493 QString customTypeName;
494 QMetaType type = metaTypeForParameter(param->type, &customTypeName);
495 if (!type.isValid())
496 return q23::make_unexpected(qQmlCompileError(
497 s->location,
498 QQmlPropertyCacheCreatorBase::tr("Invalid signal parameter type: %1")
499 .arg(customTypeName)));
500
501 paramTypes[i] = type;
502 }
503 }
504
505 auto flags = QQmlPropertyData::defaultSignalFlags();
506 if (paramCount)
507 flags.setHasArguments(true);
508
509 QString signalName = stringAt(s->nameIndex);
510 const auto it = seenSignals.find(signalName);
511 if (it == seenSignals.end()) {
512 seenSignals[signalName] = AllowOverride::No;
513 } else {
514 // TODO: Remove the AllowOverride::Yes branch once we can.
515 QQmlError message = qQmlCompileError(
516 s->location,
517 QQmlPropertyCacheCreatorBase::tr(
518 "Duplicate signal name: "
519 "invalid override of property change signal or superclass signal"));
520 switch (*it) {
521 case AllowOverride::No:
522 return q23::make_unexpected(std::move(message));
523 case AllowOverride::Yes:
524 message.setUrl(objectContainer->url());
525 qCWarning(invalidOverride).noquote() << message.toString();
526 *it = AllowOverride::No; // No further overriding allowed.
527 break;
528 }
529 }
530 cache->appendSignal(signalName, flags, effectiveMethodIndex++,
531 paramCount ? paramTypes.constData() : nullptr, names);
532 }
533
534 // Dynamic slots
535 auto function = objectContainer->objectFunctionsBegin(obj);
536 auto fend = objectContainer->objectFunctionsEnd(obj);
537 for (; function != fend; ++function) {
538 auto flags = QQmlPropertyData::defaultSlotFlags();
539
540 const QString slotName = stringAt(function->nameIndex);
541 const auto it = seenSignals.constFind(slotName);
542 if (it != seenSignals.constEnd()) {
543 // TODO: Remove the AllowOverride::Yes branch once we can.
544 QQmlError message = qQmlCompileError(
545 function->location,
546 QQmlPropertyCacheCreatorBase::tr(
547 "Duplicate method name: "
548 "invalid override of property change signal or superclass signal"));
549 switch (*it) {
550 case AllowOverride::No:
551 return q23::make_unexpected(std::move(message));
552 case AllowOverride::Yes:
553 message.setUrl(objectContainer->url());
554 qCWarning(invalidOverride).noquote() << message.toString();
555 break;
556 }
557 }
558 // Note: we don't append slotName to the seenSignals list, since we don't
559 // protect against overriding change signals or methods with properties.
560
561 QList<QByteArray> parameterNames;
562 QList<QMetaType> parameterTypes;
563 auto formal = function->formalsBegin();
564 auto end = function->formalsEnd();
565 for (; formal != end; ++formal) {
566 flags.setHasArguments(true);
567 parameterNames << stringAt(formal->nameIndex).toUtf8();
568 QMetaType type = metaTypeForParameter(formal->type);
569 if (!type.isValid())
570 type = QMetaType::fromType<QVariant>();
571 parameterTypes << type;
572 }
573
574 QMetaType returnType = metaTypeForParameter(function->returnType);
575 if (!returnType.isValid())
576 returnType = QMetaType::fromType<QVariant>();
577
578 cache->appendMethod(slotName, flags, effectiveMethodIndex++, returnType, parameterNames,
579 parameterTypes);
580 }
581
582 // Dynamic properties
583 int propertyIndex = cache->propertyIndexCacheStart;
584 int notifyIndex = cache->signalHandlerIndexCacheStart;
585 int objPropertyIdx = 0;
586 p = obj->propertiesBegin();
587 pend = obj->propertiesEnd();
588 for (; p != pend; ++p, ++objPropertyIdx, propertyIndex++, notifyIndex++) {
589 auto propertyDataOrError = tryCreateQQmlPropertyData(*p, propertyIndex, notifyIndex);
590 if (!propertyDataOrError.has_value()) {
591 return q23::make_unexpected(propertyDataOrError.error());
592 }
593
594 QString propertyName = stringAt(p->nameIndex());
595 if (!obj->hasAliasAsDefaultProperty()
596 && objPropertyIdx == obj->indexOfDefaultPropertyOrAlias)
597 cache->_defaultPropertyName = propertyName;
598
599 const auto &appendResult =
600 cache->appendPropertyAttr(propertyName, std::move(propertyDataOrError).value());
601 if (!appendResult) {
602 return q23::make_unexpected(
603 qQmlCompileError(p->location, explain(appendResult.error())));
604 }
605 }
606 return cache;
607};
608
609template <typename ObjectContainer>
612 const QV4::CompiledData::Property &propertyIR, int coreIndex, int notifyIndex) const
613{
614 const auto propertyTypeOrError = tryResolvePropertyType(propertyIR);
615 if (!propertyTypeOrError.has_value()) {
616 return q23::make_unexpected(propertyTypeOrError.error());
617 }
618 const auto propertyType = propertyTypeOrError.value();
619
620 QQmlPropertyData propertyData;
621 propertyData.setPropType(propertyType.metaType);
622 propertyData.setCoreIndex(coreIndex);
623 propertyData.setNotifyIndex(notifyIndex);
624 propertyData.setFlags(QQmlPropertyCacheCreator::propertyDataFlags(propertyIR, propertyType));
625 propertyData.setTypeVersion(propertyType.revision);
626 return propertyData;
627}
628
629template <typename ObjectContainer>
631{
632 auto isAddressable = [](const QUrl &url) {
633 const QString fileName = url.fileName();
634 return !fileName.isEmpty() && fileName.front().isUpper();
635 };
636
637 const CompiledObject *obj = objectContainer->objectAt(objectIndex);
638 bool needVMEMetaObject = isVMERequired == VMEMetaObjectIsRequired::Always
639 || obj->propertyCount() != 0 || obj->aliasCount() != 0 || obj->signalCount() != 0
640 || obj->functionCount() != 0 || obj->enumCount() != 0
641 || obj->inlineComponentCount() != 0
642 || ((obj->hasFlag(QV4::CompiledData::Object::IsComponent)
643 || (objectIndex == 0 && isAddressable(objectContainer->url())))
644 && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType());
645
646 if (!needVMEMetaObject) {
647 auto binding = obj->bindingsBegin();
648 auto end = obj->bindingsEnd();
649 for ( ; binding != end; ++binding) {
650 if (binding->type() == QV4::CompiledData::Binding::Type_Object
651 && (binding->flags() & QV4::CompiledData::Binding::IsOnAssignment)) {
652 // If the on assignment is inside a group property, we need to distinguish between QObject based
653 // group properties and value type group properties. For the former the base type is derived from
654 // the property that references us, for the latter we only need a meta-object on the referencing object
655 // because interceptors can't go to the shared value type instances.
656 if (context.instantiatingProperty && QQmlMetaType::isValueType(context.instantiatingProperty->propType())) {
657 if (!propertyCaches->needsVMEMetaObject(context.referencingObjectIndex)) {
658 const CompiledObject *obj = objectContainer->objectAt(context.referencingObjectIndex);
659 auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
660 Q_ASSERT(typeRef);
661 QQmlPropertyCache::ConstPtr baseTypeCache = typeRef->createPropertyCache();
662 QQmlError error = baseTypeCache
663 ? createMetaObject(context.referencingObjectIndex, obj, baseTypeCache)
664 : qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr(
665 "Type cannot be used for 'on' assignment"));
666 if (error.isValid())
667 return error;
668 }
669 } else {
670 // On assignments are implemented using value interceptors, which require a VME meta object.
671 needVMEMetaObject = true;
672 }
673 break;
674 }
675 }
676 }
677
678 QQmlPropertyCache::ConstPtr baseTypeCache;
679 {
680 QQmlError error;
681 baseTypeCache = propertyCacheForObject(obj, context, &error);
682 if (error.isValid())
683 return error;
684 }
685
686 if (baseTypeCache) {
687 if (needVMEMetaObject) {
688 QQmlError error = createMetaObject(objectIndex, obj, baseTypeCache);
689 if (error.isValid())
690 return error;
691 } else {
692 propertyCaches->set(objectIndex, baseTypeCache);
693 }
694 }
695
696 QQmlPropertyCache::ConstPtr thisCache = propertyCaches->at(objectIndex);
697 auto binding = obj->bindingsBegin();
698 auto end = obj->bindingsEnd();
699 for (; binding != end; ++binding) {
700 switch (binding->type()) {
701 case QV4::CompiledData::Binding::Type_Object:
702 case QV4::CompiledData::Binding::Type_GroupProperty:
703 case QV4::CompiledData::Binding::Type_AttachedProperty:
704 // We can always resolve object, group, and attached properties.
705 break;
706 default:
707 // Everything else is of no interest here.
708 continue;
709 }
710
712 objectIndex, &(*binding), stringAt(binding->propertyNameIndex), thisCache);
713
714 // Binding to group property where we failed to look up the type of the
715 // property? Possibly a group property that is an alias that's not resolved yet.
716 // Let's attempt to resolve it after we're done with the aliases and fill in the
717 // propertyCaches entry then.
718 if (!thisCache || !context.resolveInstantiatingProperty())
719 pendingGroupPropertyBindings->append(context);
720
721 QQmlError error = buildMetaObjectRecursively(
722 binding->value.objectIndex, context, VMEMetaObjectIsRequired::Maybe);
723 if (error.isValid())
724 return error;
725 }
726
727 QQmlError noError;
728 return noError;
729}
730
731template <typename ObjectContainer>
732inline QQmlPropertyCache::ConstPtr QQmlPropertyCacheCreator<ObjectContainer>::propertyCacheForObject(const CompiledObject *obj, const QQmlBindingInstantiationContext &context, QQmlError *error) const
733{
734 if (context.instantiatingProperty) {
735 return context.instantiatingPropertyCache();
736 } else if (obj->inheritedTypeNameIndex != 0) {
737 auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
738 Q_ASSERT(typeRef);
739
740 if (typeRef->isFullyDynamicType()) {
741 if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
742 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new properties."));
743 return nullptr;
744 }
745 if (obj->signalCount() > 0) {
746 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new signals."));
747 return nullptr;
748 }
749 if (obj->functionCount() > 0) {
750 *error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully Dynamic types cannot declare new functions."));
751 return nullptr;
752 }
753 }
754
755 if (QQmlPropertyCache::ConstPtr propertyCache = typeRef->createPropertyCache())
756 return propertyCache;
757 *error = qQmlCompileError(
758 obj->location,
759 QQmlPropertyCacheCreatorBase::tr("Type '%1' cannot declare new members.")
760 .arg(stringAt(obj->inheritedTypeNameIndex)));
761 return nullptr;
762 } else if (const QV4::CompiledData::Binding *binding = context.instantiatingBinding) {
763 if (binding->isAttachedProperty()) {
764 auto *typeRef = objectContainer->resolvedType(
765 binding->propertyNameIndex);
766 Q_ASSERT(typeRef);
767 QQmlType qmltype = typeRef->type();
768 if (!qmltype.isValid()) {
769 imports->resolveType(
770 typeLoader, stringAt(binding->propertyNameIndex),
771 &qmltype, nullptr, nullptr);
772 }
773
774 const QMetaObject *attachedMo = qmltype.attachedPropertiesType(typeLoader);
775 if (!attachedMo) {
776 *error = qQmlCompileError(binding->location, QQmlPropertyCacheCreatorBase::tr("Non-existent attached object"));
777 return nullptr;
778 }
779 return QQmlMetaType::propertyCache(attachedMo);
780 }
781 }
782 return nullptr;
783}
784
785template <typename ObjectContainer>
787 int objectIndex, const CompiledObject *obj,
788 const QQmlPropertyCache::ConstPtr &baseTypeCache)
789{
790 const auto dynamicClassName = [this](int objectIndex, const auto &baseTypeCache) -> QByteArray {
791 const auto isComponentRoot = objectIndex == 0 /*root object*/
792 || objectIndex == int(currentRoot) /*root object of IC*/;
793 if (isComponentRoot && !typeClassName.isEmpty()) {
794 return typeClassName;
795 }
796 return QByteArray(QQmlMetaObject(baseTypeCache).className())
797 .append("_QML_")
798 .append(QByteArray::number(classIndexCounter.fetchAndAddRelaxed(1)));
799 };
800
801 const auto cacheOrError =
802 tryDeriveCacheFrom(obj, baseTypeCache, dynamicClassName(objectIndex, baseTypeCache));
803 if (!cacheOrError.has_value()) {
804 return cacheOrError.error();
805 }
806 auto &cache = cacheOrError.value();
807
808 using ListPropertyAssignBehavior = typename ObjectContainer::ListPropertyAssignBehavior;
809 switch (objectContainer->listPropertyAssignBehavior()) {
810 case ListPropertyAssignBehavior::ReplaceIfNotDefault:
811 cache->_listPropertyAssignBehavior = "ReplaceIfNotDefault";
812 break;
813 case ListPropertyAssignBehavior::Replace:
814 cache->_listPropertyAssignBehavior = "Replace";
815 break;
816 case ListPropertyAssignBehavior::Append:
817 break;
818 }
819
820 propertyCaches->setOwn(objectIndex, cache);
821 propertyCaches->setNeedsVMEMetaObject(objectIndex);
822 return QQmlError();
823}
824
825template <typename ObjectContainer>
827 const QV4::CompiledData::ParameterType &param, QString *customTypeName) const
828{
829 const quint32 typeId = param.typeNameIndexOrCommonType();
830 if (param.indexIsCommonType()) {
831 // built-in type
832 if (param.isList())
833 return listTypeForPropertyType(QV4::CompiledData::CommonType(typeId));
834 return metaTypeForPropertyType(QV4::CompiledData::CommonType(typeId));
835 }
836
837 // lazily resolved type
838 const QString typeName = stringAt(param.typeNameIndexOrCommonType());
839 if (customTypeName)
840 *customTypeName = typeName;
841 QQmlType qmltype;
842 bool selfReference = false;
843 if (!imports->resolveType(
844 typeLoader, typeName, &qmltype, nullptr, nullptr, nullptr,
845 QQmlType::AnyRegistrationType, &selfReference))
846 return QMetaType();
847
848 if (!qmltype.isComposite()) {
849 const QMetaType typeId = param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
850 if (!typeId.isValid() && qmltype.isInlineComponentType()) {
851 const QQmlType qmlType = objectContainer->qmlTypeForComponent(qmltype.elementName());
852 return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
853 } else {
854 return typeId;
855 }
856 }
857
858 if (selfReference) {
859 const QQmlType qmlType = objectContainer->qmlTypeForComponent();
860 return param.isList() ? qmlType.qListTypeId() : qmlType.typeId();
861 }
862
863 return param.isList() ? qmltype.qListTypeId() : qmltype.typeId();
864}
865
866template <typename ObjectContainer>
867inline auto QQmlPropertyCacheCreator<ObjectContainer>::tryResolvePropertyType(
868 const QV4::CompiledData::Property &propertyIR) const
869 -> q23::expected<PropertyType, QQmlError>
870{
871 using namespace Qt::StringLiterals;
872 PropertyType propertyType;
873 propertyType.commonType = propertyIR.commonType();
874
875 if (propertyType.commonType != QV4::CompiledData::CommonType::Invalid) {
876 // common type
877 propertyType.metaType = propertyIR.isList()
878 ? listTypeForPropertyType(propertyType.commonType)
879 : metaTypeForPropertyType(propertyType.commonType);
880 return propertyType;
881 }
882
883 // needs to be resolved
884 // can be extracted and passed to tryResolvePropertyType as a function object to simplify
885 // dependency injection (imports / typeLoader)
886 Q_ASSERT(!propertyIR.isCommonType());
887 QQmlType qmltype;
888 bool selfReference = false;
889 QList<QQmlError> errors;
890 const QString typeName = stringAt(propertyIR.commonTypeOrTypeNameIndex());
891 if (!imports->resolveType(typeLoader, typeName, &qmltype, nullptr, nullptr, &errors,
892 QQmlType::AnyRegistrationType, &selfReference)) {
893 Q_ASSERT(!errors.isEmpty());
894
895 if (typeName == "list"_L1 && errors[0].description() == "is not a type"_L1) {
896 errors[0].setDescription(errors[0].description().append(
897 ". It requires an element type argument (eg. list<int>)"_L1));
898 }
899
900 return q23::make_unexpected(
901 qQmlCompileError(propertyIR.location, typeName + u' ' + errors[0].description()));
902 }
903
904 Q_ASSERT(qmltype.isValid());
905
906 propertyType.metaType = propertyIR.isList() ? qmltype.qListTypeId() : qmltype.typeId();
907
908 if (!qmltype.isComposite() && !qmltype.isInlineComponentType())
909 propertyType.revision = qmltype.version();
910
911 return propertyType;
912}
913
914template <typename ObjectContainer>
915inline QQmlPropertyData::Flags QQmlPropertyCacheCreator<ObjectContainer>::propertyDataFlags(
916 const QV4::CompiledData::Property &propertyIR, const PropertyType &resolvedPropertyType)
917{
918 QQmlPropertyData::Flags flags;
919
920 // set type flag
921 if (propertyIR.isList()) {
922 flags.setType(QQmlPropertyData::Flags::QListType);
923 } else if (resolvedPropertyType.commonType == QV4::CompiledData::CommonType::Var) {
924 flags.setType(QQmlPropertyData::Flags::VarPropertyType);
925 } else if (resolvedPropertyType.metaType.flags().testFlag(QMetaType::PointerToQObject)) {
926 flags.setType(QQmlPropertyData::Flags::QObjectDerivedType);
927 }
928
929 // set attributes
930 if (!propertyIR.isReadOnly()
931 && !resolvedPropertyType.metaType.flags().testFlag(QMetaType::IsQmlList))
932 flags.setIsWritable(true);
933 if (propertyIR.isFinal())
934 flags.setIsFinal(true);
935 if (propertyIR.isVirtual())
936 flags.setIsVirtual(true);
937 if (propertyIR.isOverride())
938 flags.setDoesOverride(true);
939
940 return flags;
941}
942
943template <typename ObjectContainer, typename CompiledObject>
944int objectForId(const ObjectContainer *objectContainer, const CompiledObject &component, int id)
945{
946 for (quint32 i = 0, count = component.namedObjectsInComponentCount(); i < count; ++i) {
947 const int candidateIndex = component.namedObjectsInComponentTable()[i];
948 const CompiledObject &candidate = *objectContainer->objectAt(candidateIndex);
949 if (candidate.objectId() == id)
950 return candidateIndex;
951 }
952 return -1;
953}
954
955template <typename ObjectContainer>
957{
958public:
959 typedef typename ObjectContainer::CompiledObject CompiledObject;
960
962 QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer);
964 const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex,
965 int aliasIndex, int encodedMetaPropertyIndex);
966
967private:
968 QQmlError propertyDataForAlias(
969 const CompiledObject &component, const QV4::CompiledData::Alias &alias, QMetaType *type,
970 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
971 int targetPropertyIndex);
972
973 QQmlPropertyCacheVector *propertyCaches;
974 const ObjectContainer *objectContainer;
975};
976
977template <typename ObjectContainer>
979 QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
981 , objectContainer(objectContainer)
982{
983}
984
985template <typename ObjectContainer>
986inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
987 const CompiledObject &component, const QV4::CompiledData::Alias &alias, QMetaType *type,
988 QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags, int targetPropertyIndex)
989{
990 *type = QMetaType();
991 bool writable = false;
992 bool resettable = false;
993 bool notifiesViaBindable = false;
994
995 propertyFlags->setIsAlias(true);
996
997 if (alias.isAliasToLocalAlias()) {
998 const QV4::CompiledData::Alias *lastAlias = &alias;
999 QVarLengthArray<const QV4::CompiledData::Alias *, 4> seenAliases({lastAlias});
1000
1001 do {
1002 const int targetObjectIndex = objectForId(
1003 objectContainer, component, lastAlias->targetObjectId());
1004 Q_ASSERT(targetObjectIndex >= 0);
1005 const CompiledObject *targetObject = objectContainer->objectAt(targetObjectIndex);
1006 Q_ASSERT(targetObject);
1007
1008 auto nextAlias = targetObject->aliasesBegin();
1009 for (uint i = 0; i < lastAlias->localAliasIndex; ++i)
1010 ++nextAlias;
1011
1012 const QV4::CompiledData::Alias *targetAlias = &(*nextAlias);
1013 if (seenAliases.contains(targetAlias)) {
1014 return qQmlCompileError(targetAlias->location,
1015 QQmlPropertyCacheCreatorBase::tr("Cyclic alias"));
1016 }
1017
1018 seenAliases.append(targetAlias);
1019 lastAlias = targetAlias;
1020 } while (lastAlias->isAliasToLocalAlias());
1021
1022 return propertyDataForAlias(
1023 component, *lastAlias, type, version, propertyFlags, targetPropertyIndex);
1024 }
1025
1026 const int targetObjectIndex = objectForId(objectContainer, component, alias.targetObjectId());
1027 Q_ASSERT(targetObjectIndex >= 0);
1028 const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
1029
1030 if (targetPropertyIndex == -1) {
1031 Q_ASSERT(alias.hasFlag(QV4::CompiledData::Alias::AliasPointsToPointerObject));
1032 auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
1033 if (!typeRef) {
1034 // Can be caused by the alias target not being a valid id or property. E.g.:
1035 // property alias dataValue: dataVal
1036 // invalidAliasComponent { id: dataVal }
1037 return qQmlCompileError(targetObject.location,
1038 QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
1039 }
1040
1041 const auto referencedType = typeRef->type();
1042 Q_ASSERT(referencedType.isValid());
1043 *type = referencedType.typeId();
1044 if (!type->isValid() && referencedType.isInlineComponentType()) {
1045 *type = objectContainer->qmlTypeForComponent(referencedType.elementName()).typeId();
1046 Q_ASSERT(type->isValid());
1047 }
1048
1049 *version = typeRef->version();
1050
1051 propertyFlags->setType(QQmlPropertyData::Flags::QObjectDerivedType);
1052 } else {
1053 int coreIndex = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).coreIndex();
1054 int valueTypeIndex
1055 = QQmlPropertyIndex::fromEncoded(targetPropertyIndex).valueTypeIndex();
1056
1057 QQmlPropertyCache::ConstPtr targetCache = propertyCaches->at(targetObjectIndex);
1058 Q_ASSERT(targetCache);
1059
1060 const QQmlPropertyData *targetProperty = targetCache->property(coreIndex);
1061 Q_ASSERT(targetProperty);
1062
1063 const QMetaType targetPropType = targetProperty->propType();
1064
1065 const auto populateWithPropertyData = [&](const QQmlPropertyData *property) {
1066 *type = property->propType();
1067 writable = property->isWritable();
1068 resettable = property->isResettable();
1069 notifiesViaBindable = property->notifiesViaBindable();
1070
1071 if (property->isVarProperty())
1072 propertyFlags->setType(QQmlPropertyData::Flags::QVariantType);
1073 else
1074 propertyFlags->copyPropertyTypeFlags(property->flags());
1075 };
1076
1077 // for deep aliases, valueTypeIndex is always set
1078 if (!QQmlMetaType::isValueType(targetPropType) && valueTypeIndex != -1) {
1079 // deep alias property
1080
1081 QQmlPropertyCache::ConstPtr typeCache
1082 = QQmlMetaType::propertyCacheForType(targetPropType);
1083
1084 if (!typeCache) {
1085 // See if it's a half-resolved composite type
1086 if (const QV4::ResolvedTypeReference *typeRef
1087 = objectContainer->resolvedType(targetPropType)) {
1088 typeCache = typeRef->typePropertyCache();
1089 }
1090 }
1091
1092 const QQmlPropertyData *typeProperty = typeCache
1093 ? typeCache->property(valueTypeIndex)
1094 : nullptr;
1095 if (typeProperty == nullptr) {
1096 return qQmlCompileError(
1097 alias.referenceLocation,
1098 QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
1099 }
1100 populateWithPropertyData(typeProperty);
1101 } else {
1102 // value type or primitive type or enum
1103 populateWithPropertyData(targetProperty);
1104
1105 if (valueTypeIndex != -1) {
1106 const QMetaObject *valueTypeMetaObject
1107 = QQmlMetaType::metaObjectForValueType(*type);
1108 const QMetaProperty valueTypeMetaProperty
1109 = valueTypeMetaObject->property(valueTypeIndex);
1110 *type = valueTypeMetaProperty.metaType();
1111
1112 // We can only write or reset the value type property if we can write
1113 // the value type itself.
1114 resettable = writable && valueTypeMetaProperty.isResettable();
1115 writable = writable && valueTypeMetaProperty.isWritable();
1116
1117 // Do not update notifiesViaBindable. The core property counts for notifications.
1118 propertyFlags->setIsDeepAlias(true);
1119 }
1120 }
1121 }
1122
1123 propertyFlags->setIsWritable(
1124 writable && !alias.hasFlag(QV4::CompiledData::Alias::IsReadOnly));
1125 propertyFlags->setIsResettable(resettable);
1126 propertyFlags->setIsBindable(notifiesViaBindable);
1127 return QQmlError();
1128}
1129
1130template <typename ObjectContainer>
1132 const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex,
1133 int aliasIndex, int encodedMetaPropertyIndex)
1134{
1135 const CompiledObject &object = *objectContainer->objectAt(objectIndex);
1136
1137 Q_ASSERT(object.aliasCount() > aliasIndex);
1138 QMetaType type;
1139 QTypeRevision version = QTypeRevision::zero();
1140 QQmlPropertyData::Flags propertyFlags;
1141 QQmlError error = propertyDataForAlias(
1142 component, alias, &type, &version, &propertyFlags, encodedMetaPropertyIndex);
1143 if (error.isValid())
1144 return error;
1145
1146 const QString propertyName = objectContainer->stringAt(alias.nameIndex());
1147
1148 const QQmlPropertyCache::Ptr propertyCache = propertyCaches->ownAt(objectIndex);
1149 Q_ASSERT(propertyCache);
1150
1151 const int effectiveSignalIndex
1152 = propertyCache->signalHandlerIndexCacheStart + propertyCache->propertyIndexCache.size();
1153 const int effectivePropertyIndex
1154 = propertyCache->propertyIndexCacheStart + propertyCache->propertyIndexCache.size();
1155
1156 if (object.hasAliasAsDefaultProperty() && aliasIndex == object.indexOfDefaultPropertyOrAlias)
1157 propertyCache->_defaultPropertyName = propertyName;
1158
1159 const auto &appendResult =
1160 propertyCache->appendAlias(propertyName, propertyFlags, effectivePropertyIndex, type,
1161 version, effectiveSignalIndex, encodedMetaPropertyIndex);
1162 if (!appendResult) {
1163 return qQmlCompileError(alias.location,
1164 QQmlPropertyCacheCreatorBase::explain(appendResult.error()));
1165 }
1166 return QQmlError();
1167}
1168
1169QT_END_NAMESPACE
1170
1171#endif // QQMLPROPERTYCACHECREATOR_P_H
QQmlError appendAliasToPropertyCache(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int objectIndex, int aliasIndex, int encodedMetaPropertyIndex)
QQmlPropertyCacheAliasCreator(QQmlPropertyCacheVector *propertyCaches, const ObjectContainer *objectContainer)
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
QQmlError createMetaObject(int objectIndex, const CompiledObject *obj, const QQmlPropertyCache::ConstPtr &baseTypeCache)
QMetaType metaTypeForParameter(const QV4::CompiledData::ParameterType &param, QString *customTypeName=nullptr) const
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)
q23::expected< QQmlPropertyData, QQmlError > tryCreateQQmlPropertyData(const QV4::CompiledData::Property &propertyIR, int coreIndex, int notifyIndex) const
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)
QQmlPropertyCache::ConstPtr referencingObjectPropertyCache
const QV4::CompiledData::Binding * instantiatingBinding
const QQmlPropertyData * instantiatingProperty
QQmlPropertyCache::ConstPtr instantiatingPropertyCache() const
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)