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>
30template<
typename ObjectContainer>
39 ObjectContainer *compiler,
46 enum AliasResolutionResult {
54 void setObjectId(
int index)
const;
55 [[nodiscard]]
bool markAsComponent(
int index)
const;
56 [[nodiscard]] AliasResolutionResult resolveAliasesInObject(
int objectIndex,
QQmlError *
error);
59 [[nodiscard]]
QQmlError findAndRegisterImplicitComponents(
61 [[nodiscard]]
QQmlError collectIdsAndAliases(
int objectIndex);
62 [[nodiscard]]
QQmlError resolveAliases(
int componentIndex);
64 QString stringAt(
int idx)
const {
return m_compiler->stringAt(idx); }
74 error.setDescription(description);
75 error.setUrl(m_compiler->url());
79 template<
typename Token>
91 if (
metaObject == &QQmlComponent::staticMetaObject)
102 ObjectContainer *m_compiler =
nullptr;
112 typename ObjectContainer::IdToObjectMap m_idToObjectIndex;
115template<
typename ObjectContainer>
117 ObjectContainer *compiler,
120 : m_compiler(compiler)
121 , m_enginePrivate(enginePrivate)
122 , m_propertyCaches(propertyCaches)
126template<
typename ObjectContainer>
133 ? propertyCache->parent()->defaultProperty()
134 : propertyCache->defaultProperty();
136 for (
auto binding =
obj->bindingsBegin(),
end =
obj->bindingsEnd(); binding !=
end; ++binding) {
142 auto targetObject = m_compiler->objectAt(binding->value.objectIndex);
143 auto typeReference = resolvedType(targetObject->inheritedTypeNameIndex);
147 const auto type = typeReference->type();
149 firstMetaObject =
type.metaObject();
150 else if (
const auto compilationUnit = typeReference->compilationUnit())
151 firstMetaObject = compilationUnit->rootPropertyCache()->firstCppMetaObject();
152 if (isUsableComponent(firstMetaObject))
157 if (binding->propertyNameIndex !=
quint32(0)) {
158 bool notInRevision =
false;
159 pd = propertyResolver.property(stringAt(binding->propertyNameIndex), ¬InRevision);
161 pd = defaultProperty;
171 :
QQmlMetaType::rawPropertyCacheForType(pd->propType());
172 const QMetaObject *
mo = pc ? pc->firstCppMetaObject() :
nullptr;
174 if (
mo == &QQmlComponent::staticMetaObject)
176 mo =
mo->superClass();
182 if (!wrapImplicitComponent(binding))
183 return error(binding,
tr(
"Cannot wrap implicit component"));
190template<
typename ObjectContainer>
197 const int objCountWithoutSynthesizedComponents = m_compiler->objectCount();
200 const int startObjectIndex = root == 0 ? root : root+1;
202 for (
int i = startObjectIndex;
i < objCountWithoutSynthesizedComponents; ++
i) {
203 auto obj = m_compiler->objectAt(
i);
204 const bool isInlineComponentRoot
206 const bool isPartOfInlineComponent
210 bool isExplicitComponent =
false;
211 if (
obj->inheritedTypeNameIndex) {
212 auto *tref = resolvedType(
obj->inheritedTypeNameIndex);
214 if (tref->type().metaObject() == &QQmlComponent::staticMetaObject)
215 isExplicitComponent =
true;
218 if (isInlineComponentRoot && isExplicitComponent) {
219 qCWarning(lcQmlTypeCompiler).nospace().noquote()
220 << m_compiler->url().toString() <<
":" <<
obj->location.line() <<
":"
221 <<
obj->location.column()
222 <<
": Using a Component as the root of an inline component is deprecated: "
223 "inline components are "
224 "automatically wrapped into Components when needed.";
229 if (isInlineComponentRoot || isPartOfInlineComponent)
231 }
else if (!isPartOfInlineComponent || isInlineComponentRoot) {
234 if (
cache && !isExplicitComponent) {
242 if (
obj->inheritedTypeNameIndex == 0 && !
cache)
245 if (!isExplicitComponent) {
254 if (!markAsComponent(
i))
255 return error(
obj,
tr(
"Cannot mark object as component"));
259 if (isExplicitComponent)
260 qCWarning(lcQmlTypeCompiler).nospace().noquote()
261 << m_compiler->url().toString() <<
":" <<
obj->location.line() <<
":"
262 <<
obj->location.column()
263 <<
": Using a Component as the root of a QML document is deprecated: types "
264 "defined in qml documents are "
265 "automatically wrapped into Components when needed.";
268 if (
obj->functionCount() > 0)
269 return error(
obj,
tr(
"Component objects cannot declare new functions."));
270 if (
obj->propertyCount() > 0 ||
obj->aliasCount() > 0)
271 return error(
obj,
tr(
"Component objects cannot declare new properties."));
272 if (
obj->signalCount() > 0)
273 return error(
obj,
tr(
"Component objects cannot declare new signals."));
275 if (
obj->bindingCount() == 0)
276 return error(
obj,
tr(
"Cannot create empty component specification"));
278 const auto rootBinding =
obj->bindingsBegin();
279 const auto bindingsEnd =
obj->bindingsEnd();
283 for (
auto b = rootBinding;
b != bindingsEnd; ++
b) {
284 if (
b->propertyNameIndex == 0)
287 return error(
b,
tr(
"Component elements may not contain properties other than id"));
290 if (
auto b = rootBinding;
292 return error(
obj,
tr(
"Invalid component body specification"));
298 m_componentRoots.append(
i);
301 for (
int i = 0;
i < m_componentRoots.size(); ++
i) {
303 const auto rootBinding =
component->bindingsBegin();
305 m_idToObjectIndex.clear();
306 m_objectsWithAliases.clear();
308 if (
const QQmlError error = collectIdsAndAliases(rootBinding->value.objectIndex);
320 m_idToObjectIndex.clear();
321 m_objectsWithAliases.clear();
326 allocateNamedObjects(m_compiler->objectAt(root));
327 return resolveAliases(root);
330template<
typename ObjectContainer>
333 auto obj = m_compiler->objectAt(objectIndex);
335 if (
obj->idNameIndex != 0) {
336 if (m_idToObjectIndex.contains(
obj->idNameIndex))
337 return error(
obj->locationOfIdProperty,
tr(
"id is not unique"));
338 setObjectId(objectIndex);
339 m_idToObjectIndex.insert(
obj->idNameIndex, objectIndex);
342 if (
obj->aliasCount() > 0)
343 m_objectsWithAliases.append(objectIndex);
349 for (
auto binding =
obj->bindingsBegin(),
end =
obj->bindingsEnd();
350 binding !=
end; ++binding) {
351 switch (binding->type()) {
355 if (
const QQmlError error = collectIdsAndAliases(binding->value.objectIndex);
368template<
typename ObjectContainer>
371 if (m_objectsWithAliases.isEmpty())
376 bool atLeastOneAliasResolved;
378 atLeastOneAliasResolved =
false;
381 for (
int objectIndex:
std::as_const(m_objectsWithAliases)) {
384 const auto result = resolveAliasesInObject(objectIndex, &
error);
388 if (
result == AllAliasesResolved) {
390 *m_compiler->objectAt(componentIndex), objectIndex, m_enginePrivate);
393 atLeastOneAliasResolved =
true;
394 }
else if (
result == SomeAliasesResolved) {
395 atLeastOneAliasResolved =
true;
396 pendingObjects.
append(objectIndex);
398 pendingObjects.
append(objectIndex);
401 qSwap(m_objectsWithAliases, pendingObjects);
402 }
while (!m_objectsWithAliases.isEmpty() && atLeastOneAliasResolved);
404 if (!atLeastOneAliasResolved && !m_objectsWithAliases.isEmpty()) {
405 const CompiledObject *
obj = m_compiler->objectAt(m_objectsWithAliases.first());
406 for (
auto alias =
obj->aliasesBegin(),
end =
obj->aliasesEnd(); alias !=
end; ++alias) {
408 return error(alias->location,
tr(
"Circular alias reference detected"));
void append(parameter_type t)
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)
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
obj metaObject() -> className()
@ IsPartOfInlineComponent