3#ifndef QQMLCOMPONENTANDALIASRESOLVER_P_H
4#define QQMLCOMPONENTANDALIASRESOLVER_P_H
17#include <QtQml/qqmlcomponent.h>
18#include <QtQml/qqmlerror.h>
20#include <QtCore/qglobal.h>
21#include <QtCore/qhash.h>
23#include <private/qqmltypeloader_p.h>
24#include <private/qqmlpropertycachecreator_p.h>
36template<
typename ObjectContainer>
45 ObjectContainer *compiler,
52 enum AliasResolutionResult {
60 void setObjectId(
int index)
const;
61 [[nodiscard]]
bool markAsComponent(
int index)
const;
62 [[nodiscard]] AliasResolutionResult resolveAliasesInObject(
67 [[nodiscard]]
QQmlError findAndRegisterImplicitComponents(
69 [[nodiscard]]
QQmlError collectIdsAndAliases(
int objectIndex);
70 [[nodiscard]]
QQmlError resolveAliases(
int componentIndex);
71 void resolveGeneralizedGroupProperties(
int componentIndex);
72 [[nodiscard]]
QQmlError resolveComponentsInInlineComponentRoot(
int root);
74 QString stringAt(
int idx)
const {
return m_compiler->stringAt(idx); }
82 error.setLine(qmlConvertSourceCoordinate<quint32, int>(
location.line()));
83 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(
location.column()));
84 error.setDescription(description);
85 error.setUrl(m_compiler->url());
89 template<
typename Token>
101 if (
metaObject == &QQmlComponent::staticMetaObject)
112 ObjectContainer *m_compiler =
nullptr;
120 QVector<quint32> m_componentRoots;
121 QVector<int> m_objectsWithAliases;
122 QVector<CompiledBinding *> m_generalizedGroupProperties;
123 typename ObjectContainer::IdToObjectMap m_idToObjectIndex;
126template<
typename ObjectContainer>
128 ObjectContainer *compiler,
131 : m_compiler(compiler)
132 , m_enginePrivate(enginePrivate)
133 , m_propertyCaches(propertyCaches)
137template<
typename ObjectContainer>
144 ? propertyCache->parent()->defaultProperty()
145 : propertyCache->defaultProperty();
147 for (
auto binding =
obj->bindingsBegin(),
end =
obj->bindingsEnd(); binding !=
end; ++binding) {
153 auto targetObject = m_compiler->objectAt(binding->value.objectIndex);
154 auto typeReference = resolvedType(targetObject->inheritedTypeNameIndex);
158 const auto type = typeReference->type();
160 firstMetaObject =
type.metaObject();
161 else if (
const auto compilationUnit = typeReference->compilationUnit())
162 firstMetaObject = compilationUnit->rootPropertyCache()->firstCppMetaObject();
163 if (isUsableComponent(firstMetaObject))
168 if (binding->propertyNameIndex !=
quint32(0)) {
169 bool notInRevision =
false;
170 pd = propertyResolver.property(stringAt(binding->propertyNameIndex), ¬InRevision);
172 pd = defaultProperty;
182 :
QQmlMetaType::rawPropertyCacheForType(pd->propType());
183 const QMetaObject *
mo = pc ? pc->firstCppMetaObject() :
nullptr;
185 if (
mo == &QQmlComponent::staticMetaObject)
187 mo =
mo->superClass();
193 if (!wrapImplicitComponent(binding))
194 return error(binding,
tr(
"Cannot wrap implicit component"));
200template<
typename ObjectContainer>
207 const auto rootObj = m_compiler->objectAt(root);
210 if (
const int typeName = rootObj->inheritedTypeNameIndex) {
211 const auto *tref = resolvedType(
typeName);
213 if (tref->type().metaObject() == &QQmlComponent::staticMetaObject) {
214 qCWarning(lcQmlTypeCompiler).nospace().noquote()
215 << m_compiler->url().toString() <<
":" << rootObj->location.line() <<
":"
216 << rootObj->location.column()
217 <<
": Using a Component as the root of an inline component is deprecated: "
218 "inline components are "
219 "automatically wrapped into Components when needed.";
227 return findAndRegisterImplicitComponents(rootObj, rootCache);
231template<
typename ObjectContainer>
238 const int objCountWithoutSynthesizedComponents = m_compiler->objectCount();
241 const QQmlError error = resolveComponentsInInlineComponentRoot(root);
247 const int startObjectIndex = root == 0 ? root : root+1;
249 for (
int i = startObjectIndex;
i < objCountWithoutSynthesizedComponents; ++
i) {
250 auto obj = m_compiler->objectAt(
i);
251 const bool isInlineComponentRoot
253 const bool isPartOfInlineComponent
259 if (isInlineComponentRoot || isPartOfInlineComponent)
261 }
else if (!isPartOfInlineComponent || isInlineComponentRoot) {
269 if (
obj->inheritedTypeNameIndex == 0 && !
cache)
272 bool isExplicitComponent =
false;
273 if (
obj->inheritedTypeNameIndex) {
274 auto *tref = resolvedType(
obj->inheritedTypeNameIndex);
276 if (tref->type().metaObject() == &QQmlComponent::staticMetaObject)
277 isExplicitComponent =
true;
280 if (!isExplicitComponent) {
289 if (!markAsComponent(
i))
290 return error(
obj,
tr(
"Cannot mark object as component"));
294 if (isExplicitComponent)
295 qCWarning(lcQmlTypeCompiler).nospace().noquote()
296 << m_compiler->url().toString() <<
":" <<
obj->location.line() <<
":"
297 <<
obj->location.column()
298 <<
": Using a Component as the root of a QML document is deprecated: types "
299 "defined in qml documents are "
300 "automatically wrapped into Components when needed.";
303 if (
obj->functionCount() > 0)
304 return error(
obj,
tr(
"Component objects cannot declare new functions."));
305 if (
obj->propertyCount() > 0 ||
obj->aliasCount() > 0)
306 return error(
obj,
tr(
"Component objects cannot declare new properties."));
307 if (
obj->signalCount() > 0)
308 return error(
obj,
tr(
"Component objects cannot declare new signals."));
310 if (
obj->bindingCount() == 0)
311 return error(
obj,
tr(
"Cannot create empty component specification"));
313 const auto rootBinding =
obj->bindingsBegin();
314 const auto bindingsEnd =
obj->bindingsEnd();
318 for (
auto b = rootBinding;
b != bindingsEnd; ++
b) {
319 if (
b->propertyNameIndex == 0)
322 return error(
b,
tr(
"Component elements may not contain properties other than id"));
325 if (
auto b = rootBinding;
327 return error(
obj,
tr(
"Invalid component body specification"));
333 m_componentRoots.append(
i);
336 for (
int i = 0;
i < m_componentRoots.size(); ++
i) {
338 const auto rootBinding =
component->bindingsBegin();
340 m_idToObjectIndex.clear();
341 m_objectsWithAliases.clear();
342 m_generalizedGroupProperties.clear();
344 if (
const QQmlError error = collectIdsAndAliases(rootBinding->value.objectIndex);
354 resolveGeneralizedGroupProperties(m_componentRoots.at(
i));
358 m_idToObjectIndex.clear();
359 m_objectsWithAliases.clear();
360 m_generalizedGroupProperties.clear();
365 allocateNamedObjects(m_compiler->objectAt(root));
369 resolveGeneralizedGroupProperties(root);
373template<
typename ObjectContainer>
376 auto obj = m_compiler->objectAt(objectIndex);
378 if (
obj->idNameIndex != 0) {
379 if (m_idToObjectIndex.contains(
obj->idNameIndex))
380 return error(
obj->locationOfIdProperty,
tr(
"id is not unique"));
381 setObjectId(objectIndex);
382 m_idToObjectIndex.insert(
obj->idNameIndex, objectIndex);
385 if (
obj->aliasCount() > 0)
386 m_objectsWithAliases.append(objectIndex);
392 for (
auto binding =
obj->bindingsBegin(),
end =
obj->bindingsEnd();
393 binding !=
end; ++binding) {
394 switch (binding->type()) {
396 const auto *inner = m_compiler->objectAt(binding->value.objectIndex);
397 if (m_compiler->stringAt(inner->inheritedTypeNameIndex).isEmpty()) {
398 const auto cache = m_propertyCaches->at(objectIndex);
400 m_compiler->stringAt(binding->propertyNameIndex),
nullptr,
nullptr)) {
401 m_generalizedGroupProperties.append(binding);
408 if (
const QQmlError error = collectIdsAndAliases(binding->value.objectIndex);
421template<
typename ObjectContainer>
424 if (m_objectsWithAliases.isEmpty())
427 QQmlPropertyCacheAliasCreator<ObjectContainer> aliasCacheCreator(m_propertyCaches, m_compiler);
429 bool atLeastOneAliasResolved;
431 atLeastOneAliasResolved =
false;
432 QVector<int> pendingObjects;
434 for (
int objectIndex:
std::as_const(m_objectsWithAliases)) {
437 const auto &
component = *m_compiler->objectAt(componentIndex);
442 if (
result == AllAliasesResolved) {
444 component, objectIndex, m_enginePrivate);
447 atLeastOneAliasResolved =
true;
448 }
else if (
result == SomeAliasesResolved) {
449 atLeastOneAliasResolved =
true;
450 pendingObjects.append(objectIndex);
452 pendingObjects.append(objectIndex);
455 qSwap(m_objectsWithAliases, pendingObjects);
456 }
while (!m_objectsWithAliases.isEmpty() && atLeastOneAliasResolved);
458 if (!atLeastOneAliasResolved && !m_objectsWithAliases.isEmpty()) {
459 const CompiledObject *
obj = m_compiler->objectAt(m_objectsWithAliases.first());
460 for (
auto alias =
obj->aliasesBegin(),
end =
obj->aliasesEnd(); alias !=
end; ++alias) {
462 return error(alias->location,
tr(
"Circular alias reference detected"));
469template<
typename ObjectContainer>
473 const auto &
component = *m_compiler->objectAt(componentIndex);
474 for (CompiledBinding *binding : m_generalizedGroupProperties)
475 resolveGeneralizedGroupProperty(
component, binding);
QQmlComponentAndAliasResolver(ObjectContainer *compiler, QQmlEnginePrivate *enginePrivate, QQmlPropertyCacheVector *propertyCaches)
QQmlError resolve(int root=0)
typename ObjectContainer::CompiledObject CompiledObject
typename ObjectContainer::CompiledBinding CompiledBinding
The QQmlError class encapsulates a QML error.
QTypeRevision typeVersion() const
QMetaType propType() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
constexpr bool hasMinorVersion() const
Returns true if the minor version is known, otherwise false.
QCache< int, Employee > cache
[0]
Combined button and popup list for selecting options.
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
#define Q_DECLARE_TR_FUNCTIONS(context)
DBusConnection const char DBusError * error
#define qCWarning(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLboolean GLboolean GLboolean b
static qreal component(const QPointF &point, unsigned int i)
QT_BEGIN_NAMESPACE constexpr void qSwap(T &value1, T &value2) noexcept(std::is_nothrow_swappable_v< T >)
obj metaObject() -> className()
@ IsPartOfInlineComponent