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