| 1 | // Copyright (C) 2021 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 QQMLJSREGISTERCONTENT_P_H | 
|---|
| 5 | #define QQMLJSREGISTERCONTENT_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 "qqmljsscope_p.h" | 
|---|
| 18 | #include <QtCore/qhash.h> | 
|---|
| 19 | #include <QtCore/qstring.h> | 
|---|
| 20 |  | 
|---|
| 21 | #include <variant> | 
|---|
| 22 |  | 
|---|
| 23 | QT_BEGIN_NAMESPACE | 
|---|
| 24 |  | 
|---|
| 25 | class Q_QMLCOMPILER_EXPORT QQmlJSRegisterContent | 
|---|
| 26 | { | 
|---|
| 27 | public: | 
|---|
| 28 | enum ContentVariant { | 
|---|
| 29 | ObjectById, | 
|---|
| 30 | Singleton, | 
|---|
| 31 | Script, | 
|---|
| 32 | MetaType, | 
|---|
| 33 |  | 
|---|
| 34 | JavaScriptGlobal, | 
|---|
| 35 | JavaScriptObject, | 
|---|
| 36 | JavaScriptScopeProperty, | 
|---|
| 37 | GenericObjectProperty, // Can be JSObject property or QVariantMap | 
|---|
| 38 |  | 
|---|
| 39 | ScopeProperty, | 
|---|
| 40 | ScopeMethod, | 
|---|
| 41 | ScopeAttached, | 
|---|
| 42 | ScopeModulePrefix, | 
|---|
| 43 | ExtensionScopeProperty, | 
|---|
| 44 | ExtensionScopeMethod, | 
|---|
| 45 |  | 
|---|
| 46 | ObjectProperty, | 
|---|
| 47 | ObjectMethod, | 
|---|
| 48 | ObjectEnum, | 
|---|
| 49 | ObjectAttached, | 
|---|
| 50 | ObjectModulePrefix, | 
|---|
| 51 | ExtensionObjectProperty, | 
|---|
| 52 | ExtensionObjectMethod, | 
|---|
| 53 | ExtensionObjectEnum, | 
|---|
| 54 |  | 
|---|
| 55 | MethodReturnValue, | 
|---|
| 56 | JavaScriptReturnValue, | 
|---|
| 57 |  | 
|---|
| 58 | ListValue, | 
|---|
| 59 | ListIterator, | 
|---|
| 60 | Builtin, | 
|---|
| 61 | Unknown, | 
|---|
| 62 | }; | 
|---|
| 63 |  | 
|---|
| 64 | enum { InvalidLookupIndex = -1 }; | 
|---|
| 65 |  | 
|---|
| 66 | QQmlJSRegisterContent() = default; | 
|---|
| 67 | bool isValid() const { return !m_storedType.isNull(); } | 
|---|
| 68 |  | 
|---|
| 69 | QString descriptiveName() const; | 
|---|
| 70 |  | 
|---|
| 71 | friend bool operator==(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) | 
|---|
| 72 | { | 
|---|
| 73 | return a.m_storedType == b.m_storedType && a.m_variant == b.m_variant | 
|---|
| 74 | && a.m_scope == b.m_scope && a.m_content == b.m_content; | 
|---|
| 75 | } | 
|---|
| 76 |  | 
|---|
| 77 | friend bool operator!=(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) | 
|---|
| 78 | { | 
|---|
| 79 | return !(a == b); | 
|---|
| 80 | } | 
|---|
| 81 |  | 
|---|
| 82 | bool isType() const { return m_content.index() == Type; } | 
|---|
| 83 | bool isProperty() const { return m_content.index() == Property; } | 
|---|
| 84 | bool isEnumeration() const { return m_content.index() == Enum; } | 
|---|
| 85 | bool isMethod() const { return m_content.index() == Method; } | 
|---|
| 86 | bool isImportNamespace() const { return m_content.index() == ImportNamespace; } | 
|---|
| 87 | bool isConversion() const { return m_content.index() == Conversion; } | 
|---|
| 88 | bool isList() const; | 
|---|
| 89 |  | 
|---|
| 90 | bool isWritable() const; | 
|---|
| 91 |  | 
|---|
| 92 | QQmlJSScope::ConstPtr storedType() const { return m_storedType; } | 
|---|
| 93 | QQmlJSScope::ConstPtr scopeType() const { return m_scope; } | 
|---|
| 94 |  | 
|---|
| 95 | QQmlJSScope::ConstPtr type() const | 
|---|
| 96 | { | 
|---|
| 97 | return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v: m_content).first; | 
|---|
| 98 | } | 
|---|
| 99 | QQmlJSMetaProperty property() const | 
|---|
| 100 | { | 
|---|
| 101 | return std::get<PropertyLookup>(v: m_content).property; | 
|---|
| 102 | } | 
|---|
| 103 | int baseLookupIndex() const | 
|---|
| 104 | { | 
|---|
| 105 | return std::get<PropertyLookup>(v: m_content).baseLookupIndex; | 
|---|
| 106 | } | 
|---|
| 107 | int resultLookupIndex() const | 
|---|
| 108 | { | 
|---|
| 109 | switch (m_content.index()) { | 
|---|
| 110 | case Type: | 
|---|
| 111 | return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v: m_content).second; | 
|---|
| 112 | case Property: | 
|---|
| 113 | return std::get<PropertyLookup>(v: m_content).resultLookupIndex; | 
|---|
| 114 | default: | 
|---|
| 115 | return InvalidLookupIndex; | 
|---|
| 116 | } | 
|---|
| 117 | } | 
|---|
| 118 | QQmlJSMetaEnum enumeration() const | 
|---|
| 119 | { | 
|---|
| 120 | return std::get<std::pair<QQmlJSMetaEnum, QString>>(v: m_content).first; | 
|---|
| 121 | } | 
|---|
| 122 | QString enumMember() const | 
|---|
| 123 | { | 
|---|
| 124 | return std::get<std::pair<QQmlJSMetaEnum, QString>>(v: m_content).second; | 
|---|
| 125 | } | 
|---|
| 126 | QList<QQmlJSMetaMethod> method() const { return std::get<QList<QQmlJSMetaMethod>>(v: m_content); } | 
|---|
| 127 | uint importNamespace() const { return std::get<uint>(v: m_content); } | 
|---|
| 128 |  | 
|---|
| 129 | QQmlJSScope::ConstPtr conversionResult() const | 
|---|
| 130 | { | 
|---|
| 131 | return std::get<ConvertedTypes>(v: m_content).result; | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | QQmlJSScope::ConstPtr conversionResultScope() const | 
|---|
| 135 | { | 
|---|
| 136 | return std::get<ConvertedTypes>(v: m_content).resultScope; | 
|---|
| 137 | } | 
|---|
| 138 |  | 
|---|
| 139 | QList<QQmlJSScope::ConstPtr> conversionOrigins() const | 
|---|
| 140 | { | 
|---|
| 141 | return std::get<ConvertedTypes>(v: m_content).origins; | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | ContentVariant variant() const { return m_variant; } | 
|---|
| 145 |  | 
|---|
| 146 | friend size_t qHash(const QQmlJSRegisterContent ®isterContent, size_t seed = 0) | 
|---|
| 147 | { | 
|---|
| 148 | seed = qHashMulti(seed, args: registerContent.m_storedType, args: registerContent.m_content.index(), | 
|---|
| 149 | args: registerContent.m_scope, args: registerContent.m_variant); | 
|---|
| 150 | switch (registerContent.m_content.index()) { | 
|---|
| 151 | case Type: | 
|---|
| 152 | return qHash(key: std::get<std::pair<QQmlJSScope::ConstPtr, int>>(v: registerContent.m_content), | 
|---|
| 153 | seed); | 
|---|
| 154 | case Property: | 
|---|
| 155 | return qHash(property: std::get<PropertyLookup>(v: registerContent.m_content), seed); | 
|---|
| 156 | case Enum: | 
|---|
| 157 | return qHash(key: std::get<std::pair<QQmlJSMetaEnum, QString>>(v: registerContent.m_content), | 
|---|
| 158 | seed); | 
|---|
| 159 | case Method: | 
|---|
| 160 | return qHash(key: std::get<QList<QQmlJSMetaMethod>>(v: registerContent.m_content), seed); | 
|---|
| 161 | case ImportNamespace: | 
|---|
| 162 | return qHash(key: std::get<uint>(v: registerContent.m_content), seed); | 
|---|
| 163 | case Conversion: | 
|---|
| 164 | return qHash(types: std::get<ConvertedTypes>(v: registerContent.m_content), seed); | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 | Q_UNREACHABLE_RETURN(seed); | 
|---|
| 168 | } | 
|---|
| 169 |  | 
|---|
| 170 | static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 171 | const QQmlJSScope::ConstPtr &type, | 
|---|
| 172 | int resultLookupIndex, ContentVariant variant, | 
|---|
| 173 | const QQmlJSScope::ConstPtr &scope = {}); | 
|---|
| 174 |  | 
|---|
| 175 | static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 176 | const QQmlJSMetaProperty &property, | 
|---|
| 177 | int baseLookupIndex, int resultLookupIndex, | 
|---|
| 178 | ContentVariant variant, | 
|---|
| 179 | const QQmlJSScope::ConstPtr &scope); | 
|---|
| 180 |  | 
|---|
| 181 | static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 182 | const QQmlJSMetaEnum &enumeration, | 
|---|
| 183 | const QString &enumMember, ContentVariant variant, | 
|---|
| 184 | const QQmlJSScope::ConstPtr &scope); | 
|---|
| 185 |  | 
|---|
| 186 | static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 187 | const QList<QQmlJSMetaMethod> &methods, | 
|---|
| 188 | ContentVariant variant, | 
|---|
| 189 | const QQmlJSScope::ConstPtr &scope); | 
|---|
| 190 |  | 
|---|
| 191 | static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 192 | uint importNamespaceStringId, ContentVariant variant, | 
|---|
| 193 | const QQmlJSScope::ConstPtr &scope = {}); | 
|---|
| 194 |  | 
|---|
| 195 | static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 196 | const QList<QQmlJSScope::ConstPtr> &origins, | 
|---|
| 197 | const QQmlJSScope::ConstPtr &conversion, | 
|---|
| 198 | const QQmlJSScope::ConstPtr &conversionScope, | 
|---|
| 199 | ContentVariant variant, | 
|---|
| 200 | const QQmlJSScope::ConstPtr &scope = {}); | 
|---|
| 201 |  | 
|---|
| 202 | QQmlJSRegisterContent storedIn(const QQmlJSScope::ConstPtr &newStoredType) const | 
|---|
| 203 | { | 
|---|
| 204 | QQmlJSRegisterContent result = *this; | 
|---|
| 205 | result.m_storedType = newStoredType; | 
|---|
| 206 | return result; | 
|---|
| 207 | } | 
|---|
| 208 |  | 
|---|
| 209 | QQmlJSRegisterContent castTo(const QQmlJSScope::ConstPtr &newContainedType) const | 
|---|
| 210 | { | 
|---|
| 211 | // This is not a conversion but a run time cast. It may result in null or undefined. | 
|---|
| 212 | QQmlJSRegisterContent result = *this; | 
|---|
| 213 | result.m_content = std::make_pair(x: newContainedType, y: result.resultLookupIndex()); | 
|---|
| 214 | return result; | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | private: | 
|---|
| 218 | enum ContentKind { Type, Property, Enum, Method, ImportNamespace, Conversion }; | 
|---|
| 219 |  | 
|---|
| 220 | struct ConvertedTypes | 
|---|
| 221 | { | 
|---|
| 222 | QList<QQmlJSScope::ConstPtr> origins; | 
|---|
| 223 | QQmlJSScope::ConstPtr result; | 
|---|
| 224 | QQmlJSScope::ConstPtr resultScope; | 
|---|
| 225 |  | 
|---|
| 226 | friend size_t qHash(const ConvertedTypes &types, size_t seed = 0) | 
|---|
| 227 | { | 
|---|
| 228 | return qHashMulti(seed, args: types.origins, args: types.result, args: types.resultScope); | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | friend bool operator==(const ConvertedTypes &a, const ConvertedTypes &b) | 
|---|
| 232 | { | 
|---|
| 233 | return a.origins == b.origins && a.result == b.result && a.resultScope == b.resultScope; | 
|---|
| 234 | } | 
|---|
| 235 |  | 
|---|
| 236 | friend bool operator!=(const ConvertedTypes &a, const ConvertedTypes &b) | 
|---|
| 237 | { | 
|---|
| 238 | return !(a == b); | 
|---|
| 239 | } | 
|---|
| 240 | }; | 
|---|
| 241 |  | 
|---|
| 242 | struct PropertyLookup | 
|---|
| 243 | { | 
|---|
| 244 | QQmlJSMetaProperty property; | 
|---|
| 245 | int baseLookupIndex = InvalidLookupIndex; | 
|---|
| 246 | int resultLookupIndex = InvalidLookupIndex; | 
|---|
| 247 |  | 
|---|
| 248 | friend size_t qHash(const PropertyLookup &property, size_t seed = 0) | 
|---|
| 249 | { | 
|---|
| 250 | return qHashMulti( | 
|---|
| 251 | seed, args: property.property, args: property.baseLookupIndex, args: property.resultLookupIndex); | 
|---|
| 252 | } | 
|---|
| 253 |  | 
|---|
| 254 | friend bool operator==(const PropertyLookup &a, const PropertyLookup &b) | 
|---|
| 255 | { | 
|---|
| 256 | return a.baseLookupIndex == b.baseLookupIndex | 
|---|
| 257 | && a.resultLookupIndex == b.resultLookupIndex | 
|---|
| 258 | && a.property == b.property; | 
|---|
| 259 | } | 
|---|
| 260 |  | 
|---|
| 261 | friend bool operator!=(const PropertyLookup &a, const PropertyLookup &b) | 
|---|
| 262 | { | 
|---|
| 263 | return !(a == b); | 
|---|
| 264 | } | 
|---|
| 265 | }; | 
|---|
| 266 |  | 
|---|
| 267 | using Content = std::variant< | 
|---|
| 268 | std::pair<QQmlJSScope::ConstPtr, int>, | 
|---|
| 269 | PropertyLookup, | 
|---|
| 270 | std::pair<QQmlJSMetaEnum, QString>, | 
|---|
| 271 | QList<QQmlJSMetaMethod>, | 
|---|
| 272 | uint, | 
|---|
| 273 | ConvertedTypes | 
|---|
| 274 | >; | 
|---|
| 275 |  | 
|---|
| 276 | QQmlJSRegisterContent(const QQmlJSScope::ConstPtr &storedType, | 
|---|
| 277 | const QQmlJSScope::ConstPtr &scope, ContentVariant variant) | 
|---|
| 278 | : m_storedType(storedType), m_scope(scope), m_variant(variant) | 
|---|
| 279 | { | 
|---|
| 280 | } | 
|---|
| 281 |  | 
|---|
| 282 | QQmlJSScope::ConstPtr m_storedType; | 
|---|
| 283 | QQmlJSScope::ConstPtr m_scope; | 
|---|
| 284 | Content m_content; | 
|---|
| 285 | ContentVariant m_variant = Unknown; | 
|---|
| 286 |  | 
|---|
| 287 | // TODO: Constant string/number/bool/enumval | 
|---|
| 288 | }; | 
|---|
| 289 |  | 
|---|
| 290 | QT_END_NAMESPACE | 
|---|
| 291 |  | 
|---|
| 292 | #endif // REGISTERCONTENT_H | 
|---|
| 293 |  | 
|---|