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;
49QQmlJSScope::Ptr QQmlJSScope::clone(
const ConstPtr &origin)
52 return QQmlJSScope::Ptr();
53 QQmlJSScope::Ptr cloned = create();
55 if (QQmlJSScope::Ptr parent = cloned->parentScope())
56 parent->m_childScopes.append(cloned);
61
62
63
64
65
66QQmlJSScope::Ptr QQmlJSScope::resetForReparse(Ptr &&scope)
68 auto *factory = scope.factory();
70 const QString moduleName = scope->moduleName();
71 const bool isSingleton = scope->isSingleton();
72 *scope = QQmlJSScope{ scope->internalName() };
73 scope->setOwnModuleName(moduleName);
74 scope->setIsSingleton(isSingleton);
75 return std::move(scope);
78 const QString moduleName = factory->moduleName();
79 const QString internalName = factory->internalName();
80 const bool isSingleton = factory->isSingleton();
81 *scope.factory() = QQmlJSScope::ConstPtr::Factory{ };
82 scope->setOwnModuleName(moduleName);
83 scope->setInternalName(internalName);
84 scope->setIsSingleton(isSingleton);
85 return std::move(scope);
89
90
91
92QHash<QString, QQmlJSScope::JavaScriptIdentifier> QQmlJSScope::ownJSIdentifiers()
const
94 return m_jsIdentifiers;
97void QQmlJSScope::insertJSIdentifier(
const QString &name,
const JavaScriptIdentifier &identifier)
99 Q_ASSERT(m_scopeType != QQmlSA::ScopeType::QMLScope);
100 if (identifier.kind == JavaScriptIdentifier::LexicalScoped
101 || identifier.kind == JavaScriptIdentifier::Injected
102 || QQmlSA::isFunctionScope(m_scopeType)) {
103 m_jsIdentifiers.insert(name, identifier);
105 auto targetScope = parentScope();
106 while (targetScope->m_scopeType != QQmlSA::ScopeType::JSFunctionScope)
107 targetScope = targetScope->parentScope();
108 targetScope->m_jsIdentifiers.insert(name, identifier);
112void QQmlJSScope::setLineNumber(quint32 lineNumber)
114 m_sourceLocation.startLine = lineNumber;
116 m_sourceLocation.startColumn = 1;
119void QQmlJSScope::insertPropertyIdentifier(
const QQmlJSMetaProperty &property)
121 addOwnProperty(property);
122 QQmlJSMetaMethod method(
123 QQmlSignalNames::propertyNameToChangedSignalName(property.propertyName()), u"void"_s);
124 method.setMethodType(QQmlJSMetaMethodType::Signal);
125 method.setIsImplicitQmlPropertyChangeSignal(
true);
126 addOwnMethod(method);
129bool QQmlJSScope::hasMethod(
const QString &name)
const
131 return QQmlJSUtils::searchBaseAndExtensionTypes(
132 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
133 if (mode == QQmlJSScope::ExtensionNamespace)
135 return scope->m_methods.contains(name);
140
141
142
143
144
145
146
147
148QHash<QString, QQmlJSMetaMethod> QQmlJSScope::methods()
const
150 QHash<QString, QQmlJSMetaMethod> results;
151 QQmlJSUtils::searchBaseAndExtensionTypes(
152 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
153 if (mode == QQmlJSScope::ExtensionNamespace)
155 for (
auto it = scope->m_methods.constBegin(); it != scope->m_methods.constEnd();
157 if (!results.contains(it.key()))
158 results.insert(it.key(), it.value());
166QList<QQmlJSMetaMethod> QQmlJSScope::methods(
const QString &name)
const
168 QList<QQmlJSMetaMethod> results;
170 QQmlJSUtils::searchBaseAndExtensionTypes(
171 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
172 if (mode == QQmlJSScope::ExtensionNamespace)
174 results.append(scope->ownMethods(name));
180QList<QQmlJSMetaMethod> QQmlJSScope::methods(
const QString &name, QQmlJSMetaMethodType type)
const
182 QList<QQmlJSMetaMethod> results;
184 QQmlJSUtils::searchBaseAndExtensionTypes(
185 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
186 if (mode == QQmlJSScope::ExtensionNamespace)
188 const auto ownMethods = scope->ownMethods(name);
189 for (
const auto &method : ownMethods) {
190 if (method.methodType() == type)
191 results.append(method);
198bool QQmlJSScope::hasEnumeration(
const QString &name)
const
200 return QQmlJSUtils::searchBaseAndExtensionTypes(
201 this, [&](
const QQmlJSScope *scope) {
return scope->m_enumerations.contains(name); });
204bool QQmlJSScope::hasOwnEnumerationKey(
const QString &name)
const
206 for (
const auto &e : m_enumerations) {
207 if (e.keys().contains(name))
213bool QQmlJSScope::hasEnumerationKey(
const QString &name)
const
215 return QQmlJSUtils::searchBaseAndExtensionTypes(
216 this, [&](
const QQmlJSScope *scope) {
return scope->hasOwnEnumerationKey(name); });
219QQmlJSMetaEnum QQmlJSScope::enumeration(
const QString &name)
const
221 QQmlJSMetaEnum result;
223 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
224 const auto it = scope->m_enumerations.find(name);
225 if (it == scope->m_enumerations.end())
234QHash<QString, QQmlJSMetaEnum> QQmlJSScope::enumerations()
const
236 QHash<QString, QQmlJSMetaEnum> results;
238 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
239 for (
auto it = scope->m_enumerations.constBegin(); it != scope->m_enumerations.constEnd();
241 if (!results.contains(it.key()))
242 results.insert(it.key(), it.value());
250QString QQmlJSScope::augmentedInternalName()
const
252 using namespace Qt::StringLiterals;
253 Q_ASSERT(!m_internalName.isEmpty());
255 switch (m_semantics) {
256 case AccessSemantics::Reference:
257 return m_internalName +
" *"_L1;
258 case AccessSemantics::Value:
259 case AccessSemantics::Sequence:
261 case AccessSemantics::None:
265 for (QQmlJSScope::ConstPtr base = baseType(); base; base = base->baseType()) {
266 switch (base->accessSemantics()) {
267 case AccessSemantics::Reference:
268 return m_internalName +
" *"_L1;
269 case AccessSemantics::Value:
270 case AccessSemantics::Sequence:
271 return m_internalName;
272 case AccessSemantics::None:
278 return m_internalName;
281QString QQmlJSScope::prettyName(QAnyStringView name)
283 const auto internal =
"$internal$."_L1;
284 const QString anonymous =
"$anonymous$."_L1;
286 QString pretty = name.toString();
288 if (pretty.startsWith(internal))
289 pretty = pretty.mid(internal.size());
290 else if (pretty.startsWith(anonymous))
291 pretty = pretty.mid(anonymous.size());
293 if (pretty == u"std::nullptr_t")
296 if (pretty == u"void")
297 return u"undefined"_s;
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319QQmlJSScope::IsComponentRoot QQmlJSScope::componentRootStatus()
const {
320 if (m_flags.testAnyFlags(
321 Flags(WrappedInImplicitComponent | FileRootComponent | InlineComponent))) {
322 return IsComponentRoot::Yes;
326 if (m_flags.testFlag(AssignedToUnknownProperty))
327 return IsComponentRoot::Maybe;
329 auto base = nonCompositeBaseType(parentScope());
331 return IsComponentRoot::No;
332 return base->internalName() == u"QQmlComponent"
333 ? IsComponentRoot::Yes
334 : IsComponentRoot::No;
337std::optional<QQmlJSScope::JavaScriptIdentifier>
338QQmlJSScope::jsIdentifier(
const QString &id)
const
340 for (
const auto *scope =
this; scope; scope = scope->parentScope().data()) {
341 if (QQmlSA::isFunctionScope(scope->m_scopeType)
342 || scope->m_scopeType == QQmlSA::ScopeType::JSLexicalScope) {
343 auto it = scope->m_jsIdentifiers.find(id);
344 if (it != scope->m_jsIdentifiers.end())
349 return std::optional<JavaScriptIdentifier>{};
352std::optional<QQmlJSScope::JavaScriptIdentifier> QQmlJSScope::ownJSIdentifier(
const QString &id)
const
354 auto it = m_jsIdentifiers.find(id);
355 if (it != m_jsIdentifiers.end())
358 return std::optional<JavaScriptIdentifier>{};
364 const int separatorIndex = typeName.lastIndexOf(u'.');
366 if (separatorIndex < 1 || separatorIndex >= typeName.size() - 1)
369 const auto parentIt = contextualTypes.types().constFind(typeName.first(separatorIndex).toString());
370 if (parentIt == contextualTypes.types().constEnd())
373 auto inlineComponentParent = *parentIt;
379 QStringView inlineComponentName = typeName.sliced(separatorIndex + 1);
380 QQueue<QQmlJSScope::ConstPtr> candidatesForInlineComponents;
381 candidatesForInlineComponents.enqueue(inlineComponentParent.scope);
382 while (candidatesForInlineComponents.size()) {
383 QQmlJSScope::ConstPtr current = candidatesForInlineComponents.dequeue();
386 if (current->isInlineComponent() && current->inlineComponentName() == inlineComponentName) {
387 return { current, inlineComponentParent.revision };
392 const auto &childScopes = current->childScopes();
393 for (
const auto &child : childScopes) {
394 if (child->scopeType() == QQmlSA::ScopeType::QMLScope)
395 candidatesForInlineComponents.enqueue(child);
398 if (
const auto base = current->baseType())
399 candidatesForInlineComponents.enqueue(base);
405
406
407
408
409
410
411
412QQmlJSScope::ImportedScope<QQmlJSScope::ConstPtr> QQmlJSScope::findType(
413 const QString &name,
const QQmlJS::ContextualTypes &contextualTypes,
414 QSet<QString> *usedTypes)
416 const auto useType = [&]() {
417 if (usedTypes !=
nullptr)
418 usedTypes->insert(name);
421 auto type = contextualTypes.types().constFind(name);
423 if (type != contextualTypes.types().constEnd()) {
428 const auto findListType = [&](
const QString &prefix,
const QString &postfix)
429 -> ImportedScope<ConstPtr> {
430 if (name.startsWith(prefix) && name.endsWith(postfix)) {
431 const qsizetype prefixLength = prefix.length();
432 const QString &elementName
433 = name.mid(prefixLength, name.length() - prefixLength - postfix.length());
434 const ImportedScope<ConstPtr> element
435 = findType(elementName, contextualTypes, usedTypes);
438 return { element.scope->listType(), element.revision };
445 switch (contextualTypes.context()) {
446 case QQmlJS::ContextualTypes::INTERNAL: {
447 if (
const auto listType = findListType(u"QList<"_s, u">"_s);
448 listType.scope && !listType.scope->isReferenceType()) {
452 if (
const auto listType = findListType(u"QQmlListProperty<"_s, u">"_s);
453 listType.scope && listType.scope->isReferenceType()) {
458 const auto colonColon = name.lastIndexOf(QStringLiteral(
"::"));
459 if (colonColon == -1)
462 const QString outerTypeName = name.left(colonColon);
463 const auto outerType = contextualTypes.types().constFind(outerTypeName);
464 if (outerType == contextualTypes.types().constEnd())
467 for (
const auto &innerType : std::as_const(outerType->scope->m_childScopes)) {
468 if (innerType->m_internalName == name) {
470 return { innerType, outerType->revision };
476 case QQmlJS::ContextualTypes::QML: {
478 const auto inlineComponent = qFindInlineComponents(name, contextualTypes);
479 if (inlineComponent.scope) {
481 return inlineComponent;
484 if (
const auto listType = findListType(u"list<"_s, u">"_s); listType.scope)
493QTypeRevision QQmlJSScope::resolveType(
494 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &context,
495 QSet<QString> *usedTypes)
497 if (self->accessSemantics() == AccessSemantics::Sequence
498 && self->internalName().startsWith(u"QQmlListProperty<"_s)) {
499 self->setIsListProperty(
true);
502 const QString baseTypeName = self->baseTypeName();
503 const auto baseType = findType(baseTypeName, context, usedTypes);
504 if (!self->m_baseType.scope && !baseTypeName.isEmpty())
505 self->m_baseType = { baseType.scope, baseType.revision };
507 if (!self->m_attachedType && !self->m_attachedTypeName.isEmpty())
508 self->m_attachedType = findType(self->m_attachedTypeName, context, usedTypes).scope;
510 if (!self->m_elementType && !self->m_elementTypeName.isEmpty())
511 self->m_elementType = findType(self->m_elementTypeName, context, usedTypes).scope;
513 if (!self->m_extensionType) {
514 if (self->m_extensionTypeName.isEmpty()) {
515 if (self->accessSemantics() == AccessSemantics::Sequence) {
517 self->setExtensionTypeName(u"Array"_s);
518 self->setExtensionIsJavaScript(
true);
519 self->m_extensionType = context.arrayType();
522 self->m_extensionType = findType(self->m_extensionTypeName, context, usedTypes).scope;
527 for (
auto it = self->m_properties.begin(), end = self->m_properties.end(); it != end; ++it) {
528 const QString typeName = it->typeName();
529 if (it->type() || typeName.isEmpty())
532 if (
const auto type = findType(typeName, context, usedTypes); type.scope) {
533 it->setType(it->isList() ? type.scope->listType() : type.scope);
537 const auto enumeration = self->m_enumerations.find(typeName);
538 if (enumeration != self->m_enumerations.end()) {
539 it->setType(it->isList()
540 ? enumeration->type()->listType()
541 : QQmlJSScope::ConstPtr(enumeration->type()));
545 const auto resolveParameter = [&](QQmlJSMetaParameter ¶meter) {
546 if (
const QString typeName = parameter.typeName();
547 !parameter.type() && !typeName.isEmpty()) {
548 auto type = findType(typeName, context, usedTypes);
549 if (type.scope && parameter.isList()) {
550 type.scope = type.scope->listType();
551 parameter.setIsList(
false);
552 parameter.setIsPointer(
false);
553 parameter.setTypeName(type.scope ? type.scope->internalName() : QString());
554 }
else if (type.scope && type.scope->isReferenceType()) {
555 parameter.setIsPointer(
true);
557 parameter.setType({ type.scope });
561 for (
auto it = self->m_methods.begin(), end = self->m_methods.end(); it != end; ++it) {
562 auto returnValue = it->returnValue();
563 resolveParameter(returnValue);
564 it->setReturnValue(returnValue);
566 auto parameters = it->parameters();
567 for (
int i = 0, length = parameters.size(); i < length; ++i)
568 resolveParameter(parameters[i]);
569 it->setParameters(parameters);
572 for (
auto it = self->m_jsIdentifiers.begin(); it != self->m_jsIdentifiers.end(); ++it) {
574 it->scope = findType(it->typeName.value(), context, usedTypes).scope;
577 return baseType.revision;
580void QQmlJSScope::updateChildScope(
581 const QQmlJSScope::Ptr &childScope,
const QQmlJSScope::Ptr &self,
582 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
584 switch (childScope->scopeType()) {
585 case QQmlSA::ScopeType::GroupedPropertyScope:
586 QQmlJSUtils::searchBaseAndExtensionTypes(
587 self.data(), [&](
const QQmlJSScope *type, QQmlJSScope::ExtensionKind mode) {
588 if (mode == QQmlJSScope::ExtensionNamespace)
590 const auto propertyIt = type->m_properties.find(childScope->internalName());
591 if (propertyIt != type->m_properties.end()) {
592 childScope->m_baseType.scope = QQmlJSScope::ConstPtr(propertyIt->type());
593 if (propertyIt->type())
594 childScope->m_semantics = propertyIt->type()->accessSemantics();
595 childScope->setBaseTypeName(propertyIt->typeName());
601 case QQmlSA::ScopeType::AttachedPropertyScope:
602 if (
const auto attachedBase = findType(
603 childScope->internalName(), contextualTypes, usedTypes).scope) {
604 childScope->m_baseType.scope = attachedBase->attachedType();
605 childScope->setBaseTypeName(attachedBase->attachedTypeName());
613template<
typename Resolver,
typename ChildScopeUpdater>
615 Resolver resolve, ChildScopeUpdater update,
const QQmlJSScope::Ptr &self,
618 const QTypeRevision revision = resolve(self, contextualTypes, usedTypes);
620 const auto childScopes = self->childScopes();
621 for (
auto it = childScopes.begin(), end = childScopes.end(); it != end; ++it) {
622 const auto childScope = *it;
623 update(childScope, self, contextualTypes, usedTypes);
624 resolveTypesInternal(resolve, update, childScope, contextualTypes, usedTypes);
629QTypeRevision QQmlJSScope::resolveTypes(
630 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
631 QSet<QString> *usedTypes)
633 const auto resolveAll = [](
const QQmlJSScope::Ptr &self,
634 const QQmlJS::ContextualTypes &contextualTypes,
635 QSet<QString> *usedTypes) {
636 resolveEnums(self, contextualTypes, usedTypes);
637 resolveList(self, contextualTypes.arrayType());
638 return resolveType(self, contextualTypes, usedTypes);
640 return resolveTypesInternal(resolveAll, updateChildScope, self, contextualTypes, usedTypes);
643void QQmlJSScope::resolveNonEnumTypes(
644 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
645 QSet<QString> *usedTypes)
647 resolveTypesInternal(resolveType, updateChildScope, self, contextualTypes, usedTypes);
654 if (underlyingType == u"uint"
655 || underlyingType == u"quint8"
656 || underlyingType == u"ushort"
657 || underlyingType == u"ulonglong") {
661 if (underlyingType == u"int"
662 || underlyingType == u"qint8"
663 || underlyingType == u"short"
664 || underlyingType == u"longlong") {
674
675
676
677
678
679
680
681
682
683
684void QQmlJSScope::resolveEnums(
685 const QQmlJSScope::Ptr &self,
const QQmlJS::ContextualTypes &contextualTypes,
686 QSet<QString> *usedTypes)
689 QHash<QString, QQmlJSMetaEnum> toBeAppended;
690 for (
auto it = self->m_enumerations.begin(), end = self->m_enumerations.end(); it != end; ++it) {
693 QQmlJSScope::Ptr enumScope = QQmlJSScope::create();
694 reparent(self, enumScope);
695 enumScope->m_scopeType = QQmlSA::ScopeType::EnumScope;
697 QString typeName = it->typeName();
698 if (typeName.isEmpty())
699 typeName = QStringLiteral(
"int");
700 else if (it->isFlag())
701 typeName = flagStorage(typeName);
702 enumScope->setBaseTypeName(typeName);
703 const auto type = findType(typeName, contextualTypes, usedTypes);
704 enumScope->m_baseType = { type.scope, type.revision };
706 enumScope->m_semantics = AccessSemantics::Value;
707 enumScope->m_internalName = self->internalName() + QStringLiteral(
"::") + it->name();
708 resolveList(enumScope, contextualTypes.arrayType());
709 if (QString alias = it->alias(); !alias.isEmpty()
710 && self->m_enumerations.constFind(alias) == self->m_enumerations.constEnd()) {
711 auto aliasScope = QQmlJSScope::clone(enumScope);
712 aliasScope->m_internalName = self->internalName() + QStringLiteral(
"::") + alias;
713 QQmlJSMetaEnum cpy(*it);
714 cpy.setType(QQmlJSScope::ConstPtr(aliasScope));
715 toBeAppended.insert(alias, cpy);
717 it->setType(QQmlJSScope::ConstPtr(enumScope));
720 self->m_enumerations.insert(toBeAppended);
723void QQmlJSScope::resolveList(
const QQmlJSScope::Ptr &self,
const QQmlJSScope::ConstPtr &arrayType)
725 if (self->listType() || self->accessSemantics() == AccessSemantics::Sequence)
728 Q_ASSERT(!arrayType.isNull());
729 QQmlJSScope::Ptr listType = QQmlJSScope::create();
730 listType->setAccessSemantics(AccessSemantics::Sequence);
731 listType->setElementTypeName(self->internalName());
733 if (self->isComposite()) {
735 listType->setInternalName(u"QQmlListProperty<>"_s);
736 listType->m_elementType = QQmlJSScope::ConstPtr(self);
737 }
else if (self->isReferenceType()) {
738 listType->setInternalName(u"QQmlListProperty<%2>"_s.arg(self->internalName()));
742 listType->setInternalName(u"QList<%2>"_s.arg(self->internalName()));
743 listType->setFilePath(self->filePath());
746 const QQmlJS::ContextualType element = { self, QTypeRevision(),
747 QQmlJS::PrecedenceValues::Default };
748 const QQmlJSImportedScope array = {arrayType, QTypeRevision()};
749 QQmlJS::ContextualTypes contextualTypes(
750 QQmlJS::ContextualTypes::INTERNAL,
751 { { self->internalName(), element }, },
752 { { self, self->internalName() }, },
754 QQmlJSScope::resolveTypes(listType, contextualTypes);
756 Q_ASSERT(listType->elementType() == self);
757 self->m_listType = listType;
760void QQmlJSScope::resolveGroup(
761 const Ptr &self,
const ConstPtr &baseType,
762 const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes)
767 Q_ASSERT(self->isComposite());
769 self->m_baseType.scope = baseType;
770 self->m_semantics = baseType->accessSemantics();
771 resolveNonEnumTypes(self, contextualTypes, usedTypes);
774QQmlJSScope::ConstPtr QQmlJSScope::findCurrentQMLScope(
const QQmlJSScope::ConstPtr &scope)
776 auto qmlScope = scope;
777 while (qmlScope && qmlScope->m_scopeType != QQmlSA::ScopeType::QMLScope)
778 qmlScope = qmlScope->parentScope();
782bool QQmlJSScope::hasProperty(
const QString &name)
const
784 return QQmlJSUtils::searchBaseAndExtensionTypes(
785 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
786 if (mode == QQmlJSScope::ExtensionNamespace)
788 return scope->m_properties.contains(name);
792QQmlJSMetaProperty QQmlJSScope::property(
const QString &name)
const
794 QQmlJSMetaProperty prop;
795 QQmlJSUtils::searchBaseAndExtensionTypes(
796 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
797 if (mode == QQmlJSScope::ExtensionNamespace)
799 const auto it = scope->m_properties.find(name);
800 if (it == scope->m_properties.end())
809
810
811
812
813
814
815QHash<QString, QQmlJSMetaProperty> QQmlJSScope::properties()
const
817 QHash<QString, QQmlJSMetaProperty> results;
818 QQmlJSUtils::searchBaseAndExtensionTypes(
819 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
820 if (mode == QQmlJSScope::ExtensionNamespace)
822 for (
auto it = scope->m_properties.constBegin();
823 it != scope->m_properties.constEnd(); it++) {
824 if (!results.contains(it.key()))
825 results.insert(it.key(), it.value());
832template <
typename Predicate>
835 QQmlJSScope::AnnotatedScope owner;
836 QQmlJSUtils::searchBaseAndExtensionTypes(
837 self, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
838 if (mode == QQmlJSScope::ExtensionNamespace)
841 owner = { scope, mode };
849QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfProperty(
const QQmlJSScope::ConstPtr &self,
852 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
853 return scope->hasOwnProperty(name);
857QQmlJSScope::AnnotatedScope QQmlJSScope::ownerOfMethod(
const QQmlJSScope::ConstPtr &self,
860 return searchOwner(self, [&name](
const QQmlJSScope::ConstPtr &scope) {
861 return scope->hasOwnMethod(name);
865void QQmlJSScope::setPropertyLocallyRequired(
const QString &name,
bool isRequired)
868 m_requiredPropertyNames.removeOne(name);
869 else if (!m_requiredPropertyNames.contains(name))
870 m_requiredPropertyNames.append(name);
873bool QQmlJSScope::isPropertyRequired(
const QString &name)
const
875 bool isRequired =
false;
876 QQmlJSUtils::searchBaseAndExtensionTypes(
877 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
878 if (scope->isPropertyLocallyRequired(name)) {
885 if (mode == QQmlJSScope::ExtensionNamespace)
891 return scope->hasOwnProperty(name);
896bool QQmlJSScope::isPropertyLocallyRequired(
const QString &name)
const
898 return m_requiredPropertyNames.contains(name);
901void QQmlJSScope::addOwnPropertyBinding(
const QQmlJSMetaPropertyBinding &binding, BindingTargetSpecifier specifier)
903 Q_ASSERT(binding.sourceLocation().isValid());
904 m_propertyBindings.insert(binding.propertyName(), binding);
908 using iter =
typename QMultiHash<QString, QQmlJSMetaPropertyBinding>::iterator;
909 std::pair<iter, iter> r = m_propertyBindings.equal_range(binding.propertyName());
910 std::rotate(r.first, std::next(r.first), r.second);
913 addOwnPropertyBindingInQmlIROrder(binding, specifier);
914 Q_ASSERT(m_propertyBindings.size() == m_propertyBindingsArray.size());
917void QQmlJSScope::addOwnPropertyBindingInQmlIROrder(
const QQmlJSMetaPropertyBinding &binding,
918 BindingTargetSpecifier specifier)
927 static_assert(QTypeInfo<QQmlJSScope::QmlIRCompatibilityBindingData>::isRelocatable,
928 "We really want T to be relocatable as it improves QList<T> performance");
931 case BindingTargetSpecifier::SimplePropertyTarget: {
932 m_propertyBindingsArray.emplaceFront(binding.propertyName(),
933 binding.sourceLocation().offset);
936 case BindingTargetSpecifier::ListPropertyTarget: {
937 const auto bindingOnTheSameProperty =
938 [&](
const QQmlJSScope::QmlIRCompatibilityBindingData &x) {
939 return x.propertyName == binding.propertyName();
945 auto pos = std::find_if_not(m_propertyBindingsArray.begin(), m_propertyBindingsArray.end(),
946 bindingOnTheSameProperty);
947 Q_ASSERT(pos == m_propertyBindingsArray.begin()
948 || std::prev(pos)->propertyName == binding.propertyName());
949 m_propertyBindingsArray.emplace(pos, binding.propertyName(),
950 binding.sourceLocation().offset);
953 case BindingTargetSpecifier::UnnamedPropertyTarget: {
956 m_propertyBindingsArray.emplaceBack(
957 binding.propertyName(), binding.sourceLocation().offset);
967QList<QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindingsInQmlIROrder()
const
969 QList<QQmlJSMetaPropertyBinding> qmlIrOrdered;
970 qmlIrOrdered.reserve(m_propertyBindingsArray.size());
972 for (
const auto &data : m_propertyBindingsArray) {
973 const auto [first, last] = m_propertyBindings.equal_range(data.propertyName);
974 Q_ASSERT(first != last);
975 auto binding = std::find_if(first, last, [&](
const QQmlJSMetaPropertyBinding &x) {
976 return x.sourceLocation().offset == data.sourceLocationOffset;
978 Q_ASSERT(binding != last);
979 qmlIrOrdered.append(*binding);
985bool QQmlJSScope::hasPropertyBindings(
const QString &name)
const
987 return QQmlJSUtils::searchBaseAndExtensionTypes(
988 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
989 if (mode != QQmlJSScope::NotExtension) {
990 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
993 return scope->hasOwnPropertyBindings(name);
997QList<QQmlJSMetaPropertyBinding> QQmlJSScope::propertyBindings(
const QString &name)
const
999 QList<QQmlJSMetaPropertyBinding> bindings;
1000 QQmlJSUtils::searchBaseAndExtensionTypes(
1001 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1002 if (mode != QQmlJSScope::NotExtension) {
1003 Q_ASSERT(!scope->hasOwnPropertyBindings(name));
1006 const auto range = scope->ownPropertyBindings(name);
1007 for (
auto it = range.first; it != range.second; ++it)
1008 bindings.append(*it);
1014bool QQmlJSScope::hasInterface(
const QString &name)
const
1016 return QQmlJSUtils::searchBaseAndExtensionTypes(
1017 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1018 if (mode != QQmlJSScope::NotExtension)
1020 return scope->m_interfaceNames.contains(name);
1024bool QQmlJSScope::isNameDeferred(
const QString &name)
const
1026 bool isDeferred =
false;
1028 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1029 const QStringList immediate = scope->ownImmediateNames();
1030 if (!immediate.isEmpty()) {
1031 isDeferred = !immediate.contains(name);
1034 const QStringList deferred = scope->ownDeferredNames();
1035 if (!deferred.isEmpty()) {
1036 isDeferred = deferred.contains(name);
1045void QQmlJSScope::setBaseTypeName(
const QString &baseTypeName)
1047 m_flags.setFlag(HasBaseTypeError,
false);
1048 m_baseTypeNameOrError = baseTypeName;
1051QString QQmlJSScope::baseTypeName()
const
1053 return m_flags.testFlag(HasBaseTypeError) ? QString() : m_baseTypeNameOrError;
1056void QQmlJSScope::setBaseTypeError(
const QString &baseTypeError)
1058 m_flags.setFlag(HasBaseTypeError);
1059 m_baseTypeNameOrError = baseTypeError;
1063
1064
1065
1066
1067
1068QString QQmlJSScope::moduleName()
const
1070 for (
const QQmlJSScope *it =
this; it; it = it->parentScope().get()) {
1071 const QString name = it->ownModuleName();
1072 if (!name.isEmpty())
1078QString QQmlJSScope::baseTypeError()
const
1080 return m_flags.testFlag(HasBaseTypeError) ? m_baseTypeNameOrError : QString();
1083QString QQmlJSScope::attachedTypeName()
const
1086 QQmlJSUtils::searchBaseAndExtensionTypes(
1087 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1088 if (mode != QQmlJSScope::NotExtension)
1090 if (scope->ownAttachedType().isNull())
1092 name = scope->ownAttachedTypeName();
1099QQmlJSScope::ConstPtr QQmlJSScope::attachedType()
const
1101 QQmlJSScope::ConstPtr ptr;
1102 QQmlJSUtils::searchBaseAndExtensionTypes(
1103 this, [&](
const QQmlJSScope *scope, QQmlJSScope::ExtensionKind mode) {
1104 if (mode != QQmlJSScope::NotExtension)
1106 if (scope->ownAttachedType().isNull())
1108 ptr = scope->ownAttachedType();
1115QQmlJSScope::AnnotatedScope QQmlJSScope::extensionType()
const
1117 if (!m_extensionType)
1118 return { m_extensionType, NotExtension };
1119 if (m_flags & ExtensionIsJavaScript)
1120 return { m_extensionType, ExtensionJavaScript };
1121 if (m_flags & ExtensionIsNamespace)
1122 return { m_extensionType, ExtensionNamespace };
1123 return { m_extensionType, ExtensionType };
1126void QQmlJSScope::addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index)
1128 m_runtimeFunctionIndices.emplaceBack(index);
1131bool QQmlJSScope::isResolved()
const
1133 const bool nameIsEmpty = (m_scopeType == ScopeType::AttachedPropertyScope
1134 || m_scopeType == ScopeType::GroupedPropertyScope)
1135 ? m_internalName.isEmpty()
1136 : m_baseTypeNameOrError.isEmpty();
1139 if (m_baseType.scope.isNull())
1141 if (isComposite() && !nonCompositeBaseType(baseType()))
1146QString QQmlJSScope::defaultPropertyName()
const
1149 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1150 name = scope->ownDefaultPropertyName();
1151 return !name.isEmpty();
1156QString QQmlJSScope::parentPropertyName()
const
1159 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1160 name = scope->ownParentPropertyName();
1161 return !name.isEmpty();
1166bool QQmlJSScope::isFullyResolved()
const
1168 bool baseResolved =
true;
1169 QQmlJSUtils::searchBaseAndExtensionTypes(
this, [&](
const QQmlJSScope *scope) {
1170 if (!scope->isResolved()) {
1171 baseResolved =
false;
1177 return baseResolved;
1180QQmlJSScope::Export::Export(
1181 QString package, QString type, QTypeRevision version, QTypeRevision revision)
1182 : m_package(std::move(package))
1183 , m_type(std::move(type))
1184 , m_version(std::move(version))
1185 , m_revision(std::move(revision))
1189bool QQmlJSScope::Export::isValid()
const
1191 return m_version.isValid() || !m_package.isEmpty() || !m_type.isEmpty();
1194QDeferredFactory<QQmlJSScope>::QDeferredFactory(QQmlJSImporter *importer,
const TypeReader &typeReader,
1195 const QString &filePath,
const QString &moduleName,
bool isSingleton)
1196 : m_importer(importer),
1197 m_typeReader(typeReader ? typeReader
1198 : [](QQmlJSImporter *importer,
const QString &filePath,
1199 const QSharedPointer<QQmlJSScope> &scopeToPopulate) {
1200 QQmlJSTypeReader defaultTypeReader(importer, filePath);
1201 defaultTypeReader(scopeToPopulate);
1202 return defaultTypeReader.errors();
1204 m_filePath(filePath),
1205 m_moduleName(moduleName),
1206 m_isSingleton(isSingleton)
1210void QDeferredFactory<QQmlJSScope>::populate(
const QSharedPointer<QQmlJSScope> &scope)
const
1212 scope->setOwnModuleName(m_moduleName);
1213 scope->setIsSingleton(m_isSingleton);
1215 QList<QQmlJS::DiagnosticMessage> errors = m_typeReader(m_importer, m_filePath, scope);
1216 m_importer->m_globalWarnings.append(errors);
1220
1221
1222
1223
1224
1225
1226
1227
1228bool QQmlJSScope::canAssign(
const QQmlJSScope::ConstPtr &derived)
const
1234 Q_ASSERT(!isComposite() || nonCompositeBaseType(baseType()));
1235 Q_ASSERT(nonCompositeBaseType(derived));
1239 const bool isBaseComponent = [
this]() {
1240 if (internalName() == u"QQmlComponent")
1242 else if (isComposite())
1244 for (
auto cppBase = nonCompositeBaseType(baseType()); cppBase;
1245 cppBase = cppBase->baseType()) {
1246 if (cppBase->internalName() == u"QQmlAbstractDelegateComponent")
1252 QDuplicateTracker<QQmlJSScope::ConstPtr> seen;
1253 for (
auto scope = derived; !scope.isNull() && !seen.hasSeen(scope);
1254 scope = scope->baseType()) {
1255 if (isSameType(scope))
1257 if (isBaseComponent && scope->internalName() == u"QObject"_s)
1261 if (internalName() == u"QVariant"_s || internalName() == u"QJSValue"_s)
1264 return isListProperty() && elementType()->canAssign(derived);
1268
1269
1270
1271bool QQmlJSScope::isInCustomParserParent()
const
1273 for (
const auto *scope =
this; scope; scope = scope->parentScope().get()) {
1274 if (!scope->baseType().isNull() && scope->baseType()->hasCustomParser())
1282
1283
1284
1285
1286std::optional<QString> QQmlJSScope::inlineComponentName()
const
1288 Q_ASSERT(isInlineComponent() == m_inlineComponentName.has_value());
1289 return m_inlineComponentName;
1293
1294
1295
1296
1297QQmlJSScope::InlineComponentOrDocumentRootName QQmlJSScope::enclosingInlineComponentName()
const
1299 for (
auto *type =
this; type; type = type->parentScope().get()) {
1300 if (type->isInlineComponent())
1301 return *type->inlineComponentName();
1303 return RootDocumentNameType();
1306QList<QQmlJSScope::ConstPtr> QQmlJSScope::childScopes()
const
1308 QList<QQmlJSScope::ConstPtr> result;
1309 result.reserve(m_childScopes.size());
1310 for (
const auto &child : m_childScopes)
1311 result.append(child);
1316
1317
1318
1319
1320
1321
1322bool QQmlJSScope::enforcesScopedEnums()
const
1324 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1325 if (scope->hasEnforcesScopedEnumsFlag())
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346bool QQmlJSScope::isCreatable()
const
1348 auto isCreatableNonRecursive = [](
const QQmlJSScope *scope) {
1349 return scope->hasCreatableFlag() && !scope->isSingleton()
1350 && scope->scopeType() == QQmlSA::ScopeType::QMLScope;
1353 for (
const QQmlJSScope* scope =
this; scope; scope = scope->baseType().get()) {
1354 if (!scope->isComposite()) {
1356 return isCreatableNonRecursive(scope);
1359 if (isCreatableNonRecursive(scope))
1367bool QQmlJSScope::isStructured()
const
1369 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1370 if (!scope->isComposite())
1371 return scope->hasStructuredFlag();
1376QQmlSA::Element QQmlJSScope::createQQmlSAElement(
const ConstPtr &ptr)
1378 QQmlSA::Element element;
1379 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = ptr;
1383QQmlSA::Element QQmlJSScope::createQQmlSAElement(ConstPtr &&ptr)
1385 QQmlSA::Element element;
1386 *
reinterpret_cast<QQmlJSScope::ConstPtr *>(element.m_data) = std::move(ptr);
1390const QQmlJSScope::ConstPtr &QQmlJSScope::scope(
const QQmlSA::Element &element)
1392 return *
reinterpret_cast<
const QQmlJSScope::ConstPtr *>(element.m_data);
1396QQmlJSScope::nonCompositeBaseRevision(
const ImportedScope<QQmlJSScope::ConstPtr> &scope)
1398 for (
auto base = scope; base.scope;
1399 base = { base.scope->m_baseType.scope, base.scope->m_baseType.revision }) {
1400 if (!base.scope->isComposite())
1401 return base.revision;
1407
1408
1409
1410
1411
1412
1413bool QQmlJSScope::isSameType(
const ConstPtr &otherScope)
const
1415 return this == otherScope.get()
1416 || (!
this->internalName().isEmpty()
1417 &&
this->internalName() == otherScope->internalName());
1420bool QQmlJSScope::inherits(
const ConstPtr &base)
const
1422 for (
const QQmlJSScope *scope =
this; scope; scope = scope->baseType().get()) {
1423 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)