12#include <QtCore/qqueue.h>
13#include <QtCore/qsharedpointer.h>
15#include <private/qduplicatetracker_p.h>
22
23
24
25
26
27
28
29
30
31
33using namespace Qt::StringLiterals;
35QQmlJSScope::QQmlJSScope(
const QString &internalName) : QQmlJSScope{}
37 m_internalName = internalName;
40void QQmlJSScope::reparent(
const QQmlJSScope::Ptr &parentScope,
const QQmlJSScope::Ptr &childScope)
42 if (
const QQmlJSScope::Ptr parent = childScope->m_parentScope.toStrongRef())
43 parent->m_childScopes.removeOne(childScope);
45 parentScope->m_childScopes.append(childScope);
46 childScope->m_parentScope = parentScope;
50
51
52
53
54
55QQmlJSScope::Ptr QQmlJSScope::resetForReparse(Ptr &&scope)
57 auto *factory = scope.factory();
59 const QString moduleName = scope->moduleName();
60 const bool isSingleton = scope->isSingleton();
61 *scope = QQmlJSScope{ scope->internalName() };
62 scope->setOwnModuleName(moduleName);
63 scope->setIsSingleton(isSingleton);
64 return std::move(scope);
67 const QString moduleName = factory->moduleName();
68 const QString internalName = factory->internalName();
69 const bool isSingleton = factory->isSingleton();
70 *scope.factory() = QQmlJSScope::ConstPtr::Factory{ };
71 scope->setOwnModuleName(moduleName);
72 scope->setInternalName(internalName);
73 scope->setIsSingleton(isSingleton);
74 return std::move(scope);
78
79
80
81QHash<QString, QQmlJSScope::JavaScriptIdentifier> QQmlJSScope::ownJSIdentifiers()
const
83 return m_jsIdentifiers;
86void QQmlJSScope::insertJSIdentifier(
const QString &name,
const JavaScriptIdentifier &identifier)
88 Q_ASSERT(m_scopeType != QQmlSA::ScopeType::QMLScope);
89 if (identifier.kind == JavaScriptIdentifier::LexicalScoped
90 || identifier.kind == JavaScriptIdentifier::Injected
91 || QQmlSA::isFunctionScope(m_scopeType)) {
92 m_jsIdentifiers.insert(name, identifier);
94 auto targetScope = parentScope();
95 while (targetScope->m_scopeType != QQmlSA::ScopeType::JSFunctionScope)
96 targetScope = targetScope->parentScope();
97 targetScope->m_jsIdentifiers.insert(name, identifier);
101void QQmlJSScope::setLineNumber(quint32 lineNumber)
103 m_sourceLocation.startLine = lineNumber;
105 m_sourceLocation.startColumn = 1;
108void QQmlJSScope::setLineNumberInResolvedFile(quint32 lineNumber)
110 m_lineNumberInResolvedFile = lineNumber;
113bool QQmlJSScope::hasMethod(
const QString &name)
const
115 return QQmlJSUtils::searchBaseAndExtensionTypes(
116 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
117 if (mode == QQmlJSScope::ExtensionNamespace)
119 return scope->m_methods.contains(name);
124
125
126
127
128
129
130
131
132QHash<QString, QQmlJSMetaMethod> QQmlJSScope::methods()
const
134 QHash<QString, QQmlJSMetaMethod> results;
135 QQmlJSUtils::searchBaseAndExtensionTypes(
136 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
137 if (mode == QQmlJSScope::ExtensionNamespace)
139 for (
auto it = scope->m_methods.constBegin(); it != scope->m_methods.constEnd();
141 if (!results.contains(it.key()))
142 results.insert(it.key(), it.value());
150QList<QQmlJSMetaMethod> QQmlJSScope::methods(
const QString &name)
const
152 QList<QQmlJSMetaMethod> results;
154 QQmlJSUtils::searchBaseAndExtensionTypes(
155 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
156 if (mode == QQmlJSScope::ExtensionNamespace)
158 results.append(scope->ownMethods(name));
164QList<QQmlJSMetaMethod> QQmlJSScope::methods(
const QString &name, QQmlJSMetaMethodType type)
const
166 QList<QQmlJSMetaMethod> results;
168 QQmlJSUtils::searchBaseAndExtensionTypes(
169 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
170 if (mode == QQmlJSScope::ExtensionNamespace)
172 const auto ownMethods = scope->ownMethods(name);
173 for (
const auto &method : ownMethods) {
174 if (method.methodType() == type)
175 results.append(method);
182bool QQmlJSScope::hasEnumeration(
const QString &name)
const
184 return QQmlJSUtils::searchBaseAndExtensionTypes(
185 this, [&](
const QQmlJSScope *scope) {
return scope->m_enumerations.contains(name); });
188bool QQmlJSScope::hasOwnEnumerationKey(
const QString &name)
const
190 for (
const auto &e : m_enumerations) {
191 if (e.keys().contains(name))
197bool QQmlJSScope::hasEnumerationKey(
const QString &name)
const
199 return QQmlJSUtils::searchBaseAndExtensionTypes(
200 this, [&](
const QQmlJSScope *scope) {
return scope->hasOwnEnumerationKey(name); });
203QQmlJSMetaEnum QQmlJSScope::enumeration(
const QString &name)
const
205 QQmlJSMetaEnum result;
207 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
208 const auto it = scope->m_enumerations.find(name);
209 if (it == scope->m_enumerations.end())
218QHash<QString, QQmlJSMetaEnum> QQmlJSScope::enumerations()
const
220 QHash<QString, QQmlJSMetaEnum> results;
222 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
223 for (
auto it = scope->m_enumerations.constBegin(); it != scope->m_enumerations.constEnd();
225 if (!results.contains(it.key()))
226 results.insert(it.key(), it.value());
234QString QQmlJSScope::augmentedInternalName()
const
236 using namespace Qt::StringLiterals;
237 Q_ASSERT(!m_internalName.isEmpty());
239 switch (m_semantics) {
240 case AccessSemantics::Reference:
241 return m_internalName +
" *"_L1;
242 case AccessSemantics::Value:
243 case AccessSemantics::Sequence:
245 case AccessSemantics::None:
249 for (QQmlJSScope::ConstPtr base = baseType(); base; base = base->baseType()) {
250 switch (base->accessSemantics()) {
251 case AccessSemantics::Reference:
252 return m_internalName +
" *"_L1;
253 case AccessSemantics::Value:
254 case AccessSemantics::Sequence:
255 return m_internalName;
256 case AccessSemantics::None:
262 return m_internalName;
265QString QQmlJSScope::prettyName(QAnyStringView name)
267 const auto internal =
"$internal$."_L1;
268 const QString anonymous =
"$anonymous$."_L1;
270 QString pretty = name.toString();
272 if (pretty.startsWith(internal))
273 pretty = pretty.mid(internal.size());
274 else if (pretty.startsWith(anonymous))
275 pretty = pretty.mid(anonymous.size());
277 if (pretty == u"std::nullptr_t")
280 if (pretty == u"void")
281 return u"undefined"_s;
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303QQmlJSScope::IsComponentRoot QQmlJSScope::componentRootStatus()
const {
304 if (m_flags.testAnyFlags(
305 Flags(WrappedInImplicitComponent | FileRootComponent | InlineComponent))) {
306 return IsComponentRoot::Yes;
310 if (m_flags.testFlag(AssignedToUnknownProperty))
311 return IsComponentRoot::Maybe;
313 auto base = nonCompositeBaseType(parentScope());
315 return IsComponentRoot::No;
316 return base->internalName() == u"QQmlComponent"
317 ? IsComponentRoot::Yes
318 : IsComponentRoot::No;
321std::optional<QQmlJSScope::JavaScriptIdentifier>
322QQmlJSScope::jsIdentifier(
const QString &id)
const
324 for (
const auto *scope =
this; scope; scope = scope->parentScope().data()) {
325 if (QQmlSA::isFunctionScope(scope->m_scopeType)
326 || scope->m_scopeType == QQmlSA::ScopeType::JSLexicalScope) {
327 auto it = scope->m_jsIdentifiers.find(id);
328 if (it != scope->m_jsIdentifiers.end())
333 return std::optional<JavaScriptIdentifier>{};
336std::optional<QQmlJSScope::JavaScriptIdentifier> QQmlJSScope::ownJSIdentifier(
const QString &id)
const
338 auto it = m_jsIdentifiers.find(id);
339 if (it != m_jsIdentifiers.end())
342 return std::optional<JavaScriptIdentifier>{};
348 const int separatorIndex = typeName.lastIndexOf(u'.');
350 if (separatorIndex < 1 || separatorIndex >= typeName.size() - 1)
353 const auto parentIt = contextualTypes.types().constFind(typeName.first(separatorIndex).toString());
354 if (parentIt == contextualTypes.types().constEnd())
357 auto inlineComponentParent = *parentIt;
363 QStringView inlineComponentName = typeName.sliced(separatorIndex + 1);
364 QQueue<QQmlJSScope::ConstPtr> candidatesForInlineComponents;
365 candidatesForInlineComponents.enqueue(inlineComponentParent.scope);
366 while (candidatesForInlineComponents.size()) {
367 QQmlJSScope::ConstPtr current = candidatesForInlineComponents.dequeue();
370 if (current->isInlineComponent() && current->inlineComponentName() == inlineComponentName) {
371 return { current, inlineComponentParent.revision };
376 const auto &childScopes = current->childScopes();
377 for (
const auto &child : childScopes) {
378 if (child->scopeType() == QQmlSA::ScopeType::QMLScope)
379 candidatesForInlineComponents.enqueue(child);
382 if (
const auto base = current->baseType())
383 candidatesForInlineComponents.enqueue(base);
389
390
391
392
393
394
395
396QQmlJSScope::ImportedScope<QQmlJSScope::ConstPtr> QQmlJSScope::findType(
397 const QString &name,
const QQmlJS::ContextualTypes &contextualTypes,
398 QSet<QString> *usedTypes)
400 const auto useType = [&]() {
401 if (usedTypes !=
nullptr)
402 usedTypes->insert(name);
405 auto type = contextualTypes.types().constFind(name);
406 const QString currentSelector = contextualTypes.currentFileSelector();
408 if (type != contextualTypes.types().constEnd()) {
410 if (currentSelector.isEmpty()) {
415 const QString typeSelector = QQmlJSUtils::fileSelectorFor(type->scope);
416 if (typeSelector.isEmpty() || typeSelector == currentSelector) {
420 if (
auto matching = contextualTypes.fileSelectedTypeFor(name, currentSelector)) {
424 }
else if (!currentSelector.isEmpty()) {
426 if (
auto matching = contextualTypes.fileSelectedTypeFor(name, currentSelector)) {
432 const auto findListType = [&](
const QString &prefix,
const QString &postfix)
433 -> ImportedScope<ConstPtr> {
434 if (name.startsWith(prefix) && name.endsWith(postfix)) {
435 const qsizetype prefixLength = prefix.length();
436 const QString &elementName
437 = name.mid(prefixLength, name.length() - prefixLength - postfix.length());
438 const ImportedScope<ConstPtr> element
439 = findType(elementName, contextualTypes, usedTypes);
442 return { element.scope->listType(), element.revision };
449 switch (contextualTypes.context()) {
450 case QQmlJS::ContextualTypes::INTERNAL: {
451 if (
const auto listType = findListType(u"QList<"_s, u">"_s);
452 listType.scope && !listType.scope->isReferenceType()) {
456 if (
const auto listType = findListType(u"QQmlListProperty<"_s, u">"_s);
457 listType.scope && listType.scope->isReferenceType()) {
462 const auto colonColon = name.lastIndexOf(QStringLiteral(
"::"));
463 if (colonColon == -1)
466 const QString outerTypeName = name.left(colonColon);
467 const auto outerType = contextualTypes.types().constFind(outerTypeName);
468 if (outerType == contextualTypes.types().constEnd())
471 for (
const auto &innerType : std::as_const(outerType->scope->m_childScopes)) {
472 if (innerType->m_internalName == name) {
474 return { innerType, outerType->revision };
480 case QQmlJS::ContextualTypes::QML: {
482 const auto inlineComponent = qFindInlineComponents(name, contextualTypes);
483 if (inlineComponent.scope) {
485 return inlineComponent;
488 if (
const auto listType = findListType(u"list<"_s, u">"_s); listType.scope)
497QTypeRevision QQmlJSScope::resolveType(
498 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &context,
499 QSet<QString> *usedTypes)
501 if (self->accessSemantics() == AccessSemantics::Sequence
502 && self->internalName().startsWith(u"QQmlListProperty<"_s)) {
503 self->setIsListProperty(
true);
506 const QString baseTypeName = self->baseTypeName();
507 const auto baseType = findType(baseTypeName, context, usedTypes);
508 if (!self->m_baseType.scope && !baseTypeName.isEmpty())
509 self->m_baseType = { baseType.scope, baseType.revision };
511 if (!self->m_attachedType && !self->m_attachedTypeName.isEmpty())
512 self->m_attachedType = findType(self->m_attachedTypeName, context, usedTypes).scope;
514 if (!self->m_elementType && !self->m_elementTypeName.isEmpty())
515 self->m_elementType = findType(self->m_elementTypeName, context, usedTypes).scope;
517 if (!self->m_extensionType) {
518 if (self->m_extensionTypeName.isEmpty()) {
519 if (self->accessSemantics() == AccessSemantics::Sequence) {
521 self->setExtensionTypeName(u"Array"_s);
522 self->setExtensionIsJavaScript(
true);
523 self->m_extensionType = context.arrayType();
526 self->m_extensionType = findType(self->m_extensionTypeName, context, usedTypes).scope;
531 for (
auto it = self->m_properties.begin(), end = self->m_properties.end(); it != end; ++it) {
532 const QString typeName = it->typeName();
533 if (it->type() || typeName.isEmpty())
536 if (
const auto type = findType(typeName, context, usedTypes); type.scope) {
537 it->setType(it->isList() ? type.scope->listType() : type.scope);
541 const auto enumeration = self->m_enumerations.find(typeName);
542 if (enumeration != self->m_enumerations.end()) {
543 it->setType(it->isList()
544 ? enumeration->type()->listType()
545 : QQmlJSScope::ConstPtr(enumeration->type()));
549 const auto resolveParameter = [&](QQmlJSMetaParameter ¶meter) {
550 if (
const QString typeName = parameter.typeName();
551 !parameter.type() && !typeName.isEmpty()) {
552 auto type = findType(typeName, context, usedTypes);
553 if (type.scope && parameter.isList()) {
554 type.scope = type.scope->listType();
555 parameter.setIsList(
false);
556 parameter.setIsPointer(
false);
557 parameter.setTypeName(type.scope ? type.scope->internalName() : QString());
558 }
else if (type.scope && type.scope->isReferenceType()) {
559 parameter.setIsPointer(
true);
561 parameter.setType({ type.scope });
565 for (
auto it = self->m_methods.begin(), end = self->m_methods.end(); it != end; ++it) {
566 auto returnValue = it->returnValue();
567 resolveParameter(returnValue);
568 it->setReturnValue(returnValue);
570 auto parameters = it->parameters();
571 for (
int i = 0, length = parameters.size(); i < length; ++i)
572 resolveParameter(parameters[i]);
573 it->setParameters(parameters);
576 for (
auto it = self->m_jsIdentifiers.begin(); it != self->m_jsIdentifiers.end(); ++it) {
578 it->scope = findType(it->typeName.value(), context, usedTypes).scope;
581 return baseType.revision;
584void QQmlJSScope::updateChildScope(
585 const QQmlJSScope::Ptr &childScope,
const QQmlJSScope::Ptr &self,
586 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
588 switch (childScope->scopeType()) {
589 case QQmlSA::ScopeType::GroupedPropertyScope:
590 QQmlJSUtils::searchBaseAndExtensionTypes(
591 self.data(), [&](
const QQmlJSScope *type, QQmlJSScope::ExtensionKind mode) {
592 if (mode == QQmlJSScope::ExtensionNamespace)
594 const auto propertyIt = type->m_properties.find(childScope->internalName());
595 if (propertyIt != type->m_properties.end()) {
596 childScope->m_baseType.scope = QQmlJSScope::ConstPtr(propertyIt->type());
597 if (propertyIt->type())
598 childScope->m_semantics = propertyIt->type()->accessSemantics();
599 childScope->setBaseTypeName(propertyIt->typeName());
605 case QQmlSA::ScopeType::AttachedPropertyScope:
606 if (
const auto attachedBase = findType(
607 childScope->internalName(), contextualTypes, usedTypes).scope) {
608 childScope->m_baseType.scope = attachedBase->attachedType();
609 childScope->setBaseTypeName(attachedBase->attachedTypeName());
617template<
typename Resolver,
typename ChildScopeUpdater>
619 Resolver resolve, ChildScopeUpdater update,
const QQmlJSScope::Ptr &self,
622 const QTypeRevision revision = resolve(self, contextualTypes, usedTypes);
624 const auto childScopes = self->childScopes();
625 for (
auto it = childScopes.begin(), end = childScopes.end(); it != end; ++it) {
626 const auto childScope = *it;
627 update(childScope, self, contextualTypes, usedTypes);
628 resolveTypesInternal(resolve, update, childScope, contextualTypes, usedTypes);
633QTypeRevision QQmlJSScope::resolveTypes(
634 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
635 QSet<QString> *usedTypes)
637 const auto resolveAll = [](
const QQmlJSScope::Ptr &self,
638 const QQmlJS::ContextualTypes &contextualTypes,
639 QSet<QString> *usedTypes) {
640 resolveEnums(self, contextualTypes, usedTypes);
641 resolveList(self, contextualTypes.arrayType());
642 return resolveType(self, contextualTypes, usedTypes);
644 return resolveTypesInternal(resolveAll, updateChildScope, self, contextualTypes, usedTypes);
647void QQmlJSScope::resolveNonEnumTypes(
648 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
649 QSet<QString> *usedTypes)
651 resolveTypesInternal(resolveType, updateChildScope, self, contextualTypes, usedTypes);
658 if (underlyingType == u"uint"
659 || underlyingType == u"quint8"
660 || underlyingType == u"ushort"
661 || underlyingType == u"ulonglong") {
665 if (underlyingType == u"int"
666 || underlyingType == u"qint8"
667 || underlyingType == u"short"
668 || underlyingType == u"longlong") {
678
679
680
681
682
683
684
685
686
687
688void QQmlJSScope::resolveEnums(
689 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
690 QSet<QString> *usedTypes)
693 QHash<QString, QQmlJSMetaEnum> toBeAppended;
694 for (
auto it = self->m_enumerations.begin(), end = self->m_enumerations.end(); it != end; ++it) {
697 QQmlJSScope::Ptr enumScope = QQmlJSScope::create();
698 reparent(self, enumScope);
699 enumScope->m_scopeType = QQmlSA::ScopeType::EnumScope;
701 QString typeName = it->typeName();
702 if (typeName.isEmpty())
703 typeName = QStringLiteral(
"int");
704 else if (it->isFlag())
705 typeName = flagStorage(typeName);
706 enumScope->setBaseTypeName(typeName);
707 const auto type = findType(typeName, contextualTypes, usedTypes);
708 enumScope->m_baseType = { type.scope, type.revision };
710 enumScope->m_semantics = AccessSemantics::Value;
711 enumScope->m_internalName = self->internalName() + QStringLiteral(
"::") + it->name();
712 resolveList(enumScope, contextualTypes.arrayType());
713 if (QString alias = it->alias(); !alias.isEmpty()
714 && self->m_enumerations.constFind(alias) == self->m_enumerations.constEnd()) {
715 auto aliasScope = QQmlJSScope::create();
716 *aliasScope = *enumScope;
717 reparent(self, aliasScope);
718 aliasScope->m_internalName = self->internalName() + QStringLiteral(
"::") + alias;
719 QQmlJSMetaEnum cpy(*it);
720 cpy.setType(QQmlJSScope::ConstPtr(aliasScope));
721 toBeAppended.insert(alias, cpy);
723 it->setType(QQmlJSScope::ConstPtr(enumScope));
726 self->m_enumerations.insert(toBeAppended);
729void QQmlJSScope::resolveList(
const QQmlJSScope::Ptr &self,
const QQmlJSScope::ConstPtr &arrayType)
731 if (self->listType() || self->accessSemantics() == AccessSemantics::Sequence)
734 Q_ASSERT(!arrayType.isNull());
735 QQmlJSScope::Ptr listType = QQmlJSScope::create();
736 listType->setAccessSemantics(AccessSemantics::Sequence);
737 listType->setElementTypeName(self->internalName());
739 if (self->isComposite()) {
741 listType->setInternalName(u"QQmlListProperty<>"_s);
742 listType->m_elementType = QQmlJSScope::ConstPtr(self);
743 }
else if (self->isReferenceType()) {
744 listType->setInternalName(u"QQmlListProperty<%2>"_s.arg(self->internalName()));
748 listType->setInternalName(u"QList<%2>"_s.arg(self->internalName()));
749 listType->setFilePath(self->filePath());
752 const QQmlJS::ContextualType element = { self, QTypeRevision(),
753 quint8(QQmlJS::PrecedenceValues::Default) };
754 const QQmlJSImportedScope array = {arrayType, QTypeRevision()};
755 QQmlJS::ContextualTypes contextualTypes(
756 QQmlJS::ContextualTypes::INTERNAL,
757 { { self->internalName(), element }, },
758 { { self, self->internalName() }, },
760 QQmlJSScope::resolveTypes(listType, contextualTypes);
762 Q_ASSERT(listType->elementType() == self);
763 self->m_listType = listType;
766void QQmlJSScope::resolveGroup(
767 const Ptr &self,
const ConstPtr &baseType,
768 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
773 Q_ASSERT(self->isComposite());
775 self->m_baseType.scope = baseType;
776 self->m_semantics = baseType->accessSemantics();
777 resolveNonEnumTypes(self, contextualTypes, usedTypes);
780QQmlJSScope::ConstPtr QQmlJSScope::findCurrentQMLScope(
const QQmlJSScope::ConstPtr &scope)
782 auto qmlScope = scope;
783 while (qmlScope && qmlScope->m_scopeType != QQmlSA::ScopeType::QMLScope)
784 qmlScope = qmlScope->parentScope();
788bool QQmlJSScope::hasProperty(
const QString &name)
const
790 return QQmlJSUtils::searchBaseAndExtensionTypes(
791 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
792 if (mode == QQmlJSScope::ExtensionNamespace)
794 return scope->m_properties.contains(name);
798QQmlJSMetaProperty QQmlJSScope::property(
const QString &name)
const
800 QQmlJSMetaProperty prop;
801 QQmlJSUtils::searchBaseAndExtensionTypes(
802 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
803 if (mode == QQmlJSScope::ExtensionNamespace)
805 const auto it = scope->m_properties.find(name);
806 if (it == scope->m_properties.end())
815
816
817
818
819
820
821QHash<QString, QQmlJSMetaProperty> QQmlJSScope::properties()
const
823 QHash<QString, QQmlJSMetaProperty> results;
824 QQmlJSUtils::searchBaseAndExtensionTypes(
825 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
826 if (mode == QQmlJSScope::ExtensionNamespace)
828 for (
auto it = scope->m_properties.constBegin();
829 it != scope->m_properties.constEnd(); it++) {
830 if (!results.contains(it.key()))
831 results.insert(it.key(), it.value());
838template <
typename Predicate>
841 QQmlJSScope::AnnotatedScope owner;
843 self, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
844 if (mode == QQmlJSScope::ExtensionNamespace)
847 owner = { scope, mode };
855QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfProperty(
const QQmlJSScope::ConstPtr &self,
858 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
859 return scope->hasOwnProperty(name);
863QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfMethod(
const QQmlJSScope::ConstPtr &self,
866 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
867 return scope->hasOwnMethod(name);
871QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfEnum(
const QQmlJSScope::ConstPtr &self,
874 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
875 return scope->hasOwnEnumeration(name);
879void QQmlJSScope::setPropertyLocallyRequired(
const QString &name,
bool isRequired)
882 m_requiredPropertyNames.removeOne(name);
883 else if (!m_requiredPropertyNames.contains(name))
884 m_requiredPropertyNames.append(name);
887bool QQmlJSScope::isPropertyRequired(
const QString &name)
const
889 bool isRequired =
false;
890 QQmlJSUtils::searchBaseAndExtensionTypes(
891 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
892 if (scope->isPropertyLocallyRequired(name)) {
899 if (mode == QQmlJSScope::ExtensionNamespace)
905 return scope->hasOwnProperty(name);
910bool QQmlJSScope::isPropertyLocallyRequired(
const QString &name)
const
912 return m_requiredPropertyNames.contains(name);
915void QQmlJSScope::addOwnPropertyBinding(
const QQmlJSMetaPropertyBinding &binding, BindingTargetSpecifier specifier)
917 Q_ASSERT(binding.sourceLocation().isValid());
918 m_propertyBindings.insert(binding.propertyName(), binding);
922 using iter =
typename QMultiHash<QString, QQmlJSMetaPropertyBinding>::iterator;
923 std::pair<iter, iter> r = m_propertyBindings.equal_range(binding.propertyName());
924 std::rotate(r.first, std::next(r.first), r.second);
927 addOwnPropertyBindingInQmlIROrder(binding, specifier);
928 Q_ASSERT(m_propertyBindings.size() == m_propertyBindingsArray.size());
931void QQmlJSScope::addOwnPropertyBindingInQmlIROrder(
const QQmlJSMetaPropertyBinding &binding,
932 BindingTargetSpecifier specifier)
941 static_assert(QTypeInfo<QQmlJSScope::QmlIRCompatibilityBindingData>::isRelocatable,
942 "We really want T to be relocatable as it improves QList<T> performance");
945 case BindingTargetSpecifier::SimplePropertyTarget: {
946 m_propertyBindingsArray.emplaceFront(binding.propertyName(),
947 binding.sourceLocation().offset);
950 case BindingTargetSpecifier::ListPropertyTarget: {
951 const auto bindingOnTheSameProperty =
952 [&](
const QQmlJSScope::QmlIRCompatibilityBindingData &x) {
953 return x.propertyName == binding.propertyName();
959 auto pos = std::find_if_not(m_propertyBindingsArray.begin(), m_propertyBindingsArray.end(),
960 bindingOnTheSameProperty);
961 Q_ASSERT(pos == m_propertyBindingsArray.begin()
962 || std::prev(pos)->propertyName == binding.propertyName());
963 m_propertyBindingsArray.emplace(pos, binding.propertyName(),
964 binding.sourceLocation().offset);
967 case BindingTargetSpecifier::UnnamedPropertyTarget: {
970 m_propertyBindingsArray.emplaceBack(
971 binding.propertyName(), binding.sourceLocation().offset);
981QList<QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindingsInQmlIROrder()
const
983 QList<QQmlJSMetaPropertyBinding> qmlIrOrdered;
984 qmlIrOrdered.reserve(m_propertyBindingsArray.size());
986 for (
const auto &data : m_propertyBindingsArray) {
987 const auto [first, last] = m_propertyBindings.equal_range(data.propertyName);
988 Q_ASSERT(first != last);
989 auto binding = std::find_if(first, last, [&](
const QQmlJSMetaPropertyBinding &x) {
990 return x.sourceLocation().offset == data.sourceLocationOffset;
992 Q_ASSERT(binding != last);
993 qmlIrOrdered.append(*binding);
999bool QQmlJSScope::hasPropertyBindings(
const QString &name)
const
1001 return QQmlJSUtils::searchBaseAndExtensionTypes(
1002 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1003 if (mode != QQmlJSScope::NotExtension) {
1004 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
1007 return scope->hasOwnPropertyBindings(name);
1011QList<QQmlJSMetaPropertyBinding> QQmlJSScope::propertyBindings(
const QString &name)
const
1013 QList<QQmlJSMetaPropertyBinding> bindings;
1014 QQmlJSUtils::searchBaseAndExtensionTypes(
1015 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1016 if (mode != QQmlJSScope::NotExtension) {
1017 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
1020 const auto range = scope->ownPropertyBindings(name);
1021 for (
auto it = range.first; it != range.second; ++it)
1022 bindings.append(*it);
1028bool QQmlJSScope::hasInterface(
const QString &name)
const
1030 return QQmlJSUtils::searchBaseAndExtensionTypes(
1031 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1032 if (mode != QQmlJSScope::NotExtension)
1034 return scope->m_interfaceNames.contains(name);
1038bool QQmlJSScope::isNameDeferred(
const QString &name)
const
1040 bool isDeferred =
false;
1042 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1043 const QStringList immediate = scope->ownImmediateNames();
1044 if (!immediate.isEmpty()) {
1045 isDeferred = !immediate.contains(name);
1048 const QStringList deferred = scope->ownDeferredNames();
1049 if (!deferred.isEmpty()) {
1050 isDeferred = deferred.contains(name);
1059void QQmlJSScope::setBaseTypeName(
const QString &baseTypeName)
1061 m_flags.setFlag(HasBaseTypeError,
false);
1062 m_baseTypeNameOrError = baseTypeName;
1065QString QQmlJSScope::baseTypeName()
const
1067 return m_flags.testFlag(HasBaseTypeError) ? QString() : m_baseTypeNameOrError;
1070void QQmlJSScope::setBaseTypeError(
const QString &baseTypeError)
1072 m_flags.setFlag(HasBaseTypeError);
1073 m_baseTypeNameOrError = baseTypeError;
1077
1078
1079
1080
1081
1082QString QQmlJSScope::moduleName()
const
1084 for (
const QQmlJSScope *it =
this; it; it = it->parentScope().get()) {
1085 const QString name = it->ownModuleName();
1086 if (!name.isEmpty())
1092QString QQmlJSScope::baseTypeError()
const
1094 return m_flags.testFlag(HasBaseTypeError) ? m_baseTypeNameOrError : QString();
1097QString QQmlJSScope::attachedTypeName()
const
1100 QQmlJSUtils::searchBaseAndExtensionTypes(
1101 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1102 if (mode != QQmlJSScope::NotExtension)
1104 if (scope->ownAttachedType().isNull())
1106 name = scope->ownAttachedTypeName();
1113QQmlJSScope::ConstPtr QQmlJSScope::attachedType()
const
1115 QQmlJSScope::ConstPtr ptr;
1116 QQmlJSUtils::searchBaseAndExtensionTypes(
1117 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1118 if (mode != QQmlJSScope::NotExtension)
1120 if (scope->ownAttachedType().isNull())
1122 ptr = scope->ownAttachedType();
1129QQmlJSScope::AnnotatedScope QQmlJSScope::extensionType()
const
1131 if (!m_extensionType)
1132 return { m_extensionType, NotExtension };
1133 if (m_flags & ExtensionIsJavaScript)
1134 return { m_extensionType, ExtensionJavaScript };
1135 if (m_flags & ExtensionIsNamespace)
1136 return { m_extensionType, ExtensionNamespace };
1137 return { m_extensionType, ExtensionType };
1140void QQmlJSScope::addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index)
1142 m_runtimeFunctionIndices.emplaceBack(index);
1145bool QQmlJSScope::isResolved()
const
1147 const bool nameIsEmpty = (m_scopeType == ScopeType::AttachedPropertyScope
1148 || m_scopeType == ScopeType::GroupedPropertyScope)
1149 ? m_internalName.isEmpty()
1150 : m_baseTypeNameOrError.isEmpty();
1153 if (m_baseType.scope.isNull())
1155 if (isComposite() && !nonCompositeBaseType(baseType()))
1160QString QQmlJSScope::defaultPropertyName()
const
1163 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1164 name = scope->ownDefaultPropertyName();
1165 return !name.isEmpty();
1170QString QQmlJSScope::parentPropertyName()
const
1173 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1174 name = scope->ownParentPropertyName();
1175 return !name.isEmpty();
1180bool QQmlJSScope::isFullyResolved()
const
1182 bool baseResolved =
true;
1183 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1184 if (!scope->isResolved()) {
1185 baseResolved =
false;
1191 return baseResolved;
1194QQmlJSScope::Export::Export(
1195 QString package, QString type, QTypeRevision version, QTypeRevision revision)
1196 : m_package(std::move(package))
1197 , m_type(std::move(type))
1198 , m_version(std::move(version))
1199 , m_revision(std::move(revision))
1203bool QQmlJSScope::Export::isValid()
const
1205 return m_version.isValid() || !m_package.isEmpty() || !m_type.isEmpty();
1208QDeferredFactory<QQmlJSScope>::QDeferredFactory(QQmlJSImporter *importer,
1209 const QQmlJS::TypeReader &typeReader,
1210 const QString &filePath,
const QString &moduleName,
1212 : m_importer(importer),
1213 m_typeReader(typeReader ? typeReader : QQmlJS::TypeReader{ QQmlJS::defaultTypeReader }),
1214 m_filePath(filePath),
1215 m_moduleName(moduleName),
1216 m_isSingleton(isSingleton)
1220void QDeferredFactory<QQmlJSScope>::populate(
const QSharedPointer<QQmlJSScope> &scope)
const
1222 scope->setOwnModuleName(m_moduleName);
1223 scope->setIsSingleton(m_isSingleton);
1225 m_typeReader(m_importer, m_filePath, scope);
1229
1230
1231
1232
1233
1234
1235
1236
1237bool QQmlJSScope::canAssign(
const QQmlJSScope::ConstPtr &derived)
const
1243 Q_ASSERT(!isComposite() || nonCompositeBaseType(baseType()));
1244 Q_ASSERT(nonCompositeBaseType(derived));
1248 const bool isBaseComponent = [
this]() {
1249 if (internalName() == u"QQmlComponent")
1251 else if (isComposite())
1253 for (
auto cppBase = nonCompositeBaseType(baseType()); cppBase;
1254 cppBase = cppBase->baseType()) {
1255 if (cppBase->internalName() == u"QQmlAbstractDelegateComponent")
1261 QDuplicateTracker<QQmlJSScope::ConstPtr> seen;
1262 for (
auto scope = derived; !scope.isNull() && !seen.hasSeen(scope);
1263 scope = scope->baseType()) {
1264 if (isSameType(scope))
1266 if (isBaseComponent && scope->internalName() == u"QObject"_s)
1270 if (internalName() == u"QVariant"_s || internalName() == u"QJSValue"_s)
1273 return isListProperty() && elementType()->canAssign(derived);
1277
1278
1279
1280bool QQmlJSScope::isInCustomParserParent()
const
1282 for (
const auto *scope =
this; scope; scope = scope->parentScope().get()) {
1283 if (!scope->baseType().isNull() && scope->baseType()->hasCustomParser())
1291
1292
1293
1294
1295std::optional<QString> QQmlJSScope::inlineComponentName()
const
1297 Q_ASSERT(isInlineComponent() == m_inlineComponentName.has_value());
1298 return m_inlineComponentName;
1302
1303
1304
1305
1306QQmlJSScope::InlineComponentOrDocumentRootName QQmlJSScope::enclosingInlineComponentName()
const
1308 for (
auto *type =
this; type; type = type->parentScope().get()) {
1309 if (type->isInlineComponent())
1310 return *type->inlineComponentName();
1312 return RootDocumentNameType();
1315QList<QQmlJSScope::ConstPtr> QQmlJSScope::childScopes()
const
1317 QList<QQmlJSScope::ConstPtr> result;
1318 result.reserve(m_childScopes.size());
1319 for (
const auto &child : m_childScopes)
1320 result.append(child);
1325
1326
1327
1328
1329
1330
1331bool QQmlJSScope::enforcesScopedEnums()
const
1333 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1334 if (scope->hasEnforcesScopedEnumsFlag())
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355bool QQmlJSScope::isCreatable()
const
1357 auto isCreatableNonRecursive = [](
const QQmlJSScope *scope) {
1358 return scope->hasCreatableFlag() && !scope->isSingleton()
1359 && scope->scopeType() == QQmlSA::ScopeType::QMLScope;
1362 for (
const QQmlJSScope* scope =
this; scope; scope = scope->baseType().get()) {
1363 if (!scope->isComposite()) {
1365 return isCreatableNonRecursive(scope);
1368 if (isCreatableNonRecursive(scope))
1376bool QQmlJSScope::isStructured()
const
1378 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1379 if (!scope->isComposite())
1380 return scope->hasStructuredFlag();
1385QQmlSA::Element QQmlJSScope::createQQmlSAElement(
const ConstPtr &ptr)
1387 QQmlSA::Element element;
1388 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = ptr;
1392QQmlSA::Element QQmlJSScope::createQQmlSAElement(ConstPtr &&ptr)
1394 QQmlSA::Element element;
1395 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = std::move(ptr);
1399const QQmlJSScope::ConstPtr &QQmlJSScope::scope(
const QQmlSA::Element &element)
1401 return *
reinterpret_cast<
const QQmlJSScope::ConstPtr *>(element.m_data);
1405QQmlJSScope::nonCompositeBaseRevision(
const ImportedScope<QQmlJSScope::ConstPtr> &scope)
1407 for (
auto base = scope; base.scope;
1408 base = { base.scope->m_baseType.scope, base.scope->m_baseType.revision }) {
1409 if (!base.scope->isComposite())
1410 return base.revision;
1416
1417
1418
1419
1420
1421
1422bool QQmlJSScope::isSameType(
const ConstPtr &otherScope)
const
1424 return this == otherScope.get()
1425 || (!
this->internalName().isEmpty()
1426 &&
this->internalName() == otherScope->internalName());
1429bool QQmlJSScope::inherits(
const ConstPtr &base)
const
1431 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1432 if (scope->isSameType(base))
static QQmlJSScope::ImportedScope< QQmlJSScope::ConstPtr > qFindInlineComponents(QStringView typeName, const QQmlJS::ContextualTypes &contextualTypes)
QQmlJSScope::AnnotatedScope searchOwner(const QQmlJSScope::ConstPtr &self, Predicate &&p)
static QString flagStorage(const QString &underlyingType)
static QTypeRevision resolveTypesInternal(Resolver resolve, ChildScopeUpdater update, const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, QSet< QString > *usedTypes)