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 enum ParentMode { UseDocumentParent, UseParentProperty };
36 enum CloneMode { CloneTypes, DoNotCloneTypes };
37 enum ListMode { UseListProperty, UseQObjectList };
38
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 QQmlJSScope::ConstPtr voidType() const { return m_voidType; }
45 QQmlJSScope::ConstPtr emptyType() const { return m_emptyType; }
46 QQmlJSScope::ConstPtr nullType() const { return m_nullType; }
47 QQmlJSScope::ConstPtr realType() const { return m_realType; }
48 QQmlJSScope::ConstPtr floatType() const { return m_floatType; }
49 QQmlJSScope::ConstPtr int8Type() const { return m_int8Type; }
50 QQmlJSScope::ConstPtr uint8Type() const { return m_uint8Type; }
51 QQmlJSScope::ConstPtr int16Type() const { return m_int16Type; }
52 QQmlJSScope::ConstPtr uint16Type() const { return m_uint16Type; }
53 QQmlJSScope::ConstPtr int32Type() const { return m_int32Type; }
54 QQmlJSScope::ConstPtr uint32Type() const { return m_uint32Type; }
55 QQmlJSScope::ConstPtr int64Type() const { return m_int64Type; }
56 QQmlJSScope::ConstPtr uint64Type() const { return m_uint64Type; }
57 QQmlJSScope::ConstPtr sizeType() const { return m_sizeType; }
58 QQmlJSScope::ConstPtr boolType() const { return m_boolType; }
59 QQmlJSScope::ConstPtr stringType() const { return m_stringType; }
60 QQmlJSScope::ConstPtr stringListType() const { return m_stringListType; }
61 QQmlJSScope::ConstPtr byteArrayType() const { return m_byteArrayType; }
62 QQmlJSScope::ConstPtr urlType() const { return m_urlType; }
63 QQmlJSScope::ConstPtr dateTimeType() const { return m_dateTimeType; }
64 QQmlJSScope::ConstPtr dateType() const { return m_dateType; }
65 QQmlJSScope::ConstPtr timeType() const { return m_timeType; }
66 QQmlJSScope::ConstPtr variantListType() const { return m_variantListType; }
67 QQmlJSScope::ConstPtr variantMapType() const { return m_variantMapType; }
68 QQmlJSScope::ConstPtr varType() const { return m_varType; }
69 QQmlJSScope::ConstPtr jsValueType() const { return m_jsValueType; }
70 QQmlJSScope::ConstPtr jsPrimitiveType() const { return m_jsPrimitiveType; }
71 QQmlJSScope::ConstPtr listPropertyType() const { return m_listPropertyType; }
72 QQmlJSScope::ConstPtr metaObjectType() const { return m_metaObjectType; }
73 QQmlJSScope::ConstPtr functionType() const { return m_functionType; }
74 QQmlJSScope::ConstPtr jsGlobalObject() const { return m_jsGlobalObject; }
75 QQmlJSScope::ConstPtr qObjectType() const { return m_qObjectType; }
76 QQmlJSScope::ConstPtr qObjectListType() const { return m_qObjectListType; }
77 QQmlJSScope::ConstPtr arrayPrototype() const { return m_arrayPrototype; }
78 QQmlJSScope::ConstPtr forInIteratorPtr() const { return m_forInIteratorPtr; }
79 QQmlJSScope::ConstPtr forOfIteratorPtr() const { return m_forOfIteratorPtr; }
80
81 QQmlJSScope::ConstPtr mathObject() const;
82 QQmlJSScope::ConstPtr consoleObject() const;
83
84 QQmlJSScope::ConstPtr scopeForLocation(const QV4::CompiledData::Location &location) const;
85
86 bool isPrefix(const QString &name) const
87 {
88 return m_imports.hasType(name) && !m_imports.type(name).scope;
89 }
90
91 const QHash<QString, QQmlJS::ImportedScope<QQmlJSScope::ConstPtr>> &importedTypes() const
92 {
93 return m_imports.types();
94 }
95
96 const auto &importedNames() const
97 {
98 return m_imports.contextualTypes().names();
99 }
100
101 QQmlJSScope::ConstPtr typeForName(const QString &name) const
102 {
103 return m_imports.type(name).scope;
104 }
105 QString nameForType(const QQmlJSScope::ConstPtr &type) const
106 {
107 // We want here not the name of the original type. That one may not exist.
108 // We want the name of the type we've used as replacement since that is
109 // whatever we do with the type expects.
110 return m_imports.name(type: comparableType(type));
111 }
112
113 QQmlJSScope::ConstPtr typeFromAST(QQmlJS::AST::Type *type) const;
114 QQmlJSScope::ConstPtr typeForConst(QV4::ReturnedValue rv) const;
115 QQmlJSRegisterContent typeForBinaryOperation(QSOperator::Op oper,
116 const QQmlJSRegisterContent &left,
117 const QQmlJSRegisterContent &right) const;
118
119 enum class UnaryOperator { Not, Plus, Minus, Increment, Decrement, Complement };
120 QQmlJSRegisterContent typeForArithmeticUnaryOperation(
121 UnaryOperator op, const QQmlJSRegisterContent &operand) const;
122
123 bool isPrimitive(const QQmlJSRegisterContent &type) const;
124 bool isPrimitive(const QQmlJSScope::ConstPtr &type) const;
125
126 bool isNumeric(const QQmlJSRegisterContent &type) const;
127 bool isIntegral(const QQmlJSRegisterContent &type) const;
128
129 bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const;
130 bool canConvertFromTo(const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const;
131 QQmlJSRegisterContent merge(const QQmlJSRegisterContent &a,
132 const QQmlJSRegisterContent &b) const;
133
134 enum class ComponentIsGeneric { No, Yes };
135 QQmlJSScope::ConstPtr
136 genericType(const QQmlJSScope::ConstPtr &type,
137 ComponentIsGeneric allowComponent = ComponentIsGeneric::No) const;
138
139 QQmlJSRegisterContent builtinType(const QQmlJSScope::ConstPtr &type) const;
140 QQmlJSRegisterContent globalType(const QQmlJSScope::ConstPtr &type) const;
141 QQmlJSRegisterContent scopedType(const QQmlJSScope::ConstPtr &scope, const QString &name,
142 int lookupIndex = QQmlJSRegisterContent::InvalidLookupIndex,
143 QQmlJSScopesByIdOptions options = Default) const;
144 QQmlJSRegisterContent memberType(
145 const QQmlJSRegisterContent &type, const QString &name,
146 int lookupIndex = QQmlJSRegisterContent::InvalidLookupIndex) const;
147 QQmlJSRegisterContent valueType(const QQmlJSRegisterContent &list) const;
148 QQmlJSRegisterContent returnType(
149 const QQmlJSScope::ConstPtr &type, QQmlJSRegisterContent::ContentVariant variant,
150 const QQmlJSScope::ConstPtr &scope) const;
151
152 QQmlJSRegisterContent iteratorPointer(
153 const QQmlJSRegisterContent &listType, QQmlJS::AST::ForEachType type,
154 int lookupIndex) const;
155
156 bool registerIsStoredIn(const QQmlJSRegisterContent &reg,
157 const QQmlJSScope::ConstPtr &type) const;
158 bool registerContains(const QQmlJSRegisterContent &reg,
159 const QQmlJSScope::ConstPtr &type) const;
160 QQmlJSScope::ConstPtr containedType(const QQmlJSRegisterContent &container) const;
161 QString containedTypeName(const QQmlJSRegisterContent &container,
162 bool useFancyName = false) const;
163
164 QQmlJSRegisterContent tracked(const QQmlJSRegisterContent &type) const;
165 QQmlJSRegisterContent original(const QQmlJSRegisterContent &type) const;
166
167 QQmlJSScope::ConstPtr trackedContainedType(const QQmlJSRegisterContent &container) const;
168 QQmlJSScope::ConstPtr originalContainedType(const QQmlJSRegisterContent &container) const;
169
170 [[nodiscard]] bool adjustTrackedType(
171 const QQmlJSScope::ConstPtr &tracked, const QQmlJSScope::ConstPtr &conversion) const;
172 [[nodiscard]] bool adjustTrackedType(
173 const QQmlJSScope::ConstPtr &tracked,
174 const QList<QQmlJSScope::ConstPtr> &conversions) const;
175 void adjustOriginalType(
176 const QQmlJSScope::ConstPtr &tracked, const QQmlJSScope::ConstPtr &conversion) const;
177 void generalizeType(const QQmlJSScope::ConstPtr &type) const;
178
179 void setParentMode(ParentMode mode) { m_parentMode = mode; }
180 ParentMode parentMode() const { return m_parentMode; }
181
182 void setCloneMode(CloneMode mode) { m_cloneMode = mode; }
183 bool cloneMode() const { return m_cloneMode; }
184
185 QQmlJSScope::ConstPtr storedType(const QQmlJSScope::ConstPtr &type) const;
186 QQmlJSScope::ConstPtr originalType(const QQmlJSScope::ConstPtr &type) const;
187 QQmlJSScope::ConstPtr trackedType(const QQmlJSScope::ConstPtr &type) const;
188 QQmlJSScope::ConstPtr comparableType(const QQmlJSScope::ConstPtr &type) const;
189
190 const QQmlJSScopesById &objectsById() const { return m_objectsById; }
191 bool canCallJSFunctions() const { return m_objectsById.signaturesAreEnforced(); }
192 bool canAddressValueTypes() const { return m_objectsById.valueTypesAreAddressable(); }
193
194 const QHash<QQmlJS::SourceLocation, QQmlJSMetaSignalHandler> &signalHandlers() const
195 {
196 return m_signalHandlers;
197 }
198
199 bool equals(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const;
200
201 QQmlJSRegisterContent convert(
202 const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const;
203 QQmlJSRegisterContent cast(
204 const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const;
205
206 QQmlJSScope::ConstPtr merge(const QQmlJSScope::ConstPtr &a,
207 const QQmlJSScope::ConstPtr &b) const;
208
209 bool canHoldUndefined(const QQmlJSRegisterContent &content) const;
210 bool isOptionalType(const QQmlJSRegisterContent &content) const;
211 QQmlJSScope::ConstPtr extractNonVoidFromOptionalType(
212 const QQmlJSRegisterContent &content) const;
213
214 bool isNumeric(const QQmlJSScope::ConstPtr &type) const;
215 bool isIntegral(const QQmlJSScope::ConstPtr &type) const;
216 bool isSignedInteger(const QQmlJSScope::ConstPtr &type) const;
217 bool isUnsignedInteger(const QQmlJSScope::ConstPtr &type) const;
218 bool isNativeArrayIndex(const QQmlJSScope::ConstPtr &type) const;
219
220 bool canHold(const QQmlJSScope::ConstPtr &container,
221 const QQmlJSScope::ConstPtr &contained) const;
222
223 bool canPopulate(
224 const QQmlJSScope::ConstPtr &type, const QQmlJSScope::ConstPtr &argument,
225 bool *isExtension) const;
226
227 QQmlJSMetaMethod selectConstructor(
228 const QQmlJSScope::ConstPtr &type, const QQmlJSScope::ConstPtr &argument,
229 bool *isExtension) const;
230
231 bool areEquivalentLists(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const;
232
233 bool isTriviallyCopyable(const QQmlJSScope::ConstPtr &type) const;
234
235 bool inherits(const QQmlJSScope::ConstPtr &derived, const QQmlJSScope::ConstPtr &base) const;
236 QQmlJSLogger *logger() const { return m_logger; }
237 QStringList seenModuleQualifiers() const { return m_seenModuleQualifiers; }
238
239protected:
240
241 QQmlJSRegisterContent memberType(
242 const QQmlJSScope::ConstPtr &type, const QString &name,
243 int baseLookupIndex, int resultLookupIndex) const;
244 QQmlJSRegisterContent memberEnumType(const QQmlJSScope::ConstPtr &type,
245 const QString &name) const;
246 bool checkEnums(const QQmlJSScope::ConstPtr &scope, const QString &name,
247 QQmlJSRegisterContent *result, QQmlJSScope::ExtensionKind mode) const;
248 bool canPrimitivelyConvertFromTo(
249 const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const;
250 QQmlJSRegisterContent lengthProperty(bool isWritable, const QQmlJSScope::ConstPtr &scope) const;
251 QQmlJSRegisterContent transformed(
252 const QQmlJSRegisterContent &origin,
253 QQmlJSScope::ConstPtr (QQmlJSTypeResolver::*op)(const QQmlJSScope::ConstPtr &) const) const;
254
255 QQmlJSRegisterContent registerContentForName(
256 const QString &name,
257 const QQmlJSScope::ConstPtr &scopeType = QQmlJSScope::ConstPtr(),
258 bool hasObjectModuelPrefix = false) const;
259
260 bool canFindComponentBoundaries(const QQmlJSScope::ConstPtr &scope) const;
261
262 QQmlJSScope::ConstPtr m_voidType;
263 QQmlJSScope::ConstPtr m_emptyType;
264 QQmlJSScope::ConstPtr m_nullType;
265 QQmlJSScope::ConstPtr m_numberPrototype;
266 QQmlJSScope::ConstPtr m_arrayPrototype;
267 QQmlJSScope::ConstPtr m_realType;
268 QQmlJSScope::ConstPtr m_floatType;
269 QQmlJSScope::ConstPtr m_int8Type;
270 QQmlJSScope::ConstPtr m_uint8Type;
271 QQmlJSScope::ConstPtr m_int16Type;
272 QQmlJSScope::ConstPtr m_uint16Type;
273 QQmlJSScope::ConstPtr m_int32Type;
274 QQmlJSScope::ConstPtr m_uint32Type;
275 QQmlJSScope::ConstPtr m_int64Type;
276 QQmlJSScope::ConstPtr m_uint64Type;
277 QQmlJSScope::ConstPtr m_sizeType;
278 QQmlJSScope::ConstPtr m_boolType;
279 QQmlJSScope::ConstPtr m_stringType;
280 QQmlJSScope::ConstPtr m_stringListType;
281 QQmlJSScope::ConstPtr m_byteArrayType;
282 QQmlJSScope::ConstPtr m_urlType;
283 QQmlJSScope::ConstPtr m_dateTimeType;
284 QQmlJSScope::ConstPtr m_dateType;
285 QQmlJSScope::ConstPtr m_timeType;
286 QQmlJSScope::ConstPtr m_variantListType;
287 QQmlJSScope::ConstPtr m_variantMapType;
288 QQmlJSScope::ConstPtr m_varType;
289 QQmlJSScope::ConstPtr m_jsValueType;
290 QQmlJSScope::ConstPtr m_jsPrimitiveType;
291 QQmlJSScope::ConstPtr m_listPropertyType;
292 QQmlJSScope::ConstPtr m_qObjectType;
293 QQmlJSScope::ConstPtr m_qObjectListType;
294 QQmlJSScope::ConstPtr m_qQmlScriptStringType;
295 QQmlJSScope::ConstPtr m_metaObjectType;
296 QQmlJSScope::ConstPtr m_functionType;
297 QQmlJSScope::ConstPtr m_jsGlobalObject;
298 QQmlJSScope::ConstPtr m_forInIteratorPtr;
299 QQmlJSScope::ConstPtr m_forOfIteratorPtr;
300
301 QQmlJSScopesById m_objectsById;
302 QHash<QV4::CompiledData::Location, QQmlJSScope::ConstPtr> m_objectsByLocation;
303 QQmlJSImporter::ImportedTypes m_imports;
304 QHash<QQmlJS::SourceLocation, QQmlJSMetaSignalHandler> m_signalHandlers;
305 QStringList m_seenModuleQualifiers;
306
307 ParentMode m_parentMode = UseParentProperty;
308 CloneMode m_cloneMode = CloneTypes;
309 QQmlJSLogger *m_logger = nullptr;
310
311 struct TrackedType
312 {
313 // The type originally found via type analysis.
314 QQmlJSScope::ConstPtr original;
315
316 // Any later replacement used to overwrite the contents of the clone.
317 QQmlJSScope::ConstPtr replacement;
318
319 // A clone of original, used to track the type,
320 // contents possibly overwritten by replacement.
321 QQmlJSScope::Ptr clone;
322 };
323
324 std::unique_ptr<QHash<QQmlJSScope::ConstPtr, TrackedType>> m_trackedTypes;
325};
326
327/*!
328\internal
329
330QQmlJSTypeResolver expects to be outlived by its importer and mapper. It crashes when its importer
331or mapper gets destructed. Therefore, you can use this struct to extend the lifetime of its
332dependencies in case you need to store the resolver as a class member.
333QQmlJSTypeResolver also expects to be outlived by the logger used by the importvisitor, while the
334importvisitor actually does not and will not outlive the QQmlJSTypeResolver.
335*/
336struct QQmlJSTypeResolverDependencies
337{
338 std::shared_ptr<QQmlJSImporter> importer;
339 std::shared_ptr<QQmlJSResourceFileMapper> mapper;
340 std::shared_ptr<QQmlJSLogger> logger;
341};
342
343QT_END_NAMESPACE
344
345#endif // QQMLJSTYPERESOLVER_P_H
346

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