| 1 | // Copyright (C) 2019 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 3 | |
| 4 | #ifndef QQMLJSSCOPE_P_H |
| 5 | #define QQMLJSSCOPE_P_H |
| 6 | |
| 7 | // |
| 8 | // W A R N I N G |
| 9 | // ------------- |
| 10 | // |
| 11 | // This file is not part of the Qt API. It exists purely as an |
| 12 | // implementation detail. This header file may change from version to |
| 13 | // version without notice, or even be removed. |
| 14 | // |
| 15 | // We mean it. |
| 16 | |
| 17 | #include <qtqmlcompilerexports.h> |
| 18 | |
| 19 | #include "qqmljsmetatypes_p.h" |
| 20 | #include "qdeferredpointer_p.h" |
| 21 | #include "qqmljsannotation_p.h" |
| 22 | #include "qqmlsaconstants.h" |
| 23 | #include "qqmlsa_p.h" |
| 24 | |
| 25 | #include <QtQml/private/qqmljssourcelocation_p.h> |
| 26 | |
| 27 | #include <QtCore/qfileinfo.h> |
| 28 | #include <QtCore/qhash.h> |
| 29 | #include <QtCore/qset.h> |
| 30 | #include <QtCore/qstring.h> |
| 31 | #include <QtCore/qversionnumber.h> |
| 32 | #include "qqmlsaconstants.h" |
| 33 | |
| 34 | #include <optional> |
| 35 | |
| 36 | QT_BEGIN_NAMESPACE |
| 37 | |
| 38 | class QQmlJSImporter; |
| 39 | |
| 40 | namespace QQmlJS { |
| 41 | |
| 42 | using ChildScopesIterator = QList<QDeferredSharedPointer<QQmlJSScope>>::const_iterator; |
| 43 | |
| 44 | class Export { |
| 45 | public: |
| 46 | Export() = default; |
| 47 | Export(QString package, QString type, QTypeRevision version, QTypeRevision revision); |
| 48 | |
| 49 | bool isValid() const; |
| 50 | |
| 51 | QString package() const { return m_package; } |
| 52 | QString type() const { return m_type; } |
| 53 | QTypeRevision version() const { return m_version; } |
| 54 | QTypeRevision revision() const { return m_revision; } |
| 55 | |
| 56 | private: |
| 57 | QString m_package; |
| 58 | QString m_type; |
| 59 | QTypeRevision m_version; |
| 60 | QTypeRevision m_revision; |
| 61 | }; |
| 62 | |
| 63 | template<typename Pointer> |
| 64 | struct ExportedScope { |
| 65 | Pointer scope; |
| 66 | QList<Export> exports; |
| 67 | }; |
| 68 | |
| 69 | template<typename Pointer> |
| 70 | struct ImportedScope { |
| 71 | Pointer scope; |
| 72 | QTypeRevision revision; |
| 73 | }; |
| 74 | |
| 75 | struct ContextualTypes; |
| 76 | |
| 77 | } // namespace QQmlJS |
| 78 | |
| 79 | class Q_QMLCOMPILER_EXPORT QQmlJSScope |
| 80 | { |
| 81 | friend QQmlSA::Element; |
| 82 | |
| 83 | public: |
| 84 | explicit QQmlJSScope(const QString &internalName); |
| 85 | QQmlJSScope(QQmlJSScope &&) = default; |
| 86 | QQmlJSScope &operator=(QQmlJSScope &&) = default; |
| 87 | |
| 88 | using Ptr = QDeferredSharedPointer<QQmlJSScope>; |
| 89 | using WeakPtr = QDeferredWeakPointer<QQmlJSScope>; |
| 90 | using ConstPtr = QDeferredSharedPointer<const QQmlJSScope>; |
| 91 | using WeakConstPtr = QDeferredWeakPointer<const QQmlJSScope>; |
| 92 | |
| 93 | using AccessSemantics = QQmlSA::AccessSemantics; |
| 94 | using ScopeType = QQmlSA::ScopeType; |
| 95 | |
| 96 | using InlineComponentNameType = QString; |
| 97 | using RootDocumentNameType = std::monostate; // an empty type that has std::hash |
| 98 | /*! |
| 99 | * A Hashable type to differentiate document roots from different inline components. |
| 100 | */ |
| 101 | using InlineComponentOrDocumentRootName = |
| 102 | std::variant<InlineComponentNameType, RootDocumentNameType>; |
| 103 | |
| 104 | enum Flag { |
| 105 | Creatable = 0x1, |
| 106 | Composite = 0x2, |
| 107 | JavaScriptBuiltin = 0x4, |
| 108 | Singleton = 0x8, |
| 109 | Script = 0x10, |
| 110 | CustomParser = 0x20, |
| 111 | Array = 0x40, |
| 112 | InlineComponent = 0x80, |
| 113 | WrappedInImplicitComponent = 0x100, |
| 114 | HasBaseTypeError = 0x200, |
| 115 | ExtensionIsNamespace = 0x400, |
| 116 | IsListProperty = 0x800, |
| 117 | Structured = 0x1000, |
| 118 | ExtensionIsJavaScript = 0x2000, |
| 119 | EnforcesScopedEnums = 0x4000, |
| 120 | FileRootComponent = 0x8000, |
| 121 | AssignedToUnknownProperty = 0x10000, |
| 122 | }; |
| 123 | Q_DECLARE_FLAGS(Flags, Flag) |
| 124 | Q_FLAGS(Flags); |
| 125 | |
| 126 | using Export = QQmlJS::Export; |
| 127 | template <typename Pointer> |
| 128 | using ImportedScope = QQmlJS::ImportedScope<Pointer>; |
| 129 | template <typename Pointer> |
| 130 | using ExportedScope = QQmlJS::ExportedScope<Pointer>; |
| 131 | |
| 132 | struct JavaScriptIdentifier |
| 133 | { |
| 134 | enum Kind { |
| 135 | Parameter, |
| 136 | FunctionScoped, |
| 137 | LexicalScoped, |
| 138 | Injected |
| 139 | }; |
| 140 | |
| 141 | Kind kind = FunctionScoped; |
| 142 | QQmlJS::SourceLocation location; |
| 143 | std::optional<QString> typeName; |
| 144 | bool isConst = false; |
| 145 | QQmlJSScope::WeakConstPtr scope = {}; |
| 146 | }; |
| 147 | |
| 148 | enum BindingTargetSpecifier { |
| 149 | SimplePropertyTarget, // e.g. `property int p: 42` |
| 150 | ListPropertyTarget, // e.g. `property list<Item> pList: [ Text {} ]` |
| 151 | UnnamedPropertyTarget // default property bindings, where property name is unspecified |
| 152 | }; |
| 153 | |
| 154 | template <typename Key, typename Value> |
| 155 | using QMultiHashRange = std::pair<typename QMultiHash<Key, Value>::iterator, |
| 156 | typename QMultiHash<Key, Value>::iterator>; |
| 157 | |
| 158 | static QQmlJSScope::Ptr create() { return QSharedPointer<QQmlJSScope>(new QQmlJSScope); } |
| 159 | static QQmlJSScope::Ptr create(const QString &internalName); |
| 160 | static QQmlJSScope::Ptr clone(const QQmlJSScope::ConstPtr &origin); |
| 161 | |
| 162 | static QQmlJSScope::ConstPtr findCurrentQMLScope(const QQmlJSScope::ConstPtr &scope); |
| 163 | |
| 164 | QQmlJSScope::Ptr parentScope(); |
| 165 | QQmlJSScope::ConstPtr parentScope() const; |
| 166 | static void reparent(const QQmlJSScope::Ptr &parentScope, const QQmlJSScope::Ptr &childScope); |
| 167 | |
| 168 | void insertJSIdentifier(const QString &name, const JavaScriptIdentifier &identifier); |
| 169 | QHash<QString, JavaScriptIdentifier> ownJSIdentifiers() const; |
| 170 | void insertPropertyIdentifier(const QQmlJSMetaProperty &prop); |
| 171 | |
| 172 | ScopeType scopeType() const { return m_scopeType; } |
| 173 | void setScopeType(ScopeType type) { m_scopeType = type; } |
| 174 | |
| 175 | void addOwnMethod(const QQmlJSMetaMethod &method) { m_methods.insert(key: method.methodName(), value: method); } |
| 176 | QMultiHashRange<QString, QQmlJSMetaMethod> mutableOwnMethodsRange(const QString &name) |
| 177 | { |
| 178 | return m_methods.equal_range(key: name); |
| 179 | } |
| 180 | QMultiHash<QString, QQmlJSMetaMethod> ownMethods() const { return m_methods; } |
| 181 | QList<QQmlJSMetaMethod> ownMethods(const QString &name) const { return m_methods.values(key: name); } |
| 182 | bool hasOwnMethod(const QString &name) const { return m_methods.contains(key: name); } |
| 183 | |
| 184 | bool hasMethod(const QString &name) const; |
| 185 | QHash<QString, QQmlJSMetaMethod> methods() const; |
| 186 | QList<QQmlJSMetaMethod> methods(const QString &name) const; |
| 187 | QList<QQmlJSMetaMethod> methods(const QString &name, QQmlJSMetaMethodType type) const; |
| 188 | |
| 189 | void addOwnEnumeration(const QQmlJSMetaEnum &enumeration) { m_enumerations.insert(key: enumeration.name(), value: enumeration); } |
| 190 | QHash<QString, QQmlJSMetaEnum> ownEnumerations() const { return m_enumerations; } |
| 191 | QQmlJSMetaEnum ownEnumeration(const QString &name) const { return m_enumerations.value(key: name); } |
| 192 | bool hasOwnEnumeration(const QString &name) const { return m_enumerations.contains(key: name); } |
| 193 | |
| 194 | bool hasEnumeration(const QString &name) const; |
| 195 | bool hasEnumerationKey(const QString &name) const; |
| 196 | bool hasOwnEnumerationKey(const QString &name) const; |
| 197 | QQmlJSMetaEnum enumeration(const QString &name) const; |
| 198 | QHash<QString, QQmlJSMetaEnum> enumerations() const; |
| 199 | |
| 200 | void setAnnotations(const QList<QQmlJSAnnotation> &annotation) { m_annotations = std::move(annotation); } |
| 201 | const QList<QQmlJSAnnotation> &annotations() const { return m_annotations; } |
| 202 | |
| 203 | QString filePath() const { return m_filePath; } |
| 204 | void setFilePath(const QString &file) { m_filePath = file; } |
| 205 | |
| 206 | // The name the type uses to refer to itself. Either C++ class name or base name of |
| 207 | // QML file. isComposite tells us if this is a C++ or a QML name. |
| 208 | QString internalName() const { return m_internalName; } |
| 209 | void setInternalName(const QString &internalName) { m_internalName = internalName; } |
| 210 | QString augmentedInternalName() const; |
| 211 | |
| 212 | // This returns a more user readable version of internalName / baseTypeName |
| 213 | static QString prettyName(QAnyStringView name); |
| 214 | |
| 215 | enum class IsComponentRoot : quint8 { No = 0, Yes, Maybe }; |
| 216 | IsComponentRoot componentRootStatus() const; |
| 217 | |
| 218 | void setAliases(const QStringList &aliases) { m_aliases = aliases; } |
| 219 | QStringList aliases() const { return m_aliases; } |
| 220 | |
| 221 | void setInterfaceNames(const QStringList& interfaces) { m_interfaceNames = interfaces; } |
| 222 | QStringList interfaceNames() const { return m_interfaceNames; } |
| 223 | |
| 224 | bool hasInterface(const QString &name) const; |
| 225 | bool hasOwnInterface(const QString &name) const { return m_interfaceNames.contains(str: name); } |
| 226 | |
| 227 | void setOwnDeferredNames(const QStringList &names) { m_ownDeferredNames = names; } |
| 228 | QStringList ownDeferredNames() const { return m_ownDeferredNames; } |
| 229 | void setOwnImmediateNames(const QStringList &names) { m_ownImmediateNames = names; } |
| 230 | QStringList ownImmediateNames() const { return m_ownImmediateNames; } |
| 231 | |
| 232 | bool isNameDeferred(const QString &name) const; |
| 233 | |
| 234 | // If isComposite(), this is the QML/JS name of the prototype. Otherwise it's the |
| 235 | // relevant base class (in the hierarchy starting from QObject) of a C++ type. |
| 236 | void setBaseTypeName(const QString &baseTypeName); |
| 237 | QString baseTypeName() const; |
| 238 | |
| 239 | QQmlJSScope::ConstPtr baseType() const { return m_baseType.scope; } |
| 240 | QTypeRevision baseTypeRevision() const { return m_baseType.revision; } |
| 241 | |
| 242 | QString moduleName() const; |
| 243 | QString ownModuleName() const { return m_moduleName; } |
| 244 | void setOwnModuleName(const QString &moduleName) { m_moduleName = moduleName; } |
| 245 | |
| 246 | void clearBaseType() { m_baseType = {}; } |
| 247 | void setBaseTypeError(const QString &baseTypeError); |
| 248 | QString baseTypeError() const; |
| 249 | |
| 250 | void addOwnProperty(const QQmlJSMetaProperty &prop) { m_properties.insert(key: prop.propertyName(), value: prop); } |
| 251 | QHash<QString, QQmlJSMetaProperty> ownProperties() const { return m_properties; } |
| 252 | QQmlJSMetaProperty ownProperty(const QString &name) const { return m_properties.value(key: name); } |
| 253 | bool hasOwnProperty(const QString &name) const { return m_properties.contains(key: name); } |
| 254 | |
| 255 | bool hasProperty(const QString &name) const; |
| 256 | QQmlJSMetaProperty property(const QString &name) const; |
| 257 | QHash<QString, QQmlJSMetaProperty> properties() const; |
| 258 | |
| 259 | void setPropertyLocallyRequired(const QString &name, bool isRequired); |
| 260 | bool isPropertyRequired(const QString &name) const; |
| 261 | bool isPropertyLocallyRequired(const QString &name) const; |
| 262 | |
| 263 | void addOwnPropertyBinding( |
| 264 | const QQmlJSMetaPropertyBinding &binding, |
| 265 | BindingTargetSpecifier specifier = BindingTargetSpecifier::SimplePropertyTarget); |
| 266 | QMultiHash<QString, QQmlJSMetaPropertyBinding> ownPropertyBindings() const; |
| 267 | std::pair<QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator, |
| 268 | QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator> |
| 269 | ownPropertyBindings(const QString &name) const; |
| 270 | QList<QQmlJSMetaPropertyBinding> ownPropertyBindingsInQmlIROrder() const; |
| 271 | bool hasOwnPropertyBindings(const QString &name) const; |
| 272 | |
| 273 | bool hasPropertyBindings(const QString &name) const; |
| 274 | QList<QQmlJSMetaPropertyBinding> propertyBindings(const QString &name) const; |
| 275 | |
| 276 | struct AnnotatedScope; // defined later |
| 277 | static AnnotatedScope ownerOfProperty(const QQmlJSScope::ConstPtr &self, const QString &name); |
| 278 | |
| 279 | bool isResolved() const; |
| 280 | bool isFullyResolved() const; |
| 281 | |
| 282 | QString ownDefaultPropertyName() const { return m_defaultPropertyName; } |
| 283 | void setOwnDefaultPropertyName(const QString &name) { m_defaultPropertyName = name; } |
| 284 | QString defaultPropertyName() const; |
| 285 | |
| 286 | QString ownParentPropertyName() const { return m_parentPropertyName; } |
| 287 | void setOwnParentPropertyName(const QString &name) { m_parentPropertyName = name; } |
| 288 | QString parentPropertyName() const; |
| 289 | |
| 290 | QString ownAttachedTypeName() const { return m_attachedTypeName; } |
| 291 | void setOwnAttachedTypeName(const QString &name) { m_attachedTypeName = name; } |
| 292 | QQmlJSScope::ConstPtr ownAttachedType() const { return m_attachedType; } |
| 293 | |
| 294 | QString attachedTypeName() const; |
| 295 | QQmlJSScope::ConstPtr attachedType() const; |
| 296 | |
| 297 | QString extensionTypeName() const { return m_extensionTypeName; } |
| 298 | void setExtensionTypeName(const QString &name) { m_extensionTypeName = name; } |
| 299 | enum ExtensionKind { |
| 300 | NotExtension, |
| 301 | ExtensionType, |
| 302 | ExtensionJavaScript, |
| 303 | ExtensionNamespace, |
| 304 | }; |
| 305 | struct AnnotatedScope |
| 306 | { |
| 307 | QQmlJSScope::ConstPtr scope; |
| 308 | ExtensionKind extensionSpecifier = NotExtension; |
| 309 | }; |
| 310 | AnnotatedScope extensionType() const; |
| 311 | |
| 312 | QString valueTypeName() const { return m_valueTypeName; } |
| 313 | void setValueTypeName(const QString &name) { m_valueTypeName = name; } |
| 314 | QQmlJSScope::ConstPtr valueType() const { return m_valueType; } |
| 315 | QQmlJSScope::ConstPtr listType() const { return m_listType; } |
| 316 | QQmlJSScope::Ptr listType() { return m_listType; } |
| 317 | |
| 318 | void addOwnRuntimeFunctionIndex(QQmlJSMetaMethod::AbsoluteFunctionIndex index); |
| 319 | QQmlJSMetaMethod::AbsoluteFunctionIndex |
| 320 | ownRuntimeFunctionIndex(QQmlJSMetaMethod::RelativeFunctionIndex index) const; |
| 321 | |
| 322 | |
| 323 | /*! |
| 324 | * \internal |
| 325 | * |
| 326 | * Returns true for objects defined from Qml, and false for objects declared from C++. |
| 327 | */ |
| 328 | bool isComposite() const { return m_flags.testFlag(flag: Composite); } |
| 329 | void setIsComposite(bool v) { m_flags.setFlag(flag: Composite, on: v); } |
| 330 | |
| 331 | /*! |
| 332 | * \internal |
| 333 | * |
| 334 | * Returns true for JavaScript types, false for QML and C++ types. |
| 335 | */ |
| 336 | bool isJavaScriptBuiltin() const { return m_flags.testFlag(flag: JavaScriptBuiltin); } |
| 337 | void setIsJavaScriptBuiltin(bool v) { m_flags.setFlag(flag: JavaScriptBuiltin, on: v); } |
| 338 | |
| 339 | bool isScript() const { return m_flags.testFlag(flag: Script); } |
| 340 | void setIsScript(bool v) { m_flags.setFlag(flag: Script, on: v); } |
| 341 | |
| 342 | bool hasCustomParser() const { return m_flags.testFlag(flag: CustomParser); } |
| 343 | void setHasCustomParser(bool v) { m_flags.setFlag(flag: CustomParser, on: v); } |
| 344 | |
| 345 | bool isArrayScope() const { return m_flags.testFlag(flag: Array); } |
| 346 | void setIsArrayScope(bool v) { m_flags.setFlag(flag: Array, on: v); } |
| 347 | |
| 348 | bool isInlineComponent() const { return m_flags.testFlag(flag: InlineComponent); } |
| 349 | void setIsInlineComponent(bool v) { m_flags.setFlag(flag: InlineComponent, on: v); } |
| 350 | |
| 351 | bool isWrappedInImplicitComponent() const { return m_flags.testFlag(flag: WrappedInImplicitComponent); } |
| 352 | void setIsWrappedInImplicitComponent(bool v) { m_flags.setFlag(flag: WrappedInImplicitComponent, on: v); } |
| 353 | |
| 354 | bool isAssignedToUnknownProperty() const { return m_flags.testFlag(flag: AssignedToUnknownProperty); } |
| 355 | void setAssignedToUnknownProperty(bool v) { m_flags.setFlag(flag: AssignedToUnknownProperty, on: v); } |
| 356 | |
| 357 | bool extensionIsJavaScript() const { return m_flags.testFlag(flag: ExtensionIsJavaScript); } |
| 358 | void setExtensionIsJavaScript(bool v) { m_flags.setFlag(flag: ExtensionIsJavaScript, on: v); } |
| 359 | |
| 360 | bool extensionIsNamespace() const { return m_flags.testFlag(flag: ExtensionIsNamespace); } |
| 361 | void setExtensionIsNamespace(bool v) { m_flags.setFlag(flag: ExtensionIsNamespace, on: v); } |
| 362 | |
| 363 | bool isListProperty() const { return m_flags.testFlag(flag: IsListProperty); } |
| 364 | void setIsListProperty(bool v) { m_flags.setFlag(flag: IsListProperty, on: v); } |
| 365 | |
| 366 | bool isSingleton() const { return m_flags.testFlag(flag: Singleton); } |
| 367 | void setIsSingleton(bool v) { m_flags.setFlag(flag: Singleton, on: v); } |
| 368 | |
| 369 | bool enforcesScopedEnums() const; |
| 370 | void setEnforcesScopedEnumsFlag(bool v) { m_flags.setFlag(flag: EnforcesScopedEnums, on: v); } |
| 371 | |
| 372 | bool isCreatable() const; |
| 373 | void setCreatableFlag(bool v) { m_flags.setFlag(flag: Creatable, on: v); } |
| 374 | |
| 375 | bool isStructured() const; |
| 376 | void setStructuredFlag(bool v) { m_flags.setFlag(flag: Structured, on: v); } |
| 377 | |
| 378 | bool isFileRootComponent() const { return m_flags.testFlag(flag: FileRootComponent); } |
| 379 | void setIsRootFileComponentFlag(bool v) { m_flags.setFlag(flag: FileRootComponent, on: v); } |
| 380 | |
| 381 | void setAccessSemantics(AccessSemantics semantics) { m_semantics = semantics; } |
| 382 | AccessSemantics accessSemantics() const { return m_semantics; } |
| 383 | bool isReferenceType() const { return m_semantics == QQmlJSScope::AccessSemantics::Reference; } |
| 384 | bool isValueType() const { return m_semantics == QQmlJSScope::AccessSemantics::Value; } |
| 385 | |
| 386 | std::optional<JavaScriptIdentifier> jsIdentifier(const QString &id) const; |
| 387 | std::optional<JavaScriptIdentifier> ownJSIdentifier(const QString &id) const; |
| 388 | |
| 389 | QQmlJS::ChildScopesIterator childScopesBegin() const { return m_childScopes.constBegin(); } |
| 390 | QQmlJS::ChildScopesIterator childScopesEnd() const { return m_childScopes.constEnd(); } |
| 391 | |
| 392 | void setInlineComponentName(const QString &inlineComponentName); |
| 393 | std::optional<QString> inlineComponentName() const; |
| 394 | InlineComponentOrDocumentRootName enclosingInlineComponentName() const; |
| 395 | |
| 396 | QList<QQmlJSScope::Ptr> childScopes(); |
| 397 | |
| 398 | QList<QQmlJSScope::ConstPtr> childScopes() const; |
| 399 | |
| 400 | static QTypeRevision resolveTypes( |
| 401 | const Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
| 402 | QSet<QString> *usedTypes = nullptr); |
| 403 | static void resolveNonEnumTypes( |
| 404 | const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
| 405 | QSet<QString> *usedTypes = nullptr); |
| 406 | static void resolveEnums( |
| 407 | const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
| 408 | QSet<QString> *usedTypes = nullptr); |
| 409 | static void resolveList( |
| 410 | const QQmlJSScope::Ptr &self, const QQmlJSScope::ConstPtr &arrayType); |
| 411 | static void resolveGroup( |
| 412 | const QQmlJSScope::Ptr &self, const QQmlJSScope::ConstPtr &baseType, |
| 413 | const QQmlJS::ContextualTypes &contextualTypes, |
| 414 | QSet<QString> *usedTypes = nullptr); |
| 415 | |
| 416 | void setSourceLocation(const QQmlJS::SourceLocation &sourceLocation); |
| 417 | QQmlJS::SourceLocation sourceLocation() const; |
| 418 | |
| 419 | void setIdSourceLocation(const QQmlJS::SourceLocation &sourceLocation); |
| 420 | QQmlJS::SourceLocation idSourceLocation() const; |
| 421 | |
| 422 | static QQmlJSScope::ConstPtr nonCompositeBaseType(const QQmlJSScope::ConstPtr &type); |
| 423 | |
| 424 | static QTypeRevision |
| 425 | nonCompositeBaseRevision(const ImportedScope<QQmlJSScope::ConstPtr> &scope); |
| 426 | |
| 427 | bool isSameType(const QQmlJSScope::ConstPtr &otherScope) const; |
| 428 | bool inherits(const QQmlJSScope::ConstPtr &base) const; |
| 429 | bool canAssign(const QQmlJSScope::ConstPtr &derived) const; |
| 430 | |
| 431 | bool isInCustomParserParent() const; |
| 432 | |
| 433 | |
| 434 | static ImportedScope<QQmlJSScope::ConstPtr> findType(const QString &name, |
| 435 | const QQmlJS::ContextualTypes &contextualTypes, |
| 436 | QSet<QString> *usedTypes = nullptr); |
| 437 | |
| 438 | static QQmlSA::Element createQQmlSAElement(const ConstPtr &); |
| 439 | static QQmlSA::Element createQQmlSAElement(ConstPtr &&); |
| 440 | static const QQmlJSScope::ConstPtr &scope(const QQmlSA::Element &); |
| 441 | static constexpr qsizetype sizeofQQmlSAElement() { return QQmlSA::Element::sizeofElement; } |
| 442 | |
| 443 | private: |
| 444 | /*! \internal |
| 445 | |
| 446 | Minimal information about a QQmlJSMetaPropertyBinding that allows it to |
| 447 | be manipulated similarly to QmlIR::Binding. |
| 448 | */ |
| 449 | template <typename T> |
| 450 | friend class QTypeInfo; // so that we can Q_DECLARE_TYPEINFO QmlIRCompatibilityBindingData |
| 451 | struct QmlIRCompatibilityBindingData |
| 452 | { |
| 453 | QmlIRCompatibilityBindingData() = default; |
| 454 | QmlIRCompatibilityBindingData(const QString &name, quint32 offset) |
| 455 | : propertyName(name), sourceLocationOffset(offset) |
| 456 | { |
| 457 | } |
| 458 | QString propertyName; // bound property name |
| 459 | quint32 sourceLocationOffset = 0; // binding's source location offset |
| 460 | }; |
| 461 | |
| 462 | QQmlJSScope() = default; |
| 463 | QQmlJSScope(const QQmlJSScope &) = default; |
| 464 | QQmlJSScope &operator=(const QQmlJSScope &) = default; |
| 465 | static QTypeRevision resolveType( |
| 466 | const QQmlJSScope::Ptr &self, const QQmlJS::ContextualTypes &contextualTypes, |
| 467 | QSet<QString> *usedTypes); |
| 468 | static void updateChildScope( |
| 469 | const QQmlJSScope::Ptr &childScope, const QQmlJSScope::Ptr &self, |
| 470 | const QQmlJS::ContextualTypes &contextualTypes, QSet<QString> *usedTypes); |
| 471 | |
| 472 | void addOwnPropertyBindingInQmlIROrder(const QQmlJSMetaPropertyBinding &binding, |
| 473 | BindingTargetSpecifier specifier); |
| 474 | bool hasEnforcesScopedEnumsFlag() const { return m_flags & EnforcesScopedEnums; } |
| 475 | bool hasCreatableFlag() const { return m_flags & Creatable; } |
| 476 | bool hasStructuredFlag() const { return m_flags & Structured; } |
| 477 | |
| 478 | QHash<QString, JavaScriptIdentifier> m_jsIdentifiers; |
| 479 | |
| 480 | QMultiHash<QString, QQmlJSMetaMethod> m_methods; |
| 481 | QHash<QString, QQmlJSMetaProperty> m_properties; |
| 482 | QMultiHash<QString, QQmlJSMetaPropertyBinding> m_propertyBindings; |
| 483 | |
| 484 | // a special QmlIR compatibility bindings array, ordered the same way as |
| 485 | // bindings in QmlIR::Object |
| 486 | QList<QmlIRCompatibilityBindingData> m_propertyBindingsArray; |
| 487 | |
| 488 | // same as QmlIR::Object::runtimeFunctionIndices |
| 489 | QList<QQmlJSMetaMethod::AbsoluteFunctionIndex> m_runtimeFunctionIndices; |
| 490 | |
| 491 | QHash<QString, QQmlJSMetaEnum> m_enumerations; |
| 492 | |
| 493 | QList<QQmlJSAnnotation> m_annotations; |
| 494 | QList<QQmlJSScope::Ptr> m_childScopes; |
| 495 | QQmlJSScope::WeakPtr m_parentScope; |
| 496 | |
| 497 | QString m_filePath; |
| 498 | QString m_internalName; |
| 499 | QString m_baseTypeNameOrError; |
| 500 | |
| 501 | // We only need the revision for the base type as inheritance is |
| 502 | // the only relation between two types where the revisions matter. |
| 503 | ImportedScope<QQmlJSScope::WeakConstPtr> m_baseType; |
| 504 | |
| 505 | ScopeType m_scopeType = ScopeType::QMLScope; |
| 506 | QStringList m_aliases; |
| 507 | QStringList m_interfaceNames; |
| 508 | QStringList m_ownDeferredNames; |
| 509 | QStringList m_ownImmediateNames; |
| 510 | |
| 511 | QString m_defaultPropertyName; |
| 512 | QString m_parentPropertyName; |
| 513 | /*! \internal |
| 514 | * The attached type name. |
| 515 | * This is an internal name, from a c++ type or a synthetic jsrootgen. |
| 516 | */ |
| 517 | QString m_attachedTypeName; |
| 518 | QStringList m_requiredPropertyNames; |
| 519 | QQmlJSScope::WeakConstPtr m_attachedType; |
| 520 | |
| 521 | /*! \internal |
| 522 | * The Value type name. |
| 523 | * This is an internal name, from a c++ type or a synthetic jsrootgen. |
| 524 | */ |
| 525 | QString m_valueTypeName; |
| 526 | QQmlJSScope::WeakConstPtr m_valueType; |
| 527 | QQmlJSScope::Ptr m_listType; |
| 528 | |
| 529 | /*! |
| 530 | The extension is provided as either a type (QML_{NAMESPACE_}EXTENDED) or as a |
| 531 | namespace (QML_EXTENDED_NAMESPACE). |
| 532 | The bool HasExtensionNamespace helps differentiating both cases, as namespaces |
| 533 | have a more limited lookup capaility. |
| 534 | This is an internal name, from a c++ type or a synthetic jsrootgen. |
| 535 | */ |
| 536 | QString m_extensionTypeName; |
| 537 | QQmlJSScope::WeakConstPtr m_extensionType; |
| 538 | |
| 539 | Flags m_flags = Creatable; // all types are marked as creatable by default. |
| 540 | AccessSemantics m_semantics = AccessSemantics::Reference; |
| 541 | |
| 542 | QQmlJS::SourceLocation m_sourceLocation; |
| 543 | QQmlJS::SourceLocation m_idSourceLocation; |
| 544 | |
| 545 | QString m_moduleName; |
| 546 | |
| 547 | std::optional<QString> m_inlineComponentName; |
| 548 | }; |
| 549 | |
| 550 | inline QQmlJSScope::Ptr QQmlJSScope::parentScope() |
| 551 | { |
| 552 | return m_parentScope.toStrongRef(); |
| 553 | } |
| 554 | |
| 555 | inline QQmlJSScope::ConstPtr QQmlJSScope::parentScope() const |
| 556 | { |
| 557 | QT_WARNING_PUSH |
| 558 | #if defined(Q_CC_GNU_ONLY) && Q_CC_GNU < 1400 && Q_CC_GNU >= 1200 |
| 559 | QT_WARNING_DISABLE_GCC("-Wuse-after-free" ) |
| 560 | #endif |
| 561 | return QQmlJSScope::WeakConstPtr(m_parentScope).toStrongRef(); |
| 562 | QT_WARNING_POP |
| 563 | } |
| 564 | |
| 565 | inline QMultiHash<QString, QQmlJSMetaPropertyBinding> QQmlJSScope::ownPropertyBindings() const |
| 566 | { |
| 567 | return m_propertyBindings; |
| 568 | } |
| 569 | |
| 570 | inline std::pair<QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator, QMultiHash<QString, QQmlJSMetaPropertyBinding>::const_iterator> QQmlJSScope::ownPropertyBindings(const QString &name) const |
| 571 | { |
| 572 | return m_propertyBindings.equal_range(key: name); |
| 573 | } |
| 574 | |
| 575 | inline bool QQmlJSScope::hasOwnPropertyBindings(const QString &name) const |
| 576 | { |
| 577 | return m_propertyBindings.contains(key: name); |
| 578 | } |
| 579 | |
| 580 | inline QQmlJSMetaMethod::AbsoluteFunctionIndex QQmlJSScope::ownRuntimeFunctionIndex(QQmlJSMetaMethod::RelativeFunctionIndex index) const |
| 581 | { |
| 582 | const int i = static_cast<int>(index); |
| 583 | Q_ASSERT(i >= 0); |
| 584 | Q_ASSERT(i < int(m_runtimeFunctionIndices.size())); |
| 585 | return m_runtimeFunctionIndices[i]; |
| 586 | } |
| 587 | |
| 588 | inline void QQmlJSScope::setInlineComponentName(const QString &inlineComponentName) |
| 589 | { |
| 590 | Q_ASSERT(isInlineComponent()); |
| 591 | m_inlineComponentName = inlineComponentName; |
| 592 | } |
| 593 | |
| 594 | inline QList<QQmlJSScope::Ptr> QQmlJSScope::childScopes() |
| 595 | { |
| 596 | return m_childScopes; |
| 597 | } |
| 598 | |
| 599 | inline void QQmlJSScope::setSourceLocation(const QQmlJS::SourceLocation &sourceLocation) |
| 600 | { |
| 601 | m_sourceLocation = sourceLocation; |
| 602 | } |
| 603 | |
| 604 | inline QQmlJS::SourceLocation QQmlJSScope::sourceLocation() const |
| 605 | { |
| 606 | return m_sourceLocation; |
| 607 | } |
| 608 | |
| 609 | inline void QQmlJSScope::setIdSourceLocation(const QQmlJS::SourceLocation &sourceLocation) |
| 610 | { |
| 611 | Q_ASSERT(m_scopeType == QQmlSA::ScopeType::QMLScope); |
| 612 | m_idSourceLocation = sourceLocation; |
| 613 | } |
| 614 | |
| 615 | inline QQmlJS::SourceLocation QQmlJSScope::idSourceLocation() const |
| 616 | { |
| 617 | Q_ASSERT(m_scopeType == QQmlSA::ScopeType::QMLScope); |
| 618 | return m_idSourceLocation; |
| 619 | } |
| 620 | |
| 621 | inline QQmlJSScope::ConstPtr QQmlJSScope::nonCompositeBaseType(const ConstPtr &type) |
| 622 | { |
| 623 | for (QQmlJSScope::ConstPtr base = type; base; base = base->baseType()) { |
| 624 | if (!base->isComposite()) |
| 625 | return base; |
| 626 | } |
| 627 | return {}; |
| 628 | } |
| 629 | |
| 630 | Q_DECLARE_TYPEINFO(QQmlJSScope::QmlIRCompatibilityBindingData, Q_RELOCATABLE_TYPE); |
| 631 | |
| 632 | template<> |
| 633 | class Q_QMLCOMPILER_EXPORT QDeferredFactory<QQmlJSScope> |
| 634 | { |
| 635 | public: |
| 636 | using TypeReader = std::function<QList<QQmlJS::DiagnosticMessage>( |
| 637 | QQmlJSImporter *importer, const QString &filePath, |
| 638 | const QSharedPointer<QQmlJSScope> &scopeToPopulate)>; |
| 639 | QDeferredFactory() = default; |
| 640 | |
| 641 | QDeferredFactory(QQmlJSImporter *importer, const QString &filePath, |
| 642 | const TypeReader &typeReader = {}); |
| 643 | |
| 644 | bool isValid() const |
| 645 | { |
| 646 | return !m_filePath.isEmpty() && m_importer != nullptr; |
| 647 | } |
| 648 | |
| 649 | QString internalName() const |
| 650 | { |
| 651 | return QFileInfo(m_filePath).baseName(); |
| 652 | } |
| 653 | |
| 654 | QString filePath() const { return m_filePath; } |
| 655 | |
| 656 | QQmlJSImporter* importer() const { return m_importer; } |
| 657 | |
| 658 | void setIsSingleton(bool isSingleton) |
| 659 | { |
| 660 | m_isSingleton = isSingleton; |
| 661 | } |
| 662 | |
| 663 | void setModuleName(const QString &moduleName) { m_moduleName = moduleName; } |
| 664 | |
| 665 | private: |
| 666 | friend class QDeferredSharedPointer<QQmlJSScope>; |
| 667 | friend class QDeferredSharedPointer<const QQmlJSScope>; |
| 668 | friend class QDeferredWeakPointer<QQmlJSScope>; |
| 669 | friend class QDeferredWeakPointer<const QQmlJSScope>; |
| 670 | |
| 671 | // Should only be called when lazy-loading the type in a deferred pointer. |
| 672 | void populate(const QSharedPointer<QQmlJSScope> &scope) const; |
| 673 | |
| 674 | QString m_filePath; |
| 675 | QQmlJSImporter *m_importer = nullptr; |
| 676 | bool m_isSingleton = false; |
| 677 | QString m_moduleName; |
| 678 | TypeReader m_typeReader; |
| 679 | }; |
| 680 | |
| 681 | using QQmlJSExportedScope = QQmlJSScope::ExportedScope<QQmlJSScope::Ptr>; |
| 682 | using QQmlJSImportedScope = QQmlJSScope::ImportedScope<QQmlJSScope::ConstPtr>; |
| 683 | |
| 684 | QT_END_NAMESPACE |
| 685 | |
| 686 | #endif // QQMLJSSCOPE_P_H |
| 687 | |