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