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
21QT_BEGIN_NAMESPACE
22
23struct QQmlJSRegisterContentPrivate;
24class Q_QMLCOMPILER_EXPORT QQmlJSRegisterContent
25{
26public:
27 // ContentVariant determines the relation between this register content and its scope().
28 // For example, a property is always a property of a type. That type is given as scope.
29 // Most content variants can carry either a specific kind of content, as commented below,
30 // or a conversion. If two or more register contents of the same content variant are merged,
31 // they retain their content variant but become a conversion with the original register
32 // contents linked as conversion origins.
33
34 enum ContentVariant {
35 ObjectById, // type (scope is QML scope of binding/function)
36 TypeByName, // type (TODO: scope is not guaranteed to be useful)
37 Singleton, // type (scope is either import namespace or QML scope)
38 Script, // type (scope is either import namespace or QML scope)
39 MetaType, // type (always QMetaObject, scope is the type reprented by the metaobject)
40 Extension, // type (scope is the type being extended)
41 ScopeObject, // type (either QML scope of binding/function or JS global object)
42 ParentScope, // type (scope is the child scope)
43
44 Property, // property (scope is the owner (hasOwnProperty) of the property)
45 Method, // method (retrieved as property, including overloads), like property
46 Enum, // enumeration (scope is the type the enumeration belongs to)
47
48 Attachment, // type (scope is attacher; use attacher() and attachee() for clarity)
49 ModulePrefix, // import namespace (scope is either QML scope or type the prefix is used on)
50
51 MethodCall, // method call (resolved to specific overload), like property
52
53 ListValue, // property (scope is list retrieved from)
54 ListIterator, // property (scope is list being iterated)
55
56 Literal, // type (scope does not exist)
57 Operation, // type (scope does not exist)
58
59 BaseType, // type (scope is derived type)
60 Cast, // type (scope is type casted from)
61
62 Storage, // type (scope does not exist)
63
64 // Either a synthetic type or a merger of multiple different variants.
65 // In the latter case, look at conversion origins to find out more.
66 // Synthetic types should be short lived.
67 Unknown,
68 };
69
70 enum { InvalidLookupIndex = -1 };
71
72 QQmlJSRegisterContent() = default;
73
74
75 // General properties of the register content, (mostly) independent of kind or variant
76
77 bool isNull() const { return !d; }
78 bool isValid() const;
79
80 bool isList() const;
81 bool isWritable() const;
82
83 ContentVariant variant() const;
84
85 QString descriptiveName() const;
86 QString containedTypeName() const;
87
88 int resultLookupIndex() const;
89
90 QQmlJSScope::ConstPtr storedType() const;
91 QQmlJSScope::ConstPtr containedType() const;
92 QQmlJSScope::ConstPtr scopeType() const;
93
94 bool contains(const QQmlJSScope::ConstPtr &type) const { return type == containedType(); }
95 bool isStoredIn(const QQmlJSScope::ConstPtr &type) const { return type == storedType(); }
96
97
98 // Properties of specific kinds of register contents
99
100 bool isType() const;
101 QQmlJSScope::ConstPtr type() const;
102
103 bool isProperty() const;
104 QQmlJSMetaProperty property() const;
105 int baseLookupIndex() const;
106
107 bool isEnumeration() const;
108 QQmlJSMetaEnum enumeration() const;
109 QString enumMember() const;
110
111 bool isMethod() const;
112 QList<QQmlJSMetaMethod> method() const;
113 QQmlJSScope::ConstPtr methodType() const;
114
115 bool isImportNamespace() const;
116 uint importNamespace() const;
117 QQmlJSScope::ConstPtr importNamespaceType() const;
118
119 bool isConversion() const;
120 QQmlJSScope::ConstPtr conversionResultType() const;
121 QQmlJSRegisterContent conversionResultScope() const;
122 QList<QQmlJSRegisterContent> conversionOrigins() const;
123
124 bool isMethodCall() const;
125 QQmlJSMetaMethod methodCall() const;
126 bool isJavaScriptReturnValue() const;
127
128
129 // Linked register contents
130
131 QQmlJSRegisterContent attacher() const;
132 QQmlJSRegisterContent attachee() const;
133
134 QQmlJSRegisterContent scope() const;
135 QQmlJSRegisterContent storage() const;
136 QQmlJSRegisterContent original() const;
137 QQmlJSRegisterContent shadowed() const;
138
139 quintptr id() const { return quintptr(d); }
140
141private:
142 friend class QQmlJSRegisterContentPool;
143 // TODO: Constant string/number/bool/enumval
144
145 QQmlJSRegisterContent(QQmlJSRegisterContentPrivate *dd) : d(dd) {};
146
147 friend bool operator==(QQmlJSRegisterContent a, QQmlJSRegisterContent b)
148 {
149 return a.d == b.d;
150 }
151
152 friend bool operator!=(QQmlJSRegisterContent a, QQmlJSRegisterContent b)
153 {
154 return !(a == b);
155 }
156
157 friend size_t qHash(QQmlJSRegisterContent registerContent, size_t seed = 0)
158 {
159 return qHash(t: registerContent.d, seed);
160 }
161
162 QQmlJSRegisterContentPrivate *d = nullptr;
163};
164
165class Q_QMLCOMPILER_EXPORT QQmlJSRegisterContentPool
166{
167 Q_DISABLE_COPY_MOVE(QQmlJSRegisterContentPool)
168public:
169 using ContentVariant = QQmlJSRegisterContent::ContentVariant;
170
171 QQmlJSRegisterContentPool();
172 ~QQmlJSRegisterContentPool();
173
174
175 // Create new register contents of specific kinds
176
177 QQmlJSRegisterContent createType(
178 const QQmlJSScope::ConstPtr &type, int resultLookupIndex, ContentVariant variant,
179 QQmlJSRegisterContent scope = {});
180
181 QQmlJSRegisterContent createProperty(
182 const QQmlJSMetaProperty &property, int baseLookupIndex, int resultLookupIndex,
183 ContentVariant variant, QQmlJSRegisterContent scope);
184
185 QQmlJSRegisterContent createEnumeration(
186 const QQmlJSMetaEnum &enumeration, const QString &enumMember, ContentVariant variant,
187 QQmlJSRegisterContent scope);
188
189 QQmlJSRegisterContent createMethod(
190 const QList<QQmlJSMetaMethod> &methods, const QQmlJSScope::ConstPtr &methodType,
191 ContentVariant variant, QQmlJSRegisterContent scope);
192
193 QQmlJSRegisterContent createMethodCall(
194 const QQmlJSMetaMethod &method, const QQmlJSScope::ConstPtr &returnType,
195 QQmlJSRegisterContent scope);
196
197 QQmlJSRegisterContent createImportNamespace(
198 uint importNamespaceStringId, const QQmlJSScope::ConstPtr &importNamespaceType,
199 ContentVariant variant, QQmlJSRegisterContent scope);
200
201 QQmlJSRegisterContent createConversion(
202 const QList<QQmlJSRegisterContent> &origins, const QQmlJSScope::ConstPtr &conversion,
203 QQmlJSRegisterContent conversionScope, ContentVariant variant,
204 QQmlJSRegisterContent scope);
205
206
207 // Clone and possibly adapt register contents. This leaves the original intact.
208
209 QQmlJSRegisterContent storedIn(
210 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &newStoredType);
211
212 QQmlJSRegisterContent castTo(
213 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &newContainedType);
214
215 QQmlJSRegisterContent clone(QQmlJSRegisterContent from) { return clone(from: from.d); }
216
217
218 // Change the internals of the given register content. Adjusting and generalizing store a
219 // copy of the previous content as original() and shadowed(), respectively. Storing creates
220 // a new register content for storage(). All of those assume you only do this once per
221 // register content (although you can adjust and generalize the storage, for example).
222
223 void storeType(
224 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &stored);
225 void adjustType(
226 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &adjusted);
227 void generalizeType(
228 QQmlJSRegisterContent content, const QQmlJSScope::ConstPtr &generalized);
229
230 enum AllocationMode { Permanent, Temporary };
231 void setAllocationMode(AllocationMode mode);
232 void clearTemporaries();
233
234private:
235 struct Deleter {
236 // It's a template so that we only need the QQmlJSRegisterContentPrivate dtor on usage.
237 template<typename Private>
238 constexpr void operator()(Private *d) const { delete d; }
239 };
240
241 using Pool = std::vector<std::unique_ptr<QQmlJSRegisterContentPrivate, Deleter>>;
242
243 QQmlJSRegisterContentPrivate *clone(const QQmlJSRegisterContentPrivate *from);
244 QQmlJSRegisterContentPrivate *create() { return clone(from: nullptr); }
245 QQmlJSRegisterContentPrivate *create(QQmlJSRegisterContent scope, ContentVariant variant);
246
247 Pool m_pool;
248 qsizetype m_checkpoint = -1;
249};
250
251QT_END_NAMESPACE
252
253#endif // REGISTERCONTENT_H
254

source code of qtdeclarative/src/qmlcompiler/qqmljsregistercontent_p.h