diff options
Diffstat (limited to 'src/qmlcompiler/qqmljsscope_p.h')
-rw-r--r-- | src/qmlcompiler/qqmljsscope_p.h | 694 |
1 files changed, 694 insertions, 0 deletions
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h new file mode 100644 index 0000000000..b0bc6818a3 --- /dev/null +++ b/src/qmlcompiler/qqmljsscope_p.h @@ -0,0 +1,694 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef QQMLJSSCOPE_P_H +#define QQMLJSSCOPE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include <qtqmlcompilerexports.h> + +#include "qqmljsmetatypes_p.h" +#include "qdeferredpointer_p.h" +#include "qqmljsannotation_p.h" +#include "qqmlsaconstants.h" +#include "qqmlsa_p.h" + +#include <QtQml/private/qqmljssourcelocation_p.h> + +#include <QtCore/qfileinfo.h> +#include <QtCore/qhash.h> +#include <QtCore/qset.h> +#include <QtCore/qstring.h> +#include <QtCore/qversionnumber.h> +#include "qqmlsaconstants.h" + +#include <optional> + +QT_BEGIN_NAMESPACE + +class QQmlJSImporter; + +namespace QQmlJS { + +class ConstPtrWrapperIterator +{ +public: + using Ptr = QDeferredSharedPointer<QQmlJSScope>; + using ConstPtr = QDeferredSharedPointer<const QQmlJSScope>; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = ConstPtr; + using pointer = value_type *; + using reference = value_type &; + + ConstPtrWrapperIterator(QList<Ptr>::const_iterator iterator) : m_iterator(iterator) { } + + friend bool operator==(const ConstPtrWrapperIterator &a, const ConstPtrWrapperIterator &b) + { + return a.m_iterator == b.m_iterator; + } + friend bool operator!=(const ConstPtrWrapperIterator &a, const ConstPtrWrapperIterator &b) + { + return a.m_iterator != b.m_iterator; + } + + reference operator*() + { + if (!m_pointer) + m_pointer = *m_iterator; + return m_pointer; + } + pointer operator->() + { + if (!m_pointer) + m_pointer = *m_iterator; + return &m_pointer; + } + + ConstPtrWrapperIterator &operator++() + { + m_iterator++; + m_pointer = {}; + return *this; + } + ConstPtrWrapperIterator operator++(int) + { + auto before = *this; + ++(*this); + return before; + } + +private: + QList<Ptr>::const_iterator m_iterator; + ConstPtr m_pointer; +}; + +class Export { +public: + Export() = default; + Export(QString package, QString type, QTypeRevision version, QTypeRevision revision); + + bool isValid() const; + + QString package() const { return m_package; } + QString type() const { return m_type; } + QTypeRevision version() const { return m_version; } + QTypeRevision revision() const { return m_revision; } + +private: + QString m_package; + QString m_type; + QTypeRevision m_version; + QTypeRevision m_revision; +}; + +template<typename Pointer> +struct ExportedScope { + Pointer scope; + QList<Export> exports; +}; + +template<typename Pointer> +struct ImportedScope { + Pointer scope; + QTypeRevision revision; +}; + +struct ContextualTypes; + +} // namespace QQmlJS + +class Q_QMLCOMPILER_EXPORT QQmlJSScope +{ + friend QQmlSA::Element; + +public: + explicit QQmlJSScope(const QString &internalName); + QQmlJSScope(QQmlJSScope &&) = default; + QQmlJSScope &operator=(QQmlJSScope &&) = default; + + using Ptr = QDeferredSharedPointer<QQmlJSScope>; + using WeakPtr = QDeferredWeakPointer<QQmlJSScope>; + using ConstPtr = QDeferredSharedPointer<const QQmlJSScope>; + using WeakConstPtr = QDeferredWeakPointer<const QQmlJSScope>; + + using AccessSemantics = QQmlSA::AccessSemantics; + using ScopeType = QQmlSA::ScopeType; + + using InlineComponentNameType = QString; + using RootDocumentNameType = std::monostate; // an empty type that has std::hash + /*! + * A Hashable type to differentiate document roots from different inline components. + */ + using InlineComponentOrDocumentRootName = + std::variant<InlineComponentNameType, RootDocumentNameType>; + + enum Flag { + Creatable = 0x1, + Composite = 0x2, + Singleton = 0x4, + Script = 0x8, + CustomParser = 0x10, + Array = 0x20, + InlineComponent = 0x40, + WrappedInImplicitComponent = 0x80, + HasBaseTypeError = 0x100, + ExtensionIsNamespace = 0x200, + IsListProperty = 0x400, + Structured = 0x800, + ExtensionIsJavaScript = 0x1000, + }; + Q_DECLARE_FLAGS(Flags, Flag) + Q_FLAGS(Flags); + + using Export = QQmlJS::Export; + template <typename Pointer> + using ImportedScope = QQmlJS::ImportedScope<Pointer>; + template <typename Pointer> + using ExportedScope = QQmlJS::ExportedScope<Pointer>; + + struct JavaScriptIdentifier + { + enum Kind { + Parameter, + FunctionScoped, + LexicalScoped, + Injected + }; + + Kind kind = FunctionScoped; + QQmlJS::SourceLocation location; + std::optional<QString> typeName; + bool isConst = false; + QQmlJSScope::WeakConstPtr scope = {}; + }; + + enum BindingTargetSpecifier { + SimplePropertyTarget, // e.g. `property int p: 42` + ListPropertyTarget, // e.g. `property list<Item> pList: [ Text {} ]` + UnnamedPropertyTarget // default property bindings, where property name is unspecified + }; + + template <typename Key, typename Value> + using QMultiHashRange = QPair<typename QMultiHash<Key, Value>::iterator, + typename QMultiHash<Key, Value>::iterator>; + + static QQmlJSScope::Ptr create() { return QSharedPointer<QQmlJSScope>(new QQmlJSScope); } + static QQmlJSScope::Ptr create(const QString &internalName); + static QQmlJSScope::Ptr clone(const QQmlJSScope::ConstPtr &origin); + + static QQmlJSScope::ConstPtr findCurrentQMLScope(const QQmlJSScope::ConstPtr &scope); + + QQmlJSScope::Ptr parentScope(); + QQmlJSScope::ConstPtr parentScope() const; + static void reparent(const QQmlJSScope::Ptr &parentScope, const QQmlJSScope::Ptr &childScope); + + void insertJSIdentifier(const QString &name, const JavaScriptIdentifier &identifier); + QHash<QString, JavaScriptIdentifier> ownJSIdentifiers() const; + void insertPropertyIdentifier(const QQmlJSMetaProperty &prop); + + ScopeType scopeType() const { return m_scopeType; } + void setScopeType(ScopeType type) { m_scopeType = type; } + + void addOwnMethod(const QQmlJSMetaMethod &method) { m_methods.insert(method.methodName(), method); } + QMultiHashRange<QString, QQmlJSMetaMethod> mutableOwnMethodsRange(const QString &name) + { + return m_methods.equal_range(name); + } + QMultiHash<QString, QQmlJSMetaMethod> ownMethods() const { return m_methods; } + QList<QQmlJSMetaMethod> ownMethods(const QString &name) const { return m_methods.values(name); } + bool hasOwnMethod(const QString &name) const { return m_methods.contains(name); } + + bool hasMethod(const QString &name) const; + QHash<QString, QQmlJSMetaMethod> methods() const; + QList<QQmlJSMetaMethod> methods(const QString &name) const; + QList<QQmlJSMetaMethod> methods(const QString &name, QQmlJSMetaMethodType type) const; + + void addOwnEnumeration(const QQmlJSMetaEnum &enumeration) { m_enumerations.insert(enumeration.name(), enumeration); } + QHash<QString, QQmlJSMetaEnum> ownEnumerations() const { return m_enumerations; } + QQmlJSMetaEnum ownEnumeration(const QString &name) const { return m_enumerations.value(name); } + bool hasOwnEnumeration(const QString &name) const { return m_enumerations.contains(name); } + + bool hasEnumeration(const QString &name) const; + bool hasEnumerationKey(const QString &name) const; + bool hasOwnEnumerationKey(const QString &name) const; + QQmlJSMetaEnum enumeration(const QString &name) const; + QHash<QString, QQmlJSMetaEnum> enumerations() const; + + void setAnnotations(const QList<QQmlJSAnnotation> &annotation) { m_annotations = std::move(annotation); } + const QList<QQmlJSAnnotation> &annotations() const { return m_annotations; } + + QString filePath() const { return m_filePath; } + void setFilePath(const QString &file) { m_filePath = file; } + + // The name the type uses to refer to itself. Either C++ class name or base name of + // QML file. isComposite tells us if this is a C++ or a QML name. + QString internalName() const { return m_internalName; } + void setInternalName(const QString &internalName) { m_internalName = internalName; } + QString augmentedInternalName() const; + + // This returns a more user readable version of internalName / baseTypeName + static QString prettyName(QAnyStringView name); + + bool isComponentRootElement() const; + + void setAliases(const QStringList &aliases) { m_aliases = aliases; } + QStringList aliases() const { return m_aliases; } + + void setInterfaceNames(const QStringList& interfaces) { m_interfaceNames = interfaces; } + QStringList interfaceNames() const { return m_interfaceNames; } + + bool hasInterface(const QString &name) const; + bool hasOwnInterface(const QString &name) const { return m_interfaceNames.contains(name); } + + void setOwnDeferredNames(const QStringList &names) { m_ownDeferredNames = names; } + QStringList ownDeferredNames() const { return m_ownDeferredNames; } + void setOwnImmediateNames(const QStringList &names) { m_ownImmediateNames = names; } + QStringList ownImmediateNames() const { return m_ownImmediateNames; } + + bool isNameDeferred(const QString &name) const; + + // If isComposite(), this is the QML/JS name of the prototype. Otherwise it's the + // relevant base class (in the hierarchy starting from QObject) of a C++ type. + void setBaseTypeName(const QString &baseTypeName); + QString baseTypeName() const; + + QQmlJSScope::ConstPtr baseType() const { return m_baseType.scope; } + QTypeRevision baseTypeRevision() const { return m_baseType.revision; } + + QString moduleName() const; + QString ownModuleName() const { return m_moduleName; } + void setOwnModuleName(const QString &moduleName) { m_moduleName = moduleName; } + + void clearBaseType() { m_baseType = {}; } + void setBaseTypeError(const QString &baseTypeError); + QString baseTypeError() const; + + void addOwnProperty(const QQmlJSMetaProperty &prop) { m_properties.insert(prop.propertyName(), prop); } + QHash<QString, QQmlJSMetaProperty> ownProperties() const { return m_properties; } + QQmlJSMetaProperty ownProperty(const QString &name) const { return m_properties.value(name); } + bool hasOwnProperty(const QString &name) const { return m_properties.contains(name); } + + bool hasProperty(const QString &name) const; + QQmlJSMetaProperty property(const QString &name) const; + QHash<QString, QQmlJSMetaProperty> properties() const; + + void setPropertyLocallyRequired(const QString &name, bool isRequired); + bool isPropertyRequired(const QString &name) const; + bool isPropertyLocallyRequired(const QString &name) const; + + void addOwnPropertyBinding( + const QQmlJSMetaPropertyBinding &binding, + BindingTargetSpecifier specifier = BindingTargetSpecifier::SimplePropertyTarget); + QMultiHash<QString, QQmlJSMetaPropertyBinding> ownPropertyBindings() const; + QPair<QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator, + QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator> + ownPropertyBindings(const QString &name) const; + QList<QQmlJSMetaPropertyBinding> ownPropertyBindingsInQmlIROrder() const; + bool hasOwnPropertyBindings(const QString &name) const; + + bool hasPropertyBindings(const QString &name) const; + QList<QQmlJSMetaPropertyBinding> propertyBindings(const QString &name) const; + + struct AnnotatedScope; // defined later + static AnnotatedScope ownerOfProperty(const QQmlJSScope::ConstPtr &self, const QString &name); + + bool isResolved() const; + bool isFullyResolved() const; + + QString ownDefaultPropertyName() const { return m_defaultPropertyName; } + void setOwnDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; } + QString defaultPropertyName() const; + + QString ownParentPropertyName() const { return m_parentPropertyName; } + void setOwnParentPropertyName(const QString &name) { m_parentPropertyName = name; } + QString parentPropertyName() const; + + QString ownAttachedTypeName() const { return m_attachedTypeName; } + void setOwnAttachedTypeName(const QString &name) { m_attachedTypeName = name; } + QQmlJSScope::ConstPtr ownAttachedType() const { return m_attachedType; } + + QString attachedTypeName() const; + QQmlJSScope::ConstPtr attachedType() const; + + QString extensionTypeName() const { return m_extensionTypeName; } + void setExtensionTypeName(const QString &name) { m_extensionTypeName = name; } + enum ExtensionKind { + NotExtension, + ExtensionType, + ExtensionJavaScript, + ExtensionNamespace, + }; + struct AnnotatedScope + { + QQmlJSScope::ConstPtr scope; + ExtensionKind extensionSpecifier = NotExtension; + }; + AnnotatedScope extensionType() const; + + QString valueTypeName() const { return m_valueTypeName; } + void setValueTypeName(const QString &name) { m_valueTypeName = name; } + QQmlJSScope::ConstPtr valueType() const { return m_valueType; } + QQmlJSScope::ConstPtr listType() const { return m_listType; } + QQmlJSScope::Ptr listType() { return m_listType; } + + void addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index); + QQmlJSMetaMethod::AbsoluteFunctionIndex + ownRuntimeFunctionIndex(QQmlJSMetaMethod::RelativeFunctionIndex index) const; + + + /*! + * \internal + * + * Returns true for objects defined from Qml, and false for objects declared from C++. + */ + bool isComposite() const { return m_flags & Composite; } + bool isScript() const { return m_flags & Script; } + bool hasCustomParser() const { return m_flags & CustomParser; } + bool isArrayScope() const { return m_flags & Array; } + bool isInlineComponent() const { return m_flags & InlineComponent; } + bool isWrappedInImplicitComponent() const { return m_flags & WrappedInImplicitComponent; } + bool extensionIsJavaScript() const { return m_flags & ExtensionIsJavaScript; } + bool extensionIsNamespace() const { return m_flags & ExtensionIsNamespace; } + bool isListProperty() const { return m_flags.testFlag(IsListProperty); } + void setIsListProperty(bool v) { m_flags.setFlag(IsListProperty, v); } + bool isSingleton() const { return m_flags & Singleton; } + bool isCreatable() const; + bool isStructured() const; + bool isReferenceType() const { return m_semantics == QQmlJSScope::AccessSemantics::Reference; } + bool isValueType() const { return m_semantics == QQmlJSScope::AccessSemantics::Value; } + + void setIsSingleton(bool v) { m_flags.setFlag(Singleton, v); } + void setCreatableFlag(bool v) { m_flags.setFlag(Creatable, v); } + void setStructuredFlag(bool v) { m_flags.setFlag(Structured, v); } + void setIsComposite(bool v) { m_flags.setFlag(Composite, v); } + void setIsScript(bool v) { m_flags.setFlag(Script, v); } + void setHasCustomParser(bool v); + void setIsArrayScope(bool v) { m_flags.setFlag(Array, v); } + void setIsInlineComponent(bool v) { m_flags.setFlag(InlineComponent, v); } + void setIsWrappedInImplicitComponent(bool v) { m_flags.setFlag(WrappedInImplicitComponent, v); } + void setExtensionIsJavaScript(bool v) { m_flags.setFlag(ExtensionIsJavaScript, v); } + void setExtensionIsNamespace(bool v) { m_flags.setFlag(ExtensionIsNamespace, v); } + + + void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; } + AccessSemantics accessSemantics() const { return m_semantics; } + + std::optional<JavaScriptIdentifier> jsIdentifier(const QString &id) const; + std::optional<JavaScriptIdentifier> ownJSIdentifier(const QString &id) const; + + QQmlJS::ConstPtrWrapperIterator childScopesBegin() const { return m_childScopes.constBegin(); } + QQmlJS::ConstPtrWrapperIterator childScopesEnd() const { return m_childScopes.constEnd(); } + + void setInlineComponentName(const QString &inlineComponentName); + std::optional<QString> inlineComponentName() const; + InlineComponentOrDocumentRootName enclosingInlineComponentName() const; + + QVector<QQmlJSScope::Ptr> childScopes(); + + QVector<QQmlJSScope::ConstPtr> childScopes() const; + + static QTypeRevision resolveTypes( + const Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, + QSet<QString> *usedTypes = nullptr); + static void resolveNonEnumTypes( + const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, + QSet<QString> *usedTypes = nullptr); + static void resolveEnums( + const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, + QSet<QString> *usedTypes = nullptr); + static void resolveList( + const QQmlJSScope::Ptr &self, const QQmlJSScope::ConstPtr &arrayType); + static void resolveGeneralizedGroup( + const QQmlJSScope::Ptr &self, const QQmlJSScope::ConstPtr &baseType, + const QQmlJS::ContextualTypes &contextualTypes, + QSet<QString> *usedTypes = nullptr); + + void setSourceLocation(const QQmlJS::SourceLocation &sourceLocation); + QQmlJS::SourceLocation sourceLocation() const; + + static QQmlJSScope::ConstPtr nonCompositeBaseType(const QQmlJSScope::ConstPtr &type); + + static QTypeRevision + nonCompositeBaseRevision(const ImportedScope<QQmlJSScope::ConstPtr> &scope); + + bool isSameType(const QQmlJSScope::ConstPtr &otherScope) const; + bool inherits(const QQmlJSScope::ConstPtr &base) const; + bool canAssign(const QQmlJSScope::ConstPtr &derived) const; + + bool isInCustomParserParent() const; + + + static ImportedScope<QQmlJSScope::ConstPtr> findType(const QString &name, + const QQmlJS::ContextualTypes &contextualTypes, + QSet<QString> *usedTypes = nullptr); + + static QQmlSA::Element createQQmlSAElement(const ConstPtr &); + static QQmlSA::Element createQQmlSAElement(ConstPtr &&); + static const QQmlJSScope::ConstPtr &scope(const QQmlSA::Element &); + static constexpr qsizetype sizeofQQmlSAElement() { return QQmlSA::Element::sizeofElement; } + +private: + /*! \internal + + Minimal information about a QQmlJSMetaPropertyBinding that allows it to + be manipulated similarly to QmlIR::Binding. + */ + template <typename T> + friend class QTypeInfo; // so that we can Q_DECLARE_TYPEINFO QmlIRCompatibilityBindingData + struct QmlIRCompatibilityBindingData + { + QmlIRCompatibilityBindingData() = default; + QmlIRCompatibilityBindingData(const QString &name, quint32 offset) + : propertyName(name), sourceLocationOffset(offset) + { + } + QString propertyName; // bound property name + quint32 sourceLocationOffset = 0; // binding's source location offset + }; + + QQmlJSScope() = default; + QQmlJSScope(const QQmlJSScope &) = default; + QQmlJSScope &operator=(const QQmlJSScope &) = default; + static QTypeRevision resolveType( + const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, + QSet<QString> *usedTypes); + static void updateChildScope( + const QQmlJSScope::Ptr &childScope, const QQmlJSScope::Ptr &self, + const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes); + + void addOwnPropertyBindingInQmlIROrder(const QQmlJSMetaPropertyBinding &binding, + BindingTargetSpecifier specifier); + bool hasCreatableFlag() const { return m_flags & Creatable; } + bool hasStructuredFlag() const { return m_flags & Structured; } + + QHash<QString, JavaScriptIdentifier> m_jsIdentifiers; + + QMultiHash<QString, QQmlJSMetaMethod> m_methods; + QHash<QString, QQmlJSMetaProperty> m_properties; + QMultiHash<QString, QQmlJSMetaPropertyBinding> m_propertyBindings; + + // a special QmlIR compatibility bindings array, ordered the same way as + // bindings in QmlIR::Object + QList<QmlIRCompatibilityBindingData> m_propertyBindingsArray; + + // same as QmlIR::Object::runtimeFunctionIndices + QList<QQmlJSMetaMethod::AbsoluteFunctionIndex> m_runtimeFunctionIndices; + + QHash<QString, QQmlJSMetaEnum> m_enumerations; + + QVector<QQmlJSAnnotation> m_annotations; + QVector<QQmlJSScope::Ptr> m_childScopes; + QQmlJSScope::WeakPtr m_parentScope; + + QString m_filePath; + QString m_internalName; + QString m_baseTypeNameOrError; + + // We only need the revision for the base type as inheritance is + // the only relation between two types where the revisions matter. + ImportedScope<QQmlJSScope::WeakConstPtr> m_baseType; + + ScopeType m_scopeType = ScopeType::QMLScope; + QStringList m_aliases; + QStringList m_interfaceNames; + QStringList m_ownDeferredNames; + QStringList m_ownImmediateNames; + + QString m_defaultPropertyName; + QString m_parentPropertyName; + /*! \internal + * The attached type name. + * This is an internal name, from a c++ type or a synthetic jsrootgen. + */ + QString m_attachedTypeName; + QStringList m_requiredPropertyNames; + QQmlJSScope::WeakConstPtr m_attachedType; + + /*! \internal + * The Value type name. + * This is an internal name, from a c++ type or a synthetic jsrootgen. + */ + QString m_valueTypeName; + QQmlJSScope::WeakConstPtr m_valueType; + QQmlJSScope::Ptr m_listType; + + /*! + The extension is provided as either a type (QML_{NAMESPACE_}EXTENDED) or as a + namespace (QML_EXTENDED_NAMESPACE). + The bool HasExtensionNamespace helps differentiating both cases, as namespaces + have a more limited lookup capaility. + This is an internal name, from a c++ type or a synthetic jsrootgen. + */ + QString m_extensionTypeName; + QQmlJSScope::WeakConstPtr m_extensionType; + + Flags m_flags = Creatable; // all types are marked as creatable by default. + AccessSemantics m_semantics = AccessSemantics::Reference; + + QQmlJS::SourceLocation m_sourceLocation; + + QString m_moduleName; + + std::optional<QString> m_inlineComponentName; +}; + +inline QQmlJSScope::Ptr QQmlJSScope::parentScope() +{ + return m_parentScope.toStrongRef(); +} + +inline QQmlJSScope::ConstPtr QQmlJSScope::parentScope() const +{ + QT_WARNING_PUSH +#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU < 1400 && Q_CC_GNU >= 1200 + QT_WARNING_DISABLE_GCC("-Wuse-after-free") +#endif + return QQmlJSScope::WeakConstPtr(m_parentScope).toStrongRef(); + QT_WARNING_POP +} + +inline QMultiHash<QString, QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindings() const +{ + return m_propertyBindings; +} + +inline QPair<QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator, QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator> QQmlJSScope::ownPropertyBindings(const QString &name) const +{ + return m_propertyBindings.equal_range(name); +} + +inline bool QQmlJSScope::hasOwnPropertyBindings(const QString &name) const +{ + return m_propertyBindings.contains(name); +} + +inline QQmlJSMetaMethod::AbsoluteFunctionIndex QQmlJSScope::ownRuntimeFunctionIndex(QQmlJSMetaMethod::RelativeFunctionIndex index) const +{ + const int i = static_cast<int>(index); + Q_ASSERT(i >= 0); + Q_ASSERT(i < int(m_runtimeFunctionIndices.size())); + return m_runtimeFunctionIndices[i]; +} + +inline void QQmlJSScope::setHasCustomParser(bool v) +{ + m_flags.setFlag(CustomParser, v);; +} + +inline void QQmlJSScope::setInlineComponentName(const QString &inlineComponentName) +{ + Q_ASSERT(isInlineComponent()); + m_inlineComponentName = inlineComponentName; +} + +inline QVector<QQmlJSScope::Ptr> QQmlJSScope::childScopes() +{ + return m_childScopes; +} + +inline void QQmlJSScope::setSourceLocation(const QQmlJS::SourceLocation &sourceLocation) +{ + m_sourceLocation = sourceLocation; +} + +inline QQmlJS::SourceLocation QQmlJSScope::sourceLocation() const +{ + return m_sourceLocation; +} + +inline QQmlJSScope::ConstPtr QQmlJSScope::nonCompositeBaseType(const ConstPtr &type) +{ + for (QQmlJSScope::ConstPtr base = type; base; base = base->baseType()) { + if (!base->isComposite()) + return base; + } + return {}; +} + +Q_DECLARE_TYPEINFO(QQmlJSScope::QmlIRCompatibilityBindingData, Q_RELOCATABLE_TYPE); + +template<> +class Q_QMLCOMPILER_EXPORT QDeferredFactory<QQmlJSScope> +{ +public: + using TypeReader = std::function<QList<QQmlJS::DiagnosticMessage>( + QQmlJSImporter *importer, const QString &filePath, + const QSharedPointer<QQmlJSScope> &scopeToPopulate)>; + QDeferredFactory() = default; + + QDeferredFactory(QQmlJSImporter *importer, const QString &filePath, + const TypeReader &typeReader = {}); + + bool isValid() const + { + return !m_filePath.isEmpty() && m_importer != nullptr; + } + + QString internalName() const + { + return QFileInfo(m_filePath).baseName(); + } + + QString filePath() const { return m_filePath; } + + QQmlJSImporter* importer() const { return m_importer; } + + void setIsSingleton(bool isSingleton) + { + m_isSingleton = isSingleton; + } + + void setModuleName(const QString &moduleName) { m_moduleName = moduleName; } + +private: + friend class QDeferredSharedPointer<QQmlJSScope>; + friend class QDeferredSharedPointer<const QQmlJSScope>; + friend class QDeferredWeakPointer<QQmlJSScope>; + friend class QDeferredWeakPointer<const QQmlJSScope>; + + // Should only be called when lazy-loading the type in a deferred pointer. + void populate(const QSharedPointer<QQmlJSScope> &scope) const; + + QString m_filePath; + QQmlJSImporter *m_importer = nullptr; + bool m_isSingleton = false; + QString m_moduleName; + TypeReader m_typeReader; +}; + +using QQmlJSExportedScope = QQmlJSScope::ExportedScope<QQmlJSScope::Ptr>; +using QQmlJSImportedScope = QQmlJSScope::ImportedScope<QQmlJSScope::ConstPtr>; + +QT_END_NAMESPACE + +#endif // QQMLJSSCOPE_P_H |