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);
407 if (type != contextualTypes.types().constEnd()) {
412 const auto findListType = [&](
const QString &prefix,
const QString &postfix)
413 -> ImportedScope<ConstPtr> {
414 if (name.startsWith(prefix) && name.endsWith(postfix)) {
415 const qsizetype prefixLength = prefix.length();
416 const QString &elementName
417 = name.mid(prefixLength, name.length() - prefixLength - postfix.length());
418 const ImportedScope<ConstPtr> element
419 = findType(elementName, contextualTypes, usedTypes);
422 return { element.scope->listType(), element.revision };
429 switch (contextualTypes.context()) {
430 case QQmlJS::ContextualTypes::INTERNAL: {
431 if (
const auto listType = findListType(u"QList<"_s, u">"_s);
432 listType.scope && !listType.scope->isReferenceType()) {
436 if (
const auto listType = findListType(u"QQmlListProperty<"_s, u">"_s);
437 listType.scope && listType.scope->isReferenceType()) {
442 const auto colonColon = name.lastIndexOf(QStringLiteral(
"::"));
443 if (colonColon == -1)
446 const QString outerTypeName = name.left(colonColon);
447 const auto outerType = contextualTypes.types().constFind(outerTypeName);
448 if (outerType == contextualTypes.types().constEnd())
451 for (
const auto &innerType : std::as_const(outerType->scope->m_childScopes)) {
452 if (innerType->m_internalName == name) {
454 return { innerType, outerType->revision };
460 case QQmlJS::ContextualTypes::QML: {
462 const auto inlineComponent = qFindInlineComponents(name, contextualTypes);
463 if (inlineComponent.scope) {
465 return inlineComponent;
468 if (
const auto listType = findListType(u"list<"_s, u">"_s); listType.scope)
477QTypeRevision QQmlJSScope::resolveType(
478 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &context,
479 QSet<QString> *usedTypes)
481 if (self->accessSemantics() == AccessSemantics::Sequence
482 && self->internalName().startsWith(u"QQmlListProperty<"_s)) {
483 self->setIsListProperty(
true);
486 const QString baseTypeName = self->baseTypeName();
487 const auto baseType = findType(baseTypeName, context, usedTypes);
488 if (!self->m_baseType.scope && !baseTypeName.isEmpty())
489 self->m_baseType = { baseType.scope, baseType.revision };
491 if (!self->m_attachedType && !self->m_attachedTypeName.isEmpty())
492 self->m_attachedType = findType(self->m_attachedTypeName, context, usedTypes).scope;
494 if (!self->m_elementType && !self->m_elementTypeName.isEmpty())
495 self->m_elementType = findType(self->m_elementTypeName, context, usedTypes).scope;
497 if (!self->m_extensionType) {
498 if (self->m_extensionTypeName.isEmpty()) {
499 if (self->accessSemantics() == AccessSemantics::Sequence) {
501 self->setExtensionTypeName(u"Array"_s);
502 self->setExtensionIsJavaScript(
true);
503 self->m_extensionType = context.arrayType();
506 self->m_extensionType = findType(self->m_extensionTypeName, context, usedTypes).scope;
511 for (
auto it = self->m_properties.begin(), end = self->m_properties.end(); it != end; ++it) {
512 const QString typeName = it->typeName();
513 if (it->type() || typeName.isEmpty())
516 if (
const auto type = findType(typeName, context, usedTypes); type.scope) {
517 it->setType(it->isList() ? type.scope->listType() : type.scope);
521 const auto enumeration = self->m_enumerations.find(typeName);
522 if (enumeration != self->m_enumerations.end()) {
523 it->setType(it->isList()
524 ? enumeration->type()->listType()
525 : QQmlJSScope::ConstPtr(enumeration->type()));
529 const auto resolveParameter = [&](QQmlJSMetaParameter ¶meter) {
530 if (
const QString typeName = parameter.typeName();
531 !parameter.type() && !typeName.isEmpty()) {
532 auto type = findType(typeName, context, usedTypes);
533 if (type.scope && parameter.isList()) {
534 type.scope = type.scope->listType();
535 parameter.setIsList(
false);
536 parameter.setIsPointer(
false);
537 parameter.setTypeName(type.scope ? type.scope->internalName() : QString());
538 }
else if (type.scope && type.scope->isReferenceType()) {
539 parameter.setIsPointer(
true);
541 parameter.setType({ type.scope });
545 for (
auto it = self->m_methods.begin(), end = self->m_methods.end(); it != end; ++it) {
546 auto returnValue = it->returnValue();
547 resolveParameter(returnValue);
548 it->setReturnValue(returnValue);
550 auto parameters = it->parameters();
551 for (
int i = 0, length = parameters.size(); i < length; ++i)
552 resolveParameter(parameters[i]);
553 it->setParameters(parameters);
556 for (
auto it = self->m_jsIdentifiers.begin(); it != self->m_jsIdentifiers.end(); ++it) {
558 it->scope = findType(it->typeName.value(), context, usedTypes).scope;
561 return baseType.revision;
564void QQmlJSScope::updateChildScope(
565 const QQmlJSScope::Ptr &childScope,
const QQmlJSScope::Ptr &self,
566 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
568 switch (childScope->scopeType()) {
569 case QQmlSA::ScopeType::GroupedPropertyScope:
570 QQmlJSUtils::searchBaseAndExtensionTypes(
571 self.data(), [&](
const QQmlJSScope *type, QQmlJSScope::ExtensionKind mode) {
572 if (mode == QQmlJSScope::ExtensionNamespace)
574 const auto propertyIt = type->m_properties.find(childScope->internalName());
575 if (propertyIt != type->m_properties.end()) {
576 childScope->m_baseType.scope = QQmlJSScope::ConstPtr(propertyIt->type());
577 if (propertyIt->type())
578 childScope->m_semantics = propertyIt->type()->accessSemantics();
579 childScope->setBaseTypeName(propertyIt->typeName());
585 case QQmlSA::ScopeType::AttachedPropertyScope:
586 if (
const auto attachedBase = findType(
587 childScope->internalName(), contextualTypes, usedTypes).scope) {
588 childScope->m_baseType.scope = attachedBase->attachedType();
589 childScope->setBaseTypeName(attachedBase->attachedTypeName());
597template<
typename Resolver,
typename ChildScopeUpdater>
599 Resolver resolve, ChildScopeUpdater update,
const QQmlJSScope::Ptr &self,
602 const QTypeRevision revision = resolve(self, contextualTypes, usedTypes);
604 const auto childScopes = self->childScopes();
605 for (
auto it = childScopes.begin(), end = childScopes.end(); it != end; ++it) {
606 const auto childScope = *it;
607 update(childScope, self, contextualTypes, usedTypes);
608 resolveTypesInternal(resolve, update, childScope, contextualTypes, usedTypes);
613QTypeRevision QQmlJSScope::resolveTypes(
614 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
615 QSet<QString> *usedTypes)
617 const auto resolveAll = [](
const QQmlJSScope::Ptr &self,
618 const QQmlJS::ContextualTypes &contextualTypes,
619 QSet<QString> *usedTypes) {
620 resolveEnums(self, contextualTypes, usedTypes);
621 resolveList(self, contextualTypes.arrayType());
622 return resolveType(self, contextualTypes, usedTypes);
624 return resolveTypesInternal(resolveAll, updateChildScope, self, contextualTypes, usedTypes);
627void QQmlJSScope::resolveNonEnumTypes(
628 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
629 QSet<QString> *usedTypes)
631 resolveTypesInternal(resolveType, updateChildScope, self, contextualTypes, usedTypes);
638 if (underlyingType == u"uint"
639 || underlyingType == u"quint8"
640 || underlyingType == u"ushort"
641 || underlyingType == u"ulonglong") {
645 if (underlyingType == u"int"
646 || underlyingType == u"qint8"
647 || underlyingType == u"short"
648 || underlyingType == u"longlong") {
658
659
660
661
662
663
664
665
666
667
668void QQmlJSScope::resolveEnums(
669 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
670 QSet<QString> *usedTypes)
673 QHash<QString, QQmlJSMetaEnum> toBeAppended;
674 for (
auto it = self->m_enumerations.begin(), end = self->m_enumerations.end(); it != end; ++it) {
677 QQmlJSScope::Ptr enumScope = QQmlJSScope::create();
678 reparent(self, enumScope);
679 enumScope->m_scopeType = QQmlSA::ScopeType::EnumScope;
681 QString typeName = it->typeName();
682 if (typeName.isEmpty())
683 typeName = QStringLiteral(
"int");
684 else if (it->isFlag())
685 typeName = flagStorage(typeName);
686 enumScope->setBaseTypeName(typeName);
687 const auto type = findType(typeName, contextualTypes, usedTypes);
688 enumScope->m_baseType = { type.scope, type.revision };
690 enumScope->m_semantics = AccessSemantics::Value;
691 enumScope->m_internalName = self->internalName() + QStringLiteral(
"::") + it->name();
692 resolveList(enumScope, contextualTypes.arrayType());
693 if (QString alias = it->alias(); !alias.isEmpty()
694 && self->m_enumerations.constFind(alias) == self->m_enumerations.constEnd()) {
695 auto aliasScope = QQmlJSScope::create();
696 *aliasScope = *enumScope;
697 reparent(self, aliasScope);
698 aliasScope->m_internalName = self->internalName() + QStringLiteral(
"::") + alias;
699 QQmlJSMetaEnum cpy(*it);
700 cpy.setType(QQmlJSScope::ConstPtr(aliasScope));
701 toBeAppended.insert(alias, cpy);
703 it->setType(QQmlJSScope::ConstPtr(enumScope));
706 self->m_enumerations.insert(toBeAppended);
709void QQmlJSScope::resolveList(
const QQmlJSScope::Ptr &self,
const QQmlJSScope::ConstPtr &arrayType)
711 if (self->listType() || self->accessSemantics() == AccessSemantics::Sequence)
714 Q_ASSERT(!arrayType.isNull());
715 QQmlJSScope::Ptr listType = QQmlJSScope::create();
716 listType->setAccessSemantics(AccessSemantics::Sequence);
717 listType->setElementTypeName(self->internalName());
719 if (self->isComposite()) {
721 listType->setInternalName(u"QQmlListProperty<>"_s);
722 listType->m_elementType = QQmlJSScope::ConstPtr(self);
723 }
else if (self->isReferenceType()) {
724 listType->setInternalName(u"QQmlListProperty<%2>"_s.arg(self->internalName()));
728 listType->setInternalName(u"QList<%2>"_s.arg(self->internalName()));
729 listType->setFilePath(self->filePath());
732 const QQmlJS::ContextualType element = { self, QTypeRevision(),
733 quint8(QQmlJS::PrecedenceValues::Default) };
734 const QQmlJSImportedScope array = {arrayType, QTypeRevision()};
735 QQmlJS::ContextualTypes contextualTypes(
736 QQmlJS::ContextualTypes::INTERNAL,
737 { { self->internalName(), element }, },
738 { { self, self->internalName() }, },
740 QQmlJSScope::resolveTypes(listType, contextualTypes);
742 Q_ASSERT(listType->elementType() == self);
743 self->m_listType = listType;
746void QQmlJSScope::resolveGroup(
747 const Ptr &self,
const ConstPtr &baseType,
748 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
753 Q_ASSERT(self->isComposite());
755 self->m_baseType.scope = baseType;
756 self->m_semantics = baseType->accessSemantics();
757 resolveNonEnumTypes(self, contextualTypes, usedTypes);
760QQmlJSScope::ConstPtr QQmlJSScope::findCurrentQMLScope(
const QQmlJSScope::ConstPtr &scope)
762 auto qmlScope = scope;
763 while (qmlScope && qmlScope->m_scopeType != QQmlSA::ScopeType::QMLScope)
764 qmlScope = qmlScope->parentScope();
768bool QQmlJSScope::hasProperty(
const QString &name)
const
770 return QQmlJSUtils::searchBaseAndExtensionTypes(
771 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
772 if (mode == QQmlJSScope::ExtensionNamespace)
774 return scope->m_properties.contains(name);
778QQmlJSMetaProperty QQmlJSScope::property(
const QString &name)
const
780 QQmlJSMetaProperty prop;
781 QQmlJSUtils::searchBaseAndExtensionTypes(
782 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
783 if (mode == QQmlJSScope::ExtensionNamespace)
785 const auto it = scope->m_properties.find(name);
786 if (it == scope->m_properties.end())
795
796
797
798
799
800
801QHash<QString, QQmlJSMetaProperty> QQmlJSScope::properties()
const
803 QHash<QString, QQmlJSMetaProperty> results;
804 QQmlJSUtils::searchBaseAndExtensionTypes(
805 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
806 if (mode == QQmlJSScope::ExtensionNamespace)
808 for (
auto it = scope->m_properties.constBegin();
809 it != scope->m_properties.constEnd(); it++) {
810 if (!results.contains(it.key()))
811 results.insert(it.key(), it.value());
818template <
typename Predicate>
821 QQmlJSScope::AnnotatedScope owner;
822 QQmlJSUtils::searchBaseAndExtensionTypes(
823 self, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
824 if (mode == QQmlJSScope::ExtensionNamespace)
827 owner = { scope, mode };
835QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfProperty(
const QQmlJSScope::ConstPtr &self,
838 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
839 return scope->hasOwnProperty(name);
843QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfMethod(
const QQmlJSScope::ConstPtr &self,
846 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
847 return scope->hasOwnMethod(name);
851QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfEnum(
const QQmlJSScope::ConstPtr &self,
854 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
855 return scope->hasOwnEnumeration(name);
859void QQmlJSScope::setPropertyLocallyRequired(
const QString &name,
bool isRequired)
862 m_requiredPropertyNames.removeOne(name);
863 else if (!m_requiredPropertyNames.contains(name))
864 m_requiredPropertyNames.append(name);
867bool QQmlJSScope::isPropertyRequired(
const QString &name)
const
869 bool isRequired =
false;
870 QQmlJSUtils::searchBaseAndExtensionTypes(
871 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
872 if (scope->isPropertyLocallyRequired(name)) {
879 if (mode == QQmlJSScope::ExtensionNamespace)
885 return scope->hasOwnProperty(name);
890bool QQmlJSScope::isPropertyLocallyRequired(
const QString &name)
const
892 return m_requiredPropertyNames.contains(name);
895void QQmlJSScope::addOwnPropertyBinding(
const QQmlJSMetaPropertyBinding &binding, BindingTargetSpecifier specifier)
897 Q_ASSERT(binding.sourceLocation().isValid());
898 m_propertyBindings.insert(binding.propertyName(), binding);
902 using iter =
typename QMultiHash<QString, QQmlJSMetaPropertyBinding>::iterator;
903 std::pair<iter, iter> r = m_propertyBindings.equal_range(binding.propertyName());
904 std::rotate(r.first, std::next(r.first), r.second);
907 addOwnPropertyBindingInQmlIROrder(binding, specifier);
908 Q_ASSERT(m_propertyBindings.size() == m_propertyBindingsArray.size());
911void QQmlJSScope::addOwnPropertyBindingInQmlIROrder(
const QQmlJSMetaPropertyBinding &binding,
912 BindingTargetSpecifier specifier)
921 static_assert(QTypeInfo<QQmlJSScope::QmlIRCompatibilityBindingData>::isRelocatable,
922 "We really want T to be relocatable as it improves QList<T> performance");
925 case BindingTargetSpecifier::SimplePropertyTarget: {
926 m_propertyBindingsArray.emplaceFront(binding.propertyName(),
927 binding.sourceLocation().offset);
930 case BindingTargetSpecifier::ListPropertyTarget: {
931 const auto bindingOnTheSameProperty =
932 [&](
const QQmlJSScope::QmlIRCompatibilityBindingData &x) {
933 return x.propertyName == binding.propertyName();
939 auto pos = std::find_if_not(m_propertyBindingsArray.begin(), m_propertyBindingsArray.end(),
940 bindingOnTheSameProperty);
941 Q_ASSERT(pos == m_propertyBindingsArray.begin()
942 || std::prev(pos)->propertyName == binding.propertyName());
943 m_propertyBindingsArray.emplace(pos, binding.propertyName(),
944 binding.sourceLocation().offset);
947 case BindingTargetSpecifier::UnnamedPropertyTarget: {
950 m_propertyBindingsArray.emplaceBack(
951 binding.propertyName(), binding.sourceLocation().offset);
961QList<QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindingsInQmlIROrder()
const
963 QList<QQmlJSMetaPropertyBinding> qmlIrOrdered;
964 qmlIrOrdered.reserve(m_propertyBindingsArray.size());
966 for (
const auto &data : m_propertyBindingsArray) {
967 const auto [first, last] = m_propertyBindings.equal_range(data.propertyName);
968 Q_ASSERT(first != last);
969 auto binding = std::find_if(first, last, [&](
const QQmlJSMetaPropertyBinding &x) {
970 return x.sourceLocation().offset == data.sourceLocationOffset;
972 Q_ASSERT(binding != last);
973 qmlIrOrdered.append(*binding);
979bool QQmlJSScope::hasPropertyBindings(
const QString &name)
const
981 return QQmlJSUtils::searchBaseAndExtensionTypes(
982 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
983 if (mode != QQmlJSScope::NotExtension) {
984 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
987 return scope->hasOwnPropertyBindings(name);
991QList<QQmlJSMetaPropertyBinding> QQmlJSScope::propertyBindings(
const QString &name)
const
993 QList<QQmlJSMetaPropertyBinding> bindings;
994 QQmlJSUtils::searchBaseAndExtensionTypes(
995 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
996 if (mode != QQmlJSScope::NotExtension) {
997 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
1000 const auto range = scope->ownPropertyBindings(name);
1001 for (
auto it = range.first; it != range.second; ++it)
1002 bindings.append(*it);
1008bool QQmlJSScope::hasInterface(
const QString &name)
const
1010 return QQmlJSUtils::searchBaseAndExtensionTypes(
1011 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1012 if (mode != QQmlJSScope::NotExtension)
1014 return scope->m_interfaceNames.contains(name);
1018bool QQmlJSScope::isNameDeferred(
const QString &name)
const
1020 bool isDeferred =
false;
1022 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1023 const QStringList immediate = scope->ownImmediateNames();
1024 if (!immediate.isEmpty()) {
1025 isDeferred = !immediate.contains(name);
1028 const QStringList deferred = scope->ownDeferredNames();
1029 if (!deferred.isEmpty()) {
1030 isDeferred = deferred.contains(name);
1039void QQmlJSScope::setBaseTypeName(
const QString &baseTypeName)
1041 m_flags.setFlag(HasBaseTypeError,
false);
1042 m_baseTypeNameOrError = baseTypeName;
1045QString QQmlJSScope::baseTypeName()
const
1047 return m_flags.testFlag(HasBaseTypeError) ? QString() : m_baseTypeNameOrError;
1050void QQmlJSScope::setBaseTypeError(
const QString &baseTypeError)
1052 m_flags.setFlag(HasBaseTypeError);
1053 m_baseTypeNameOrError = baseTypeError;
1057
1058
1059
1060
1061
1062QString QQmlJSScope::moduleName()
const
1064 for (
const QQmlJSScope *it =
this; it; it = it->parentScope().get()) {
1065 const QString name = it->ownModuleName();
1066 if (!name.isEmpty())
1072QString QQmlJSScope::baseTypeError()
const
1074 return m_flags.testFlag(HasBaseTypeError) ? m_baseTypeNameOrError : QString();
1077QString QQmlJSScope::attachedTypeName()
const
1080 QQmlJSUtils::searchBaseAndExtensionTypes(
1081 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1082 if (mode != QQmlJSScope::NotExtension)
1084 if (scope->ownAttachedType().isNull())
1086 name = scope->ownAttachedTypeName();
1093QQmlJSScope::ConstPtr QQmlJSScope::attachedType()
const
1095 QQmlJSScope::ConstPtr ptr;
1096 QQmlJSUtils::searchBaseAndExtensionTypes(
1097 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1098 if (mode != QQmlJSScope::NotExtension)
1100 if (scope->ownAttachedType().isNull())
1102 ptr = scope->ownAttachedType();
1109QQmlJSScope::AnnotatedScope QQmlJSScope::extensionType()
const
1111 if (!m_extensionType)
1112 return { m_extensionType, NotExtension };
1113 if (m_flags & ExtensionIsJavaScript)
1114 return { m_extensionType, ExtensionJavaScript };
1115 if (m_flags & ExtensionIsNamespace)
1116 return { m_extensionType, ExtensionNamespace };
1117 return { m_extensionType, ExtensionType };
1120void QQmlJSScope::addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index)
1122 m_runtimeFunctionIndices.emplaceBack(index);
1125bool QQmlJSScope::isResolved()
const
1127 const bool nameIsEmpty = (m_scopeType == ScopeType::AttachedPropertyScope
1128 || m_scopeType == ScopeType::GroupedPropertyScope)
1129 ? m_internalName.isEmpty()
1130 : m_baseTypeNameOrError.isEmpty();
1133 if (m_baseType.scope.isNull())
1135 if (isComposite() && !nonCompositeBaseType(baseType()))
1140QString QQmlJSScope::defaultPropertyName()
const
1143 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1144 name = scope->ownDefaultPropertyName();
1145 return !name.isEmpty();
1150QString QQmlJSScope::parentPropertyName()
const
1153 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1154 name = scope->ownParentPropertyName();
1155 return !name.isEmpty();
1160bool QQmlJSScope::isFullyResolved()
const
1162 bool baseResolved =
true;
1163 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1164 if (!scope->isResolved()) {
1165 baseResolved =
false;
1171 return baseResolved;
1174QQmlJSScope::Export::Export(
1175 QString package, QString type, QTypeRevision version, QTypeRevision revision)
1176 : m_package(std::move(package))
1177 , m_type(std::move(type))
1178 , m_version(std::move(version))
1179 , m_revision(std::move(revision))
1183bool QQmlJSScope::Export::isValid()
const
1185 return m_version.isValid() || !m_package.isEmpty() || !m_type.isEmpty();
1188QDeferredFactory<QQmlJSScope>::QDeferredFactory(QQmlJSImporter *importer,
1189 const QQmlJS::TypeReader &typeReader,
1190 const QString &filePath,
const QString &moduleName,
1192 : m_importer(importer),
1193 m_typeReader(typeReader ? typeReader : QQmlJS::TypeReader{ QQmlJS::defaultTypeReader }),
1194 m_filePath(filePath),
1195 m_moduleName(moduleName),
1196 m_isSingleton(isSingleton)
1200void QDeferredFactory<QQmlJSScope>::populate(
const QSharedPointer<QQmlJSScope> &scope)
const
1202 scope->setOwnModuleName(m_moduleName);
1203 scope->setIsSingleton(m_isSingleton);
1205 m_typeReader(m_importer, m_filePath, scope);
1209
1210
1211
1212
1213
1214
1215
1216
1217bool QQmlJSScope::canAssign(
const QQmlJSScope::ConstPtr &derived)
const
1223 Q_ASSERT(!isComposite() || nonCompositeBaseType(baseType()));
1224 Q_ASSERT(nonCompositeBaseType(derived));
1228 const bool isBaseComponent = [
this]() {
1229 if (internalName() == u"QQmlComponent")
1231 else if (isComposite())
1233 for (
auto cppBase = nonCompositeBaseType(baseType()); cppBase;
1234 cppBase = cppBase->baseType()) {
1235 if (cppBase->internalName() == u"QQmlAbstractDelegateComponent")
1241 QDuplicateTracker<QQmlJSScope::ConstPtr> seen;
1242 for (
auto scope = derived; !scope.isNull() && !seen.hasSeen(scope);
1243 scope = scope->baseType()) {
1244 if (isSameType(scope))
1246 if (isBaseComponent && scope->internalName() == u"QObject"_s)
1250 if (internalName() == u"QVariant"_s || internalName() == u"QJSValue"_s)
1253 return isListProperty() && elementType()->canAssign(derived);
1257
1258
1259
1260bool QQmlJSScope::isInCustomParserParent()
const
1262 for (
const auto *scope =
this; scope; scope = scope->parentScope().get()) {
1263 if (!scope->baseType().isNull() && scope->baseType()->hasCustomParser())
1271
1272
1273
1274
1275std::optional<QString> QQmlJSScope::inlineComponentName()
const
1277 Q_ASSERT(isInlineComponent() == m_inlineComponentName.has_value());
1278 return m_inlineComponentName;
1282
1283
1284
1285
1286QQmlJSScope::InlineComponentOrDocumentRootName QQmlJSScope::enclosingInlineComponentName()
const
1288 for (
auto *type =
this; type; type = type->parentScope().get()) {
1289 if (type->isInlineComponent())
1290 return *type->inlineComponentName();
1292 return RootDocumentNameType();
1295QList<QQmlJSScope::ConstPtr> QQmlJSScope::childScopes()
const
1297 QList<QQmlJSScope::ConstPtr> result;
1298 result.reserve(m_childScopes.size());
1299 for (
const auto &child : m_childScopes)
1300 result.append(child);
1305
1306
1307
1308
1309
1310
1311bool QQmlJSScope::enforcesScopedEnums()
const
1313 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1314 if (scope->hasEnforcesScopedEnumsFlag())
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335bool QQmlJSScope::isCreatable()
const
1337 auto isCreatableNonRecursive = [](
const QQmlJSScope *scope) {
1338 return scope->hasCreatableFlag() && !scope->isSingleton()
1339 && scope->scopeType() == QQmlSA::ScopeType::QMLScope;
1342 for (
const QQmlJSScope* scope =
this; scope; scope = scope->baseType().get()) {
1343 if (!scope->isComposite()) {
1345 return isCreatableNonRecursive(scope);
1348 if (isCreatableNonRecursive(scope))
1356bool QQmlJSScope::isStructured()
const
1358 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1359 if (!scope->isComposite())
1360 return scope->hasStructuredFlag();
1365QQmlSA::Element QQmlJSScope::createQQmlSAElement(
const ConstPtr &ptr)
1367 QQmlSA::Element element;
1368 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = ptr;
1372QQmlSA::Element QQmlJSScope::createQQmlSAElement(ConstPtr &&ptr)
1374 QQmlSA::Element element;
1375 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = std::move(ptr);
1379const QQmlJSScope::ConstPtr &QQmlJSScope::scope(
const QQmlSA::Element &element)
1381 return *
reinterpret_cast<
const QQmlJSScope::ConstPtr *>(element.m_data);
1385QQmlJSScope::nonCompositeBaseRevision(
const ImportedScope<QQmlJSScope::ConstPtr> &scope)
1387 for (
auto base = scope; base.scope;
1388 base = { base.scope->m_baseType.scope, base.scope->m_baseType.revision }) {
1389 if (!base.scope->isComposite())
1390 return base.revision;
1396
1397
1398
1399
1400
1401
1402bool QQmlJSScope::isSameType(
const ConstPtr &otherScope)
const
1404 return this == otherScope.get()
1405 || (!
this->internalName().isEmpty()
1406 &&
this->internalName() == otherScope->internalName());
1409bool QQmlJSScope::inherits(
const ConstPtr &base)
const
1411 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1412 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)