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 QQMLJSTYPERESOLVER_P_H
5#define QQMLJSTYPERESOLVER_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 <memory>
18#include <qtqmlcompilerexports.h>
19
20#include <private/qqmlirbuilder_p.h>
21#include <private/qqmljsast_p.h>
22#include "qqmljsimporter_p.h"
23#include "qqmljslogger_p.h"
24#include "qqmljsregistercontent_p.h"
25#include "qqmljsresourcefilemapper_p.h"
26#include "qqmljsscope_p.h"
27#include "qqmljsscopesbyid_p.h"
28
29QT_BEGIN_NAMESPACE
30
31class QQmlJSImportVisitor;
32class Q_QMLCOMPILER_EXPORT QQmlJSTypeResolver
33{
34public:
35 QQmlJSTypeResolver(QQmlJSImporter *importer);
36
37 // Note: must be called after the construction to read the QML program
38 void init(QQmlJSImportVisitor *visitor, QQmlJS::AST::Node *program);
39
40 QQmlJSRegisterContentPool *registerContentPool() const { return m_pool.get(); }
41 QQmlJSLogger *logger() const { return m_logger; }
42
43
44 // Configuration options
45
46 enum ParentMode { UseDocumentParent, UseParentProperty };
47 void setParentMode(ParentMode mode) { m_parentMode = mode; }
48 ParentMode parentMode() const { return m_parentMode; }
49
50 enum CloneMode { CloneTypes, DoNotCloneTypes };
51 void setCloneMode(CloneMode mode) { m_cloneMode = mode; }
52 CloneMode cloneMode() const { return m_cloneMode; }
53
54
55 // Builtin types
56
57 QQmlJSScope::ConstPtr voidType() const { return m_voidType; }
58 QQmlJSScope::ConstPtr emptyType() const { return m_emptyType; }
59 QQmlJSScope::ConstPtr nullType() const { return m_nullType; }
60 QQmlJSScope::ConstPtr realType() const { return m_realType; }
61 QQmlJSScope::ConstPtr floatType() const { return m_floatType; }
62 QQmlJSScope::ConstPtr int8Type() const { return m_int8Type; }
63 QQmlJSScope::ConstPtr uint8Type() const { return m_uint8Type; }
64 QQmlJSScope::ConstPtr int16Type() const { return m_int16Type; }
65 QQmlJSScope::ConstPtr uint16Type() const { return m_uint16Type; }
66 QQmlJSScope::ConstPtr int32Type() const { return m_int32Type; }
67 QQmlJSScope::ConstPtr uint32Type() const { return m_uint32Type; }
68 QQmlJSScope::ConstPtr int64Type() const { return m_int64Type; }
69 QQmlJSScope::ConstPtr uint64Type() const { return m_uint64Type; }
70 QQmlJSScope::ConstPtr sizeType() const { return m_sizeType; }
71 QQmlJSScope::ConstPtr boolType() const { return m_boolType; }
72 QQmlJSScope::ConstPtr stringType() const { return m_stringType; }
73 QQmlJSScope::ConstPtr stringListType() const { return m_stringListType; }
74 QQmlJSScope::ConstPtr byteArrayType() const { return m_byteArrayType; }
75 QQmlJSScope::ConstPtr urlType() const { return m_urlType; }
76 QQmlJSScope::ConstPtr dateTimeType() const { return m_dateTimeType; }
77 QQmlJSScope::ConstPtr dateType() const { return m_dateType; }
78 QQmlJSScope::ConstPtr timeType() const { return m_timeType; }
79 QQmlJSScope::ConstPtr regexpType() const { return m_regexpType; }
80 QQmlJSScope::ConstPtr variantListType() const { return m_variantListType; }
81 QQmlJSScope::ConstPtr variantMapType() const { return m_variantMapType; }
82 QQmlJSScope::ConstPtr varType() const { return m_varType; }
83 QQmlJSScope::ConstPtr qmlPropertyMapType() const { return m_qmlPropertyMapType; }
84 QQmlJSScope::ConstPtr jsValueType() const { return m_jsValueType; }
85 QQmlJSScope::ConstPtr jsPrimitiveType() const { return m_jsPrimitiveType; }
86 QQmlJSScope::ConstPtr listPropertyType() const { return m_listPropertyType; }
87 QQmlJSScope::ConstPtr metaObjectType() const { return m_metaObjectType; }
88 QQmlJSScope::ConstPtr functionType() const { return m_functionType; }
89 QQmlJSScope::ConstPtr jsGlobalObject() const { return m_jsGlobalObject; }
90 QQmlJSScope::ConstPtr qObjectType() const { return m_qObjectType; }
91 QQmlJSScope::ConstPtr qObjectListType() const { return m_qObjectListType; }
92 QQmlJSScope::ConstPtr arrayPrototype() const { return m_arrayPrototype; }
93 QQmlJSScope::ConstPtr forInIteratorPtr() const { return m_forInIteratorPtr; }
94 QQmlJSScope::ConstPtr forOfIteratorPtr() const { return m_forOfIteratorPtr; }
95 QQmlJSScope::ConstPtr qQmlScriptStringType() const { return m_qQmlScriptStringType; }
96
97 QQmlJSRegisterContent jsGlobalObjectContent() const { return m_jsGlobalObjectContent; }
98 QQmlJSScope::ConstPtr mathObject() const;
99 QQmlJSScope::ConstPtr consoleObject() const;
100
101 QQmlJSScope::ConstPtr typeForConst(QV4::ReturnedValue rv) const;
102
103
104 // Querying imports and imported types
105
106 bool isPrefix(const QString &name) const
107 {
108 return m_imports.hasType(name) && !m_imports.type(name).scope;
109 }
110
111 const QHash<QString, QQmlJS::ImportedScope<QQmlJSScope::ConstPtr>> &importedTypes() const
112 {
113 return m_imports.types();
114 }
115
116 const auto &importedNames() const
117 {
118 return m_imports.contextualTypes().names();
119 }
120
121 QQmlJSScope::ConstPtr typeForName(const QString &name) const
122 {
123 return m_imports.type(name).scope;
124 }
125
126 QString nameForType(const QQmlJSScope::ConstPtr &type) const
127 {
128 return m_imports.name(type);
129 }
130
131 QStringList seenModuleQualifiers() const { return m_seenModuleQualifiers; }
132
133
134 // Querying types from current document
135
136 QQmlJSScope::ConstPtr scopeForLocation(const QV4::CompiledData::Location &location) const;
137 QQmlJSScope::ConstPtr typeFromAST(QQmlJS::AST::Type *type) const;
138 QQmlJSScope::ConstPtr typeForId(
139 const QQmlJSScope::ConstPtr &scope, const QString &name,
140 QQmlJSScopesByIdOptions options = Default) const
141 {
142 return canFindComponentBoundaries(scope)
143 ? m_objectsById.scope(id: name, referrer: scope, options)
144 : QQmlJSScope::ConstPtr();
145 }
146
147 const QQmlJSScopesById &objectsById() const { return m_objectsById; }
148 bool canCallJSFunctions() const { return m_objectsById.signaturesAreEnforced(); }
149 bool canAddressValueTypes() const { return m_objectsById.valueTypesAreAddressable(); }
150
151 QQmlJSScope::ConstPtr scopedType(
152 const QQmlJSScope::ConstPtr &scope, const QString &name,
153 QQmlJSScopesByIdOptions options = Default) const;
154
155 const QHash<QQmlJS::SourceLocation, QQmlJSMetaSignalHandler> &signalHandlers() const
156 {
157 return m_signalHandlers;
158 }
159
160
161 // Classification of types
162
163 bool isPrimitive(QQmlJSRegisterContent type) const;
164 bool isPrimitive(const QQmlJSScope::ConstPtr &type) const;
165
166 bool isNumeric(QQmlJSRegisterContent type) const;
167 bool isNumeric(const QQmlJSScope::ConstPtr &type) const;
168
169 bool isIntegral(QQmlJSRegisterContent type) const;
170 bool isIntegral(const QQmlJSScope::ConstPtr &type) const;
171
172 bool isSignedInteger(const QQmlJSScope::ConstPtr &type) const;
173 bool isUnsignedInteger(const QQmlJSScope::ConstPtr &type) const;
174 bool isNativeArrayIndex(const QQmlJSScope::ConstPtr &type) const;
175
176 bool canHold(const QQmlJSScope::ConstPtr &container,
177 const QQmlJSScope::ConstPtr &contained) const;
178 bool canHoldUndefined(QQmlJSRegisterContent content) const;
179 bool isOptionalType(QQmlJSRegisterContent content) const;
180
181 bool canPopulate(
182 const QQmlJSScope::ConstPtr &type, const QQmlJSScope::ConstPtr &argument,
183 bool *isExtension) const;
184
185 bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const;
186 bool canConvertFromTo(QQmlJSRegisterContent from, QQmlJSRegisterContent to) const;
187
188 bool areEquivalentLists(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const;
189
190 bool isTriviallyCopyable(const QQmlJSScope::ConstPtr &type) const;
191
192 bool inherits(const QQmlJSScope::ConstPtr &derived, const QQmlJSScope::ConstPtr &base) const;
193
194
195 // Querying of types given other types
196
197 enum class ComponentIsGeneric { No, Yes };
198 QQmlJSScope::ConstPtr genericType(
199 const QQmlJSScope::ConstPtr &type,
200 ComponentIsGeneric allowComponent = ComponentIsGeneric::No) const;
201
202 QQmlJSScope::ConstPtr storedType(const QQmlJSScope::ConstPtr &type) const;
203
204 QQmlJSRegisterContent original(QQmlJSRegisterContent type) const;
205 QQmlJSScope::ConstPtr originalContainedType(QQmlJSRegisterContent container) const;
206
207 QQmlJSScope::ConstPtr merge(
208 const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const;
209
210 QQmlJSRegisterContent extractNonVoidFromOptionalType(
211 QQmlJSRegisterContent content) const;
212
213 QQmlJSMetaMethod selectConstructor(
214 const QQmlJSScope::ConstPtr &type, const QQmlJSScope::ConstPtr &argument,
215 bool *isExtension) const;
216
217
218 // Creation of "tracked" QQmlJSRegisterContents
219
220 QQmlJSRegisterContent typeForBinaryOperation(
221 QSOperator::Op oper, QQmlJSRegisterContent left,
222 QQmlJSRegisterContent right) const;
223
224 enum class UnaryOperator { Not, Plus, Minus, Increment, Decrement, Complement };
225 QQmlJSRegisterContent typeForArithmeticUnaryOperation(
226 UnaryOperator op, QQmlJSRegisterContent operand) const;
227
228 QQmlJSRegisterContent merge(
229 QQmlJSRegisterContent a, QQmlJSRegisterContent b) const;
230
231 QQmlJSRegisterContent literalType(const QQmlJSScope::ConstPtr &type) const;
232 QQmlJSRegisterContent operationType(const QQmlJSScope::ConstPtr &type) const;
233 QQmlJSRegisterContent namedType(const QQmlJSScope::ConstPtr &type) const;
234 QQmlJSRegisterContent syntheticType(const QQmlJSScope::ConstPtr &type) const;
235
236 QQmlJSRegisterContent scopedType(
237 QQmlJSRegisterContent scope, const QString &name,
238 int lookupIndex = QQmlJSRegisterContent::InvalidLookupIndex,
239 QQmlJSScopesByIdOptions options = Default) const;
240
241 QQmlJSRegisterContent memberType(
242 QQmlJSRegisterContent type, const QString &name,
243 int lookupIndex = QQmlJSRegisterContent::InvalidLookupIndex) const;
244
245 QQmlJSRegisterContent valueType(QQmlJSRegisterContent list) const;
246
247 QQmlJSRegisterContent returnType(
248 const QQmlJSMetaMethod &method, const QQmlJSScope::ConstPtr &returnType,
249 QQmlJSRegisterContent scope) const;
250
251 QQmlJSRegisterContent extensionType(
252 const QQmlJSScope::ConstPtr &extension, QQmlJSRegisterContent base) const;
253
254 QQmlJSRegisterContent baseType(
255 const QQmlJSScope::ConstPtr &base, QQmlJSRegisterContent derived) const;
256
257 QQmlJSRegisterContent parentScope(
258 const QQmlJSScope::ConstPtr &parent, QQmlJSRegisterContent child) const;
259
260 QQmlJSRegisterContent iteratorPointer(
261 QQmlJSRegisterContent listType, QQmlJS::AST::ForEachType type,
262 int lookupIndex) const;
263
264 QQmlJSRegisterContent convert(
265 QQmlJSRegisterContent from, QQmlJSRegisterContent to) const;
266 QQmlJSRegisterContent convert(
267 QQmlJSRegisterContent from, const QQmlJSScope::ConstPtr &to) const;
268
269
270 // Type adjustment
271
272 [[nodiscard]] bool adjustTrackedType(
273 QQmlJSRegisterContent tracked, const QQmlJSScope::ConstPtr &conversion) const;
274 [[nodiscard]] bool adjustTrackedType(
275 QQmlJSRegisterContent tracked, QQmlJSRegisterContent conversion) const;
276 [[nodiscard]] bool adjustTrackedType(
277 QQmlJSRegisterContent tracked,
278 const QList<QQmlJSRegisterContent> &conversions) const;
279 void adjustOriginalType(
280 QQmlJSRegisterContent tracked, const QQmlJSScope::ConstPtr &conversion) const;
281 void generalizeType(QQmlJSRegisterContent type) const;
282
283
284protected:
285
286 QQmlJSRegisterContent memberType(QQmlJSRegisterContent type, const QString &name,
287 int baseLookupIndex, int resultLookupIndex) const;
288 QQmlJSRegisterContent memberEnumType(QQmlJSRegisterContent type,
289 const QString &name) const;
290 bool checkEnums(QQmlJSRegisterContent scope, const QString &name,
291 QQmlJSRegisterContent *result) const;
292 bool canPrimitivelyConvertFromTo(
293 const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const;
294 QQmlJSRegisterContent lengthProperty(bool isWritable, QQmlJSRegisterContent scope) const;
295
296 QQmlJSScope::ConstPtr containedTypeForName(const QString &name) const;
297 QQmlJSRegisterContent registerContentForName(
298 const QString &name, QQmlJSRegisterContent scopeType = {}) const;
299
300 QQmlJSScope::ConstPtr resolveParentProperty(
301 const QString &name, const QQmlJSScope::ConstPtr &base,
302 const QQmlJSScope::ConstPtr &propType) const;
303
304 bool canFindComponentBoundaries(const QQmlJSScope::ConstPtr &scope) const;
305
306 std::unique_ptr<QQmlJSRegisterContentPool> m_pool;
307
308 QQmlJSScope::ConstPtr m_voidType;
309 QQmlJSScope::ConstPtr m_emptyType;
310 QQmlJSScope::ConstPtr m_nullType;
311 QQmlJSScope::ConstPtr m_numberPrototype;
312 QQmlJSScope::ConstPtr m_arrayPrototype;
313 QQmlJSScope::ConstPtr m_realType;
314 QQmlJSScope::ConstPtr m_floatType;
315 QQmlJSScope::ConstPtr m_int8Type;
316 QQmlJSScope::ConstPtr m_uint8Type;
317 QQmlJSScope::ConstPtr m_int16Type;
318 QQmlJSScope::ConstPtr m_uint16Type;
319 QQmlJSScope::ConstPtr m_int32Type;
320 QQmlJSScope::ConstPtr m_uint32Type;
321 QQmlJSScope::ConstPtr m_int64Type;
322 QQmlJSScope::ConstPtr m_uint64Type;
323 QQmlJSScope::ConstPtr m_sizeType;
324 QQmlJSScope::ConstPtr m_boolType;
325 QQmlJSScope::ConstPtr m_stringType;
326 QQmlJSScope::ConstPtr m_stringListType;
327 QQmlJSScope::ConstPtr m_byteArrayType;
328 QQmlJSScope::ConstPtr m_urlType;
329 QQmlJSScope::ConstPtr m_dateTimeType;
330 QQmlJSScope::ConstPtr m_dateType;
331 QQmlJSScope::ConstPtr m_timeType;
332 QQmlJSScope::ConstPtr m_regexpType;
333 QQmlJSScope::ConstPtr m_variantListType;
334 QQmlJSScope::ConstPtr m_variantMapType;
335 QQmlJSScope::ConstPtr m_varType;
336 QQmlJSScope::ConstPtr m_qmlPropertyMapType;
337 QQmlJSScope::ConstPtr m_jsValueType;
338 QQmlJSScope::ConstPtr m_jsPrimitiveType;
339 QQmlJSScope::ConstPtr m_listPropertyType;
340 QQmlJSScope::ConstPtr m_qObjectType;
341 QQmlJSScope::ConstPtr m_qObjectListType;
342 QQmlJSScope::ConstPtr m_qQmlScriptStringType;
343 QQmlJSScope::ConstPtr m_metaObjectType;
344 QQmlJSScope::ConstPtr m_functionType;
345 QQmlJSScope::ConstPtr m_jsGlobalObject;
346 QQmlJSScope::ConstPtr m_forInIteratorPtr;
347 QQmlJSScope::ConstPtr m_forOfIteratorPtr;
348
349 QQmlJSRegisterContent m_jsGlobalObjectContent;
350
351 QQmlJSScopesById m_objectsById;
352 QHash<QV4::CompiledData::Location, QQmlJSScope::ConstPtr> m_objectsByLocation;
353 QQmlJSImporter::ImportedTypes m_imports;
354 QHash<QQmlJS::SourceLocation, QQmlJSMetaSignalHandler> m_signalHandlers;
355 QStringList m_seenModuleQualifiers;
356
357 ParentMode m_parentMode = UseParentProperty;
358 CloneMode m_cloneMode = CloneTypes;
359 QQmlJSLogger *m_logger = nullptr;
360};
361
362/*!
363\internal
364
365QQmlJSTypeResolver expects to be outlived by its importer and mapper. It crashes when its importer
366or mapper gets destructed. Therefore, you can use this struct to extend the lifetime of its
367dependencies in case you need to store the resolver as a class member.
368QQmlJSTypeResolver also expects to be outlived by the logger used by the importvisitor, while the
369importvisitor actually does not and will not outlive the QQmlJSTypeResolver.
370*/
371struct QQmlJSTypeResolverDependencies
372{
373 std::shared_ptr<QQmlJSImporter> importer;
374 std::shared_ptr<QQmlJSResourceFileMapper> mapper;
375 std::shared_ptr<QQmlJSLogger> logger;
376};
377
378QT_END_NAMESPACE
379
380#endif // QQMLJSTYPERESOLVER_P_H
381

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