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::insertPropertyIdentifier(
const QQmlJSMetaProperty &property)
110 addOwnProperty(property);
111 QQmlJSMetaMethod method(
112 QQmlSignalNames::propertyNameToChangedSignalName(property.propertyName()), u"void"_s);
113 method.setMethodType(QQmlJSMetaMethodType::Signal);
114 method.setIsImplicitQmlPropertyChangeSignal(
true);
115 addOwnMethod(method);
118bool QQmlJSScope::hasMethod(
const QString &name)
const
120 return QQmlJSUtils::searchBaseAndExtensionTypes(
121 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
122 if (mode == QQmlJSScope::ExtensionNamespace)
124 return scope->m_methods.contains(name);
129
130
131
132
133
134
135
136
137QHash<QString, QQmlJSMetaMethod> QQmlJSScope::methods()
const
139 QHash<QString, QQmlJSMetaMethod> results;
140 QQmlJSUtils::searchBaseAndExtensionTypes(
141 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
142 if (mode == QQmlJSScope::ExtensionNamespace)
144 for (
auto it = scope->m_methods.constBegin(); it != scope->m_methods.constEnd();
146 if (!results.contains(it.key()))
147 results.insert(it.key(), it.value());
155QList<QQmlJSMetaMethod> QQmlJSScope::methods(
const QString &name)
const
157 QList<QQmlJSMetaMethod> results;
159 QQmlJSUtils::searchBaseAndExtensionTypes(
160 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
161 if (mode == QQmlJSScope::ExtensionNamespace)
163 results.append(scope->ownMethods(name));
169QList<QQmlJSMetaMethod> QQmlJSScope::methods(
const QString &name, QQmlJSMetaMethodType type)
const
171 QList<QQmlJSMetaMethod> results;
173 QQmlJSUtils::searchBaseAndExtensionTypes(
174 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
175 if (mode == QQmlJSScope::ExtensionNamespace)
177 const auto ownMethods = scope->ownMethods(name);
178 for (
const auto &method : ownMethods) {
179 if (method.methodType() == type)
180 results.append(method);
187bool QQmlJSScope::hasEnumeration(
const QString &name)
const
189 return QQmlJSUtils::searchBaseAndExtensionTypes(
190 this, [&](
const QQmlJSScope *scope) {
return scope->m_enumerations.contains(name); });
193bool QQmlJSScope::hasOwnEnumerationKey(
const QString &name)
const
195 for (
const auto &e : m_enumerations) {
196 if (e.keys().contains(name))
202bool QQmlJSScope::hasEnumerationKey(
const QString &name)
const
204 return QQmlJSUtils::searchBaseAndExtensionTypes(
205 this, [&](
const QQmlJSScope *scope) {
return scope->hasOwnEnumerationKey(name); });
208QQmlJSMetaEnum QQmlJSScope::enumeration(
const QString &name)
const
210 QQmlJSMetaEnum result;
212 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
213 const auto it = scope->m_enumerations.find(name);
214 if (it == scope->m_enumerations.end())
223QHash<QString, QQmlJSMetaEnum> QQmlJSScope::enumerations()
const
225 QHash<QString, QQmlJSMetaEnum> results;
227 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
228 for (
auto it = scope->m_enumerations.constBegin(); it != scope->m_enumerations.constEnd();
230 if (!results.contains(it.key()))
231 results.insert(it.key(), it.value());
239QString QQmlJSScope::augmentedInternalName()
const
241 using namespace Qt::StringLiterals;
242 Q_ASSERT(!m_internalName.isEmpty());
244 switch (m_semantics) {
245 case AccessSemantics::Reference:
246 return m_internalName +
" *"_L1;
247 case AccessSemantics::Value:
248 case AccessSemantics::Sequence:
250 case AccessSemantics::None:
254 for (QQmlJSScope::ConstPtr base = baseType(); base; base = base->baseType()) {
255 switch (base->accessSemantics()) {
256 case AccessSemantics::Reference:
257 return m_internalName +
" *"_L1;
258 case AccessSemantics::Value:
259 case AccessSemantics::Sequence:
260 return m_internalName;
261 case AccessSemantics::None:
267 return m_internalName;
270QString QQmlJSScope::prettyName(QAnyStringView name)
272 const auto internal =
"$internal$."_L1;
273 const QString anonymous =
"$anonymous$."_L1;
275 QString pretty = name.toString();
277 if (pretty.startsWith(internal))
278 pretty = pretty.mid(internal.size());
279 else if (pretty.startsWith(anonymous))
280 pretty = pretty.mid(anonymous.size());
282 if (pretty == u"std::nullptr_t")
285 if (pretty == u"void")
286 return u"undefined"_s;
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308QQmlJSScope::IsComponentRoot QQmlJSScope::componentRootStatus()
const {
309 if (m_flags.testAnyFlags(
310 Flags(WrappedInImplicitComponent | FileRootComponent | InlineComponent))) {
311 return IsComponentRoot::Yes;
315 if (m_flags.testFlag(AssignedToUnknownProperty))
316 return IsComponentRoot::Maybe;
318 auto base = nonCompositeBaseType(parentScope());
320 return IsComponentRoot::No;
321 return base->internalName() == u"QQmlComponent"
322 ? IsComponentRoot::Yes
323 : IsComponentRoot::No;
326std::optional<QQmlJSScope::JavaScriptIdentifier>
327QQmlJSScope::jsIdentifier(
const QString &id)
const
329 for (
const auto *scope =
this; scope; scope = scope->parentScope().data()) {
330 if (QQmlSA::isFunctionScope(scope->m_scopeType)
331 || scope->m_scopeType == QQmlSA::ScopeType::JSLexicalScope) {
332 auto it = scope->m_jsIdentifiers.find(id);
333 if (it != scope->m_jsIdentifiers.end())
338 return std::optional<JavaScriptIdentifier>{};
341std::optional<QQmlJSScope::JavaScriptIdentifier> QQmlJSScope::ownJSIdentifier(
const QString &id)
const
343 auto it = m_jsIdentifiers.find(id);
344 if (it != m_jsIdentifiers.end())
347 return std::optional<JavaScriptIdentifier>{};
353 const int separatorIndex = typeName.lastIndexOf(u'.');
355 if (separatorIndex < 1 || separatorIndex >= typeName.size() - 1)
358 const auto parentIt = contextualTypes.types().constFind(typeName.first(separatorIndex).toString());
359 if (parentIt == contextualTypes.types().constEnd())
362 auto inlineComponentParent = *parentIt;
368 QStringView inlineComponentName = typeName.sliced(separatorIndex + 1);
369 QQueue<QQmlJSScope::ConstPtr> candidatesForInlineComponents;
370 candidatesForInlineComponents.enqueue(inlineComponentParent.scope);
371 while (candidatesForInlineComponents.size()) {
372 QQmlJSScope::ConstPtr current = candidatesForInlineComponents.dequeue();
375 if (current->isInlineComponent() && current->inlineComponentName() == inlineComponentName) {
376 return { current, inlineComponentParent.revision };
381 const auto &childScopes = current->childScopes();
382 for (
const auto &child : childScopes) {
383 if (child->scopeType() == QQmlSA::ScopeType::QMLScope)
384 candidatesForInlineComponents.enqueue(child);
387 if (
const auto base = current->baseType())
388 candidatesForInlineComponents.enqueue(base);
394
395
396
397
398
399
400
401QQmlJSScope::ImportedScope<QQmlJSScope::ConstPtr> QQmlJSScope::findType(
402 const QString &name,
const QQmlJS::ContextualTypes &contextualTypes,
403 QSet<QString> *usedTypes)
405 const auto useType = [&]() {
406 if (usedTypes !=
nullptr)
407 usedTypes->insert(name);
410 auto type = contextualTypes.types().constFind(name);
412 if (type != contextualTypes.types().constEnd()) {
417 const auto findListType = [&](
const QString &prefix,
const QString &postfix)
418 -> ImportedScope<ConstPtr> {
419 if (name.startsWith(prefix) && name.endsWith(postfix)) {
420 const qsizetype prefixLength = prefix.length();
421 const QString &elementName
422 = name.mid(prefixLength, name.length() - prefixLength - postfix.length());
423 const ImportedScope<ConstPtr> element
424 = findType(elementName, contextualTypes, usedTypes);
427 return { element.scope->listType(), element.revision };
434 switch (contextualTypes.context()) {
435 case QQmlJS::ContextualTypes::INTERNAL: {
436 if (
const auto listType = findListType(u"QList<"_s, u">"_s);
437 listType.scope && !listType.scope->isReferenceType()) {
441 if (
const auto listType = findListType(u"QQmlListProperty<"_s, u">"_s);
442 listType.scope && listType.scope->isReferenceType()) {
447 const auto colonColon = name.lastIndexOf(QStringLiteral(
"::"));
448 if (colonColon == -1)
451 const QString outerTypeName = name.left(colonColon);
452 const auto outerType = contextualTypes.types().constFind(outerTypeName);
453 if (outerType == contextualTypes.types().constEnd())
456 for (
const auto &innerType : std::as_const(outerType->scope->m_childScopes)) {
457 if (innerType->m_internalName == name) {
459 return { innerType, outerType->revision };
465 case QQmlJS::ContextualTypes::QML: {
467 const auto inlineComponent = qFindInlineComponents(name, contextualTypes);
468 if (inlineComponent.scope) {
470 return inlineComponent;
473 if (
const auto listType = findListType(u"list<"_s, u">"_s); listType.scope)
482QTypeRevision QQmlJSScope::resolveType(
483 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &context,
484 QSet<QString> *usedTypes)
486 if (self->accessSemantics() == AccessSemantics::Sequence
487 && self->internalName().startsWith(u"QQmlListProperty<"_s)) {
488 self->setIsListProperty(
true);
491 const QString baseTypeName = self->baseTypeName();
492 const auto baseType = findType(baseTypeName, context, usedTypes);
493 if (!self->m_baseType.scope && !baseTypeName.isEmpty())
494 self->m_baseType = { baseType.scope, baseType.revision };
496 if (!self->m_attachedType && !self->m_attachedTypeName.isEmpty())
497 self->m_attachedType = findType(self->m_attachedTypeName, context, usedTypes).scope;
499 if (!self->m_elementType && !self->m_elementTypeName.isEmpty())
500 self->m_elementType = findType(self->m_elementTypeName, context, usedTypes).scope;
502 if (!self->m_extensionType) {
503 if (self->m_extensionTypeName.isEmpty()) {
504 if (self->accessSemantics() == AccessSemantics::Sequence) {
506 self->setExtensionTypeName(u"Array"_s);
507 self->setExtensionIsJavaScript(
true);
508 self->m_extensionType = context.arrayType();
511 self->m_extensionType = findType(self->m_extensionTypeName, context, usedTypes).scope;
516 for (
auto it = self->m_properties.begin(), end = self->m_properties.end(); it != end; ++it) {
517 const QString typeName = it->typeName();
518 if (it->type() || typeName.isEmpty())
521 if (
const auto type = findType(typeName, context, usedTypes); type.scope) {
522 it->setType(it->isList() ? type.scope->listType() : type.scope);
526 const auto enumeration = self->m_enumerations.find(typeName);
527 if (enumeration != self->m_enumerations.end()) {
528 it->setType(it->isList()
529 ? enumeration->type()->listType()
530 : QQmlJSScope::ConstPtr(enumeration->type()));
534 const auto resolveParameter = [&](QQmlJSMetaParameter ¶meter) {
535 if (
const QString typeName = parameter.typeName();
536 !parameter.type() && !typeName.isEmpty()) {
537 auto type = findType(typeName, context, usedTypes);
538 if (type.scope && parameter.isList()) {
539 type.scope = type.scope->listType();
540 parameter.setIsList(
false);
541 parameter.setIsPointer(
false);
542 parameter.setTypeName(type.scope ? type.scope->internalName() : QString());
543 }
else if (type.scope && type.scope->isReferenceType()) {
544 parameter.setIsPointer(
true);
546 parameter.setType({ type.scope });
550 for (
auto it = self->m_methods.begin(), end = self->m_methods.end(); it != end; ++it) {
551 auto returnValue = it->returnValue();
552 resolveParameter(returnValue);
553 it->setReturnValue(returnValue);
555 auto parameters = it->parameters();
556 for (
int i = 0, length = parameters.size(); i < length; ++i)
557 resolveParameter(parameters[i]);
558 it->setParameters(parameters);
561 for (
auto it = self->m_jsIdentifiers.begin(); it != self->m_jsIdentifiers.end(); ++it) {
563 it->scope = findType(it->typeName.value(), context, usedTypes).scope;
566 return baseType.revision;
569void QQmlJSScope::updateChildScope(
570 const QQmlJSScope::Ptr &childScope,
const QQmlJSScope::Ptr &self,
571 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
573 switch (childScope->scopeType()) {
574 case QQmlSA::ScopeType::GroupedPropertyScope:
575 QQmlJSUtils::searchBaseAndExtensionTypes(
576 self.data(), [&](
const QQmlJSScope *type, QQmlJSScope::ExtensionKind mode) {
577 if (mode == QQmlJSScope::ExtensionNamespace)
579 const auto propertyIt = type->m_properties.find(childScope->internalName());
580 if (propertyIt != type->m_properties.end()) {
581 childScope->m_baseType.scope = QQmlJSScope::ConstPtr(propertyIt->type());
582 if (propertyIt->type())
583 childScope->m_semantics = propertyIt->type()->accessSemantics();
584 childScope->setBaseTypeName(propertyIt->typeName());
590 case QQmlSA::ScopeType::AttachedPropertyScope:
591 if (
const auto attachedBase = findType(
592 childScope->internalName(), contextualTypes, usedTypes).scope) {
593 childScope->m_baseType.scope = attachedBase->attachedType();
594 childScope->setBaseTypeName(attachedBase->attachedTypeName());
602template<
typename Resolver,
typename ChildScopeUpdater>
604 Resolver resolve, ChildScopeUpdater update,
const QQmlJSScope::Ptr &self,
607 const QTypeRevision revision = resolve(self, contextualTypes, usedTypes);
609 const auto childScopes = self->childScopes();
610 for (
auto it = childScopes.begin(), end = childScopes.end(); it != end; ++it) {
611 const auto childScope = *it;
612 update(childScope, self, contextualTypes, usedTypes);
613 resolveTypesInternal(resolve, update, childScope, contextualTypes, usedTypes);
618QTypeRevision QQmlJSScope::resolveTypes(
619 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
620 QSet<QString> *usedTypes)
622 const auto resolveAll = [](
const QQmlJSScope::Ptr &self,
623 const QQmlJS::ContextualTypes &contextualTypes,
624 QSet<QString> *usedTypes) {
625 resolveEnums(self, contextualTypes, usedTypes);
626 resolveList(self, contextualTypes.arrayType());
627 return resolveType(self, contextualTypes, usedTypes);
629 return resolveTypesInternal(resolveAll, updateChildScope, self, contextualTypes, usedTypes);
632void QQmlJSScope::resolveNonEnumTypes(
633 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
634 QSet<QString> *usedTypes)
636 resolveTypesInternal(resolveType, updateChildScope, self, contextualTypes, usedTypes);
643 if (underlyingType == u"uint"
644 || underlyingType == u"quint8"
645 || underlyingType == u"ushort"
646 || underlyingType == u"ulonglong") {
650 if (underlyingType == u"int"
651 || underlyingType == u"qint8"
652 || underlyingType == u"short"
653 || underlyingType == u"longlong") {
663
664
665
666
667
668
669
670
671
672
673void QQmlJSScope::resolveEnums(
674 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
675 QSet<QString> *usedTypes)
678 QHash<QString, QQmlJSMetaEnum> toBeAppended;
679 for (
auto it = self->m_enumerations.begin(), end = self->m_enumerations.end(); it != end; ++it) {
682 QQmlJSScope::Ptr enumScope = QQmlJSScope::create();
683 reparent(self, enumScope);
684 enumScope->m_scopeType = QQmlSA::ScopeType::EnumScope;
686 QString typeName = it->typeName();
687 if (typeName.isEmpty())
688 typeName = QStringLiteral(
"int");
689 else if (it->isFlag())
690 typeName = flagStorage(typeName);
691 enumScope->setBaseTypeName(typeName);
692 const auto type = findType(typeName, contextualTypes, usedTypes);
693 enumScope->m_baseType = { type.scope, type.revision };
695 enumScope->m_semantics = AccessSemantics::Value;
696 enumScope->m_internalName = self->internalName() + QStringLiteral(
"::") + it->name();
697 resolveList(enumScope, contextualTypes.arrayType());
698 if (QString alias = it->alias(); !alias.isEmpty()
699 && self->m_enumerations.constFind(alias) == self->m_enumerations.constEnd()) {
700 auto aliasScope = QQmlJSScope::create();
701 *aliasScope = *enumScope;
702 reparent(self, aliasScope);
703 aliasScope->m_internalName = self->internalName() + QStringLiteral(
"::") + alias;
704 QQmlJSMetaEnum cpy(*it);
705 cpy.setType(QQmlJSScope::ConstPtr(aliasScope));
706 toBeAppended.insert(alias, cpy);
708 it->setType(QQmlJSScope::ConstPtr(enumScope));
711 self->m_enumerations.insert(toBeAppended);
714void QQmlJSScope::resolveList(
const QQmlJSScope::Ptr &self,
const QQmlJSScope::ConstPtr &arrayType)
716 if (self->listType() || self->accessSemantics() == AccessSemantics::Sequence)
719 Q_ASSERT(!arrayType.isNull());
720 QQmlJSScope::Ptr listType = QQmlJSScope::create();
721 listType->setAccessSemantics(AccessSemantics::Sequence);
722 listType->setElementTypeName(self->internalName());
724 if (self->isComposite()) {
726 listType->setInternalName(u"QQmlListProperty<>"_s);
727 listType->m_elementType = QQmlJSScope::ConstPtr(self);
728 }
else if (self->isReferenceType()) {
729 listType->setInternalName(u"QQmlListProperty<%2>"_s.arg(self->internalName()));
733 listType->setInternalName(u"QList<%2>"_s.arg(self->internalName()));
734 listType->setFilePath(self->filePath());
737 const QQmlJS::ContextualType element = { self, QTypeRevision(),
738 QQmlJS::PrecedenceValues::Default };
739 const QQmlJSImportedScope array = {arrayType, QTypeRevision()};
740 QQmlJS::ContextualTypes contextualTypes(
741 QQmlJS::ContextualTypes::INTERNAL,
742 { { self->internalName(), element }, },
743 { { self, self->internalName() }, },
745 QQmlJSScope::resolveTypes(listType, contextualTypes);
747 Q_ASSERT(listType->elementType() == self);
748 self->m_listType = listType;
751void QQmlJSScope::resolveGroup(
752 const Ptr &self,
const ConstPtr &baseType,
753 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
758 Q_ASSERT(self->isComposite());
760 self->m_baseType.scope = baseType;
761 self->m_semantics = baseType->accessSemantics();
762 resolveNonEnumTypes(self, contextualTypes, usedTypes);
765QQmlJSScope::ConstPtr QQmlJSScope::findCurrentQMLScope(
const QQmlJSScope::ConstPtr &scope)
767 auto qmlScope = scope;
768 while (qmlScope && qmlScope->m_scopeType != QQmlSA::ScopeType::QMLScope)
769 qmlScope = qmlScope->parentScope();
773bool QQmlJSScope::hasProperty(
const QString &name)
const
775 return QQmlJSUtils::searchBaseAndExtensionTypes(
776 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
777 if (mode == QQmlJSScope::ExtensionNamespace)
779 return scope->m_properties.contains(name);
783QQmlJSMetaProperty QQmlJSScope::property(
const QString &name)
const
785 QQmlJSMetaProperty prop;
786 QQmlJSUtils::searchBaseAndExtensionTypes(
787 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
788 if (mode == QQmlJSScope::ExtensionNamespace)
790 const auto it = scope->m_properties.find(name);
791 if (it == scope->m_properties.end())
800
801
802
803
804
805
806QHash<QString, QQmlJSMetaProperty> QQmlJSScope::properties()
const
808 QHash<QString, QQmlJSMetaProperty> results;
809 QQmlJSUtils::searchBaseAndExtensionTypes(
810 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
811 if (mode == QQmlJSScope::ExtensionNamespace)
813 for (
auto it = scope->m_properties.constBegin();
814 it != scope->m_properties.constEnd(); it++) {
815 if (!results.contains(it.key()))
816 results.insert(it.key(), it.value());
823template <
typename Predicate>
826 QQmlJSScope::AnnotatedScope owner;
827 QQmlJSUtils::searchBaseAndExtensionTypes(
828 self, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
829 if (mode == QQmlJSScope::ExtensionNamespace)
832 owner = { scope, mode };
840QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfProperty(
const QQmlJSScope::ConstPtr &self,
843 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
844 return scope->hasOwnProperty(name);
848QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfMethod(
const QQmlJSScope::ConstPtr &self,
851 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
852 return scope->hasOwnMethod(name);
856QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfEnum(
const QQmlJSScope::ConstPtr &self,
859 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
860 return scope->hasOwnEnumeration(name);
864void QQmlJSScope::setPropertyLocallyRequired(
const QString &name,
bool isRequired)
867 m_requiredPropertyNames.removeOne(name);
868 else if (!m_requiredPropertyNames.contains(name))
869 m_requiredPropertyNames.append(name);
872bool QQmlJSScope::isPropertyRequired(
const QString &name)
const
874 bool isRequired =
false;
875 QQmlJSUtils::searchBaseAndExtensionTypes(
876 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
877 if (scope->isPropertyLocallyRequired(name)) {
884 if (mode == QQmlJSScope::ExtensionNamespace)
890 return scope->hasOwnProperty(name);
895bool QQmlJSScope::isPropertyLocallyRequired(
const QString &name)
const
897 return m_requiredPropertyNames.contains(name);
900void QQmlJSScope::addOwnPropertyBinding(
const QQmlJSMetaPropertyBinding &binding, BindingTargetSpecifier specifier)
902 Q_ASSERT(binding.sourceLocation().isValid());
903 m_propertyBindings.insert(binding.propertyName(), binding);
907 using iter =
typename QMultiHash<QString, QQmlJSMetaPropertyBinding>::iterator;
908 std::pair<iter, iter> r = m_propertyBindings.equal_range(binding.propertyName());
909 std::rotate(r.first, std::next(r.first), r.second);
912 addOwnPropertyBindingInQmlIROrder(binding, specifier);
913 Q_ASSERT(m_propertyBindings.size() == m_propertyBindingsArray.size());
916void QQmlJSScope::addOwnPropertyBindingInQmlIROrder(
const QQmlJSMetaPropertyBinding &binding,
917 BindingTargetSpecifier specifier)
926 static_assert(QTypeInfo<QQmlJSScope::QmlIRCompatibilityBindingData>::isRelocatable,
927 "We really want T to be relocatable as it improves QList<T> performance");
930 case BindingTargetSpecifier::SimplePropertyTarget: {
931 m_propertyBindingsArray.emplaceFront(binding.propertyName(),
932 binding.sourceLocation().offset);
935 case BindingTargetSpecifier::ListPropertyTarget: {
936 const auto bindingOnTheSameProperty =
937 [&](
const QQmlJSScope::QmlIRCompatibilityBindingData &x) {
938 return x.propertyName == binding.propertyName();
944 auto pos = std::find_if_not(m_propertyBindingsArray.begin(), m_propertyBindingsArray.end(),
945 bindingOnTheSameProperty);
946 Q_ASSERT(pos == m_propertyBindingsArray.begin()
947 || std::prev(pos)->propertyName == binding.propertyName());
948 m_propertyBindingsArray.emplace(pos, binding.propertyName(),
949 binding.sourceLocation().offset);
952 case BindingTargetSpecifier::UnnamedPropertyTarget: {
955 m_propertyBindingsArray.emplaceBack(
956 binding.propertyName(), binding.sourceLocation().offset);
966QList<QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindingsInQmlIROrder()
const
968 QList<QQmlJSMetaPropertyBinding> qmlIrOrdered;
969 qmlIrOrdered.reserve(m_propertyBindingsArray.size());
971 for (
const auto &data : m_propertyBindingsArray) {
972 const auto [first, last] = m_propertyBindings.equal_range(data.propertyName);
973 Q_ASSERT(first != last);
974 auto binding = std::find_if(first, last, [&](
const QQmlJSMetaPropertyBinding &x) {
975 return x.sourceLocation().offset == data.sourceLocationOffset;
977 Q_ASSERT(binding != last);
978 qmlIrOrdered.append(*binding);
984bool QQmlJSScope::hasPropertyBindings(
const QString &name)
const
986 return QQmlJSUtils::searchBaseAndExtensionTypes(
987 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
988 if (mode != QQmlJSScope::NotExtension) {
989 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
992 return scope->hasOwnPropertyBindings(name);
996QList<QQmlJSMetaPropertyBinding> QQmlJSScope::propertyBindings(
const QString &name)
const
998 QList<QQmlJSMetaPropertyBinding> bindings;
999 QQmlJSUtils::searchBaseAndExtensionTypes(
1000 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1001 if (mode != QQmlJSScope::NotExtension) {
1002 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
1005 const auto range = scope->ownPropertyBindings(name);
1006 for (
auto it = range.first; it != range.second; ++it)
1007 bindings.append(*it);
1013bool QQmlJSScope::hasInterface(
const QString &name)
const
1015 return QQmlJSUtils::searchBaseAndExtensionTypes(
1016 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1017 if (mode != QQmlJSScope::NotExtension)
1019 return scope->m_interfaceNames.contains(name);
1023bool QQmlJSScope::isNameDeferred(
const QString &name)
const
1025 bool isDeferred =
false;
1027 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1028 const QStringList immediate = scope->ownImmediateNames();
1029 if (!immediate.isEmpty()) {
1030 isDeferred = !immediate.contains(name);
1033 const QStringList deferred = scope->ownDeferredNames();
1034 if (!deferred.isEmpty()) {
1035 isDeferred = deferred.contains(name);
1044void QQmlJSScope::setBaseTypeName(
const QString &baseTypeName)
1046 m_flags.setFlag(HasBaseTypeError,
false);
1047 m_baseTypeNameOrError = baseTypeName;
1050QString QQmlJSScope::baseTypeName()
const
1052 return m_flags.testFlag(HasBaseTypeError) ? QString() : m_baseTypeNameOrError;
1055void QQmlJSScope::setBaseTypeError(
const QString &baseTypeError)
1057 m_flags.setFlag(HasBaseTypeError);
1058 m_baseTypeNameOrError = baseTypeError;
1062
1063
1064
1065
1066
1067QString QQmlJSScope::moduleName()
const
1069 for (
const QQmlJSScope *it =
this; it; it = it->parentScope().get()) {
1070 const QString name = it->ownModuleName();
1071 if (!name.isEmpty())
1077QString QQmlJSScope::baseTypeError()
const
1079 return m_flags.testFlag(HasBaseTypeError) ? m_baseTypeNameOrError : QString();
1082QString QQmlJSScope::attachedTypeName()
const
1085 QQmlJSUtils::searchBaseAndExtensionTypes(
1086 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1087 if (mode != QQmlJSScope::NotExtension)
1089 if (scope->ownAttachedType().isNull())
1091 name = scope->ownAttachedTypeName();
1098QQmlJSScope::ConstPtr QQmlJSScope::attachedType()
const
1100 QQmlJSScope::ConstPtr ptr;
1101 QQmlJSUtils::searchBaseAndExtensionTypes(
1102 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1103 if (mode != QQmlJSScope::NotExtension)
1105 if (scope->ownAttachedType().isNull())
1107 ptr = scope->ownAttachedType();
1114QQmlJSScope::AnnotatedScope QQmlJSScope::extensionType()
const
1116 if (!m_extensionType)
1117 return { m_extensionType, NotExtension };
1118 if (m_flags & ExtensionIsJavaScript)
1119 return { m_extensionType, ExtensionJavaScript };
1120 if (m_flags & ExtensionIsNamespace)
1121 return { m_extensionType, ExtensionNamespace };
1122 return { m_extensionType, ExtensionType };
1125void QQmlJSScope::addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index)
1127 m_runtimeFunctionIndices.emplaceBack(index);
1130bool QQmlJSScope::isResolved()
const
1132 const bool nameIsEmpty = (m_scopeType == ScopeType::AttachedPropertyScope
1133 || m_scopeType == ScopeType::GroupedPropertyScope)
1134 ? m_internalName.isEmpty()
1135 : m_baseTypeNameOrError.isEmpty();
1138 if (m_baseType.scope.isNull())
1140 if (isComposite() && !nonCompositeBaseType(baseType()))
1145QString QQmlJSScope::defaultPropertyName()
const
1148 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1149 name = scope->ownDefaultPropertyName();
1150 return !name.isEmpty();
1155QString QQmlJSScope::parentPropertyName()
const
1158 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1159 name = scope->ownParentPropertyName();
1160 return !name.isEmpty();
1165bool QQmlJSScope::isFullyResolved()
const
1167 bool baseResolved =
true;
1168 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1169 if (!scope->isResolved()) {
1170 baseResolved =
false;
1176 return baseResolved;
1179QQmlJSScope::Export::Export(
1180 QString package, QString type, QTypeRevision version, QTypeRevision revision)
1181 : m_package(std::move(package))
1182 , m_type(std::move(type))
1183 , m_version(std::move(version))
1184 , m_revision(std::move(revision))
1188bool QQmlJSScope::Export::isValid()
const
1190 return m_version.isValid() || !m_package.isEmpty() || !m_type.isEmpty();
1193QDeferredFactory<QQmlJSScope>::QDeferredFactory(QQmlJSImporter *importer,
1194 const QQmlJS::TypeReader &typeReader,
1195 const QString &filePath,
const QString &moduleName,
1197 : m_importer(importer),
1198 m_typeReader(typeReader ? typeReader : QQmlJS::TypeReader{ QQmlJS::defaultTypeReader }),
1199 m_filePath(filePath),
1200 m_moduleName(moduleName),
1201 m_isSingleton(isSingleton)
1205void QDeferredFactory<QQmlJSScope>::populate(
const QSharedPointer<QQmlJSScope> &scope)
const
1207 scope->setOwnModuleName(m_moduleName);
1208 scope->setIsSingleton(m_isSingleton);
1210 m_typeReader(m_importer, m_filePath, scope);
1214
1215
1216
1217
1218
1219
1220
1221
1222bool QQmlJSScope::canAssign(
const QQmlJSScope::ConstPtr &derived)
const
1228 Q_ASSERT(!isComposite() || nonCompositeBaseType(baseType()));
1229 Q_ASSERT(nonCompositeBaseType(derived));
1233 const bool isBaseComponent = [
this]() {
1234 if (internalName() == u"QQmlComponent")
1236 else if (isComposite())
1238 for (
auto cppBase = nonCompositeBaseType(baseType()); cppBase;
1239 cppBase = cppBase->baseType()) {
1240 if (cppBase->internalName() == u"QQmlAbstractDelegateComponent")
1246 QDuplicateTracker<QQmlJSScope::ConstPtr> seen;
1247 for (
auto scope = derived; !scope.isNull() && !seen.hasSeen(scope);
1248 scope = scope->baseType()) {
1249 if (isSameType(scope))
1251 if (isBaseComponent && scope->internalName() == u"QObject"_s)
1255 if (internalName() == u"QVariant"_s || internalName() == u"QJSValue"_s)
1258 return isListProperty() && elementType()->canAssign(derived);
1262
1263
1264
1265bool QQmlJSScope::isInCustomParserParent()
const
1267 for (
const auto *scope =
this; scope; scope = scope->parentScope().get()) {
1268 if (!scope->baseType().isNull() && scope->baseType()->hasCustomParser())
1276
1277
1278
1279
1280std::optional<QString> QQmlJSScope::inlineComponentName()
const
1282 Q_ASSERT(isInlineComponent() == m_inlineComponentName.has_value());
1283 return m_inlineComponentName;
1287
1288
1289
1290
1291QQmlJSScope::InlineComponentOrDocumentRootName QQmlJSScope::enclosingInlineComponentName()
const
1293 for (
auto *type =
this; type; type = type->parentScope().get()) {
1294 if (type->isInlineComponent())
1295 return *type->inlineComponentName();
1297 return RootDocumentNameType();
1300QList<QQmlJSScope::ConstPtr> QQmlJSScope::childScopes()
const
1302 QList<QQmlJSScope::ConstPtr> result;
1303 result.reserve(m_childScopes.size());
1304 for (
const auto &child : m_childScopes)
1305 result.append(child);
1310
1311
1312
1313
1314
1315
1316bool QQmlJSScope::enforcesScopedEnums()
const
1318 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1319 if (scope->hasEnforcesScopedEnumsFlag())
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340bool QQmlJSScope::isCreatable()
const
1342 auto isCreatableNonRecursive = [](
const QQmlJSScope *scope) {
1343 return scope->hasCreatableFlag() && !scope->isSingleton()
1344 && scope->scopeType() == QQmlSA::ScopeType::QMLScope;
1347 for (
const QQmlJSScope* scope =
this; scope; scope = scope->baseType().get()) {
1348 if (!scope->isComposite()) {
1350 return isCreatableNonRecursive(scope);
1353 if (isCreatableNonRecursive(scope))
1361bool QQmlJSScope::isStructured()
const
1363 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1364 if (!scope->isComposite())
1365 return scope->hasStructuredFlag();
1370QQmlSA::Element QQmlJSScope::createQQmlSAElement(
const ConstPtr &ptr)
1372 QQmlSA::Element element;
1373 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = ptr;
1377QQmlSA::Element QQmlJSScope::createQQmlSAElement(ConstPtr &&ptr)
1379 QQmlSA::Element element;
1380 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = std::move(ptr);
1384const QQmlJSScope::ConstPtr &QQmlJSScope::scope(
const QQmlSA::Element &element)
1386 return *
reinterpret_cast<
const QQmlJSScope::ConstPtr *>(element.m_data);
1390QQmlJSScope::nonCompositeBaseRevision(
const ImportedScope<QQmlJSScope::ConstPtr> &scope)
1392 for (
auto base = scope; base.scope;
1393 base = { base.scope->m_baseType.scope, base.scope->m_baseType.revision }) {
1394 if (!base.scope->isComposite())
1395 return base.revision;
1401
1402
1403
1404
1405
1406
1407bool QQmlJSScope::isSameType(
const ConstPtr &otherScope)
const
1409 return this == otherScope.get()
1410 || (!
this->internalName().isEmpty()
1411 &&
this->internalName() == otherScope->internalName());
1414bool QQmlJSScope::inherits(
const ConstPtr &base)
const
1416 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1417 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)