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 <private/qtqmlcompilerexports_p.h> |
18 | |
19 | #include <private/qqmlirbuilder_p.h> |
20 | #include <private/qqmljsast_p.h> |
21 | #include "qqmljsimporter_p.h" |
22 | #include "qqmljslogger_p.h" |
23 | #include "qqmljsregistercontent_p.h" |
24 | #include "qqmljsscope_p.h" |
25 | #include "qqmljsscopesbyid_p.h" |
26 | |
27 | QT_BEGIN_NAMESPACE |
28 | |
29 | class QQmlJSImportVisitor; |
30 | class Q_QMLCOMPILER_PRIVATE_EXPORT QQmlJSTypeResolver |
31 | { |
32 | public: |
33 | enum ParentMode { UseDocumentParent, UseParentProperty }; |
34 | enum CloneMode { CloneTypes, DoNotCloneTypes }; |
35 | enum ListMode { UseListProperty, UseQObjectList }; |
36 | |
37 | QQmlJSTypeResolver(QQmlJSImporter *importer); |
38 | |
39 | // Note: must be called after the construction to read the QML program |
40 | void init(QQmlJSImportVisitor *visitor, QQmlJS::AST::Node *program); |
41 | |
42 | QQmlJSScope::ConstPtr voidType() const { return m_voidType; } |
43 | QQmlJSScope::ConstPtr emptyType() const { return m_emptyType; } |
44 | QQmlJSScope::ConstPtr nullType() const { return m_nullType; } |
45 | QQmlJSScope::ConstPtr realType() const { return m_realType; } |
46 | QQmlJSScope::ConstPtr floatType() const { return m_floatType; } |
47 | QQmlJSScope::ConstPtr int8Type() const { return m_int8Type; } |
48 | QQmlJSScope::ConstPtr uint8Type() const { return m_uint8Type; } |
49 | QQmlJSScope::ConstPtr int16Type() const { return m_int16Type; } |
50 | QQmlJSScope::ConstPtr uint16Type() const { return m_uint16Type; } |
51 | QQmlJSScope::ConstPtr int32Type() const { return m_int32Type; } |
52 | QQmlJSScope::ConstPtr uint32Type() const { return m_uint32Type; } |
53 | QQmlJSScope::ConstPtr int64Type() const { return m_int64Type; } |
54 | QQmlJSScope::ConstPtr uint64Type() const { return m_uint64Type; } |
55 | QQmlJSScope::ConstPtr boolType() const { return m_boolType; } |
56 | QQmlJSScope::ConstPtr stringType() const { return m_stringType; } |
57 | QQmlJSScope::ConstPtr stringListType() const { return m_stringListType; } |
58 | QQmlJSScope::ConstPtr byteArrayType() const { return m_byteArrayType; } |
59 | QQmlJSScope::ConstPtr urlType() const { return m_urlType; } |
60 | QQmlJSScope::ConstPtr dateTimeType() const { return m_dateTimeType; } |
61 | QQmlJSScope::ConstPtr dateType() const { return m_dateType; } |
62 | QQmlJSScope::ConstPtr timeType() const { return m_timeType; } |
63 | QQmlJSScope::ConstPtr variantListType() const { return m_variantListType; } |
64 | QQmlJSScope::ConstPtr variantMapType() const { return m_variantMapType; } |
65 | QQmlJSScope::ConstPtr varType() const { return m_varType; } |
66 | QQmlJSScope::ConstPtr jsValueType() const { return m_jsValueType; } |
67 | QQmlJSScope::ConstPtr jsPrimitiveType() const { return m_jsPrimitiveType; } |
68 | QQmlJSScope::ConstPtr listPropertyType() const { return m_listPropertyType; } |
69 | QQmlJSScope::ConstPtr metaObjectType() const { return m_metaObjectType; } |
70 | QQmlJSScope::ConstPtr functionType() const { return m_functionType; } |
71 | QQmlJSScope::ConstPtr jsGlobalObject() const { return m_jsGlobalObject; } |
72 | QQmlJSScope::ConstPtr qObjectType() const { return m_qObjectType; } |
73 | QQmlJSScope::ConstPtr qObjectListType() const { return m_qObjectListType; } |
74 | QQmlJSScope::ConstPtr arrayType() const { return m_arrayType; } |
75 | |
76 | QQmlJSScope::ConstPtr scopeForLocation(const QV4::CompiledData::Location &location) const; |
77 | QQmlJSScope::ConstPtr scopeForId( |
78 | const QString &id, const QQmlJSScope::ConstPtr &referrer) const; |
79 | QString idForScope( |
80 | const QQmlJSScope::ConstPtr &scope, const QQmlJSScope::ConstPtr &referrer) const; |
81 | |
82 | bool isPrefix(const QString &name) const |
83 | { |
84 | return m_imports.hasType(name) && !m_imports.type(name).scope; |
85 | } |
86 | |
87 | QQmlJSScope::ConstPtr typeForName(const QString &name) const |
88 | { |
89 | return m_imports.type(name).scope; |
90 | } |
91 | QQmlJSScope::ConstPtr typeFromAST(QQmlJS::AST::Type *type) const; |
92 | QQmlJSScope::ConstPtr typeForConst(QV4::ReturnedValue rv) const; |
93 | QQmlJSRegisterContent typeForBinaryOperation(QSOperator::Op oper, |
94 | const QQmlJSRegisterContent &left, |
95 | const QQmlJSRegisterContent &right) const; |
96 | |
97 | enum class UnaryOperator { Not, Plus, Minus, Increment, Decrement, Complement }; |
98 | QQmlJSRegisterContent typeForArithmeticUnaryOperation( |
99 | UnaryOperator op, const QQmlJSRegisterContent &operand) const; |
100 | |
101 | bool isPrimitive(const QQmlJSRegisterContent &type) const; |
102 | bool isNumeric(const QQmlJSRegisterContent &type) const; |
103 | bool isIntegral(const QQmlJSRegisterContent &type) const; |
104 | |
105 | bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const; |
106 | bool canConvertFromTo(const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const; |
107 | QQmlJSRegisterContent merge(const QQmlJSRegisterContent &a, |
108 | const QQmlJSRegisterContent &b) const; |
109 | |
110 | enum class ComponentIsGeneric { No, Yes }; |
111 | QQmlJSScope::ConstPtr |
112 | genericType(const QQmlJSScope::ConstPtr &type, |
113 | ComponentIsGeneric allowComponent = ComponentIsGeneric::No) const; |
114 | |
115 | QQmlJSRegisterContent builtinType(const QQmlJSScope::ConstPtr &type) const; |
116 | QQmlJSRegisterContent globalType(const QQmlJSScope::ConstPtr &type) const; |
117 | QQmlJSRegisterContent scopedType(const QQmlJSScope::ConstPtr &scope, const QString &name) const; |
118 | QQmlJSRegisterContent memberType(const QQmlJSRegisterContent &type, const QString &name) const; |
119 | QQmlJSRegisterContent valueType(const QQmlJSRegisterContent &list) const; |
120 | QQmlJSRegisterContent returnType( |
121 | const QQmlJSScope::ConstPtr &type, QQmlJSRegisterContent::ContentVariant variant, |
122 | const QQmlJSScope::ConstPtr &scope) const; |
123 | |
124 | bool registerIsStoredIn(const QQmlJSRegisterContent ®, |
125 | const QQmlJSScope::ConstPtr &type) const; |
126 | bool registerContains(const QQmlJSRegisterContent ®, |
127 | const QQmlJSScope::ConstPtr &type) const; |
128 | QQmlJSScope::ConstPtr containedType(const QQmlJSRegisterContent &container) const; |
129 | QString containedTypeName(const QQmlJSRegisterContent &container, |
130 | bool useFancyName = false) const; |
131 | |
132 | QQmlJSRegisterContent tracked(const QQmlJSRegisterContent &type) const; |
133 | QQmlJSRegisterContent original(const QQmlJSRegisterContent &type) const; |
134 | |
135 | QQmlJSScope::ConstPtr trackedContainedType(const QQmlJSRegisterContent &container) const; |
136 | QQmlJSScope::ConstPtr originalContainedType(const QQmlJSRegisterContent &container) const; |
137 | |
138 | [[nodiscard]] bool adjustTrackedType( |
139 | const QQmlJSScope::ConstPtr &tracked, const QQmlJSScope::ConstPtr &conversion) const; |
140 | [[nodiscard]] bool adjustTrackedType( |
141 | const QQmlJSScope::ConstPtr &tracked, |
142 | const QList<QQmlJSScope::ConstPtr> &conversions) const; |
143 | void adjustOriginalType( |
144 | const QQmlJSScope::ConstPtr &tracked, const QQmlJSScope::ConstPtr &conversion) const; |
145 | void generalizeType(const QQmlJSScope::ConstPtr &type) const; |
146 | |
147 | void setParentMode(ParentMode mode) { m_parentMode = mode; } |
148 | ParentMode parentMode() const { return m_parentMode; } |
149 | |
150 | void setCloneMode(CloneMode mode) { m_cloneMode = mode; } |
151 | bool cloneMode() const { return m_cloneMode; } |
152 | |
153 | QQmlJSScope::ConstPtr storedType(const QQmlJSScope::ConstPtr &type) const; |
154 | QQmlJSScope::ConstPtr originalType(const QQmlJSScope::ConstPtr &type) const; |
155 | QQmlJSScope::ConstPtr trackedType(const QQmlJSScope::ConstPtr &type) const; |
156 | QQmlJSScope::ConstPtr comparableType(const QQmlJSScope::ConstPtr &type) const; |
157 | |
158 | const QQmlJSScopesById &objectsById() const { return m_objectsById; } |
159 | bool canCallJSFunctions() const { return m_objectsById.signaturesAreEnforced(); } |
160 | bool canAddressValueTypes() const { return m_objectsById.valueTypesAreAddressable(); } |
161 | |
162 | const QHash<QQmlJS::SourceLocation, QQmlJSMetaSignalHandler> &signalHandlers() const |
163 | { |
164 | return m_signalHandlers; |
165 | } |
166 | |
167 | bool equals(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const; |
168 | |
169 | QQmlJSRegisterContent convert( |
170 | const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const; |
171 | |
172 | QQmlJSScope::ConstPtr merge(const QQmlJSScope::ConstPtr &a, |
173 | const QQmlJSScope::ConstPtr &b) const; |
174 | |
175 | bool canHoldUndefined(const QQmlJSRegisterContent &content) const; |
176 | bool isNumeric(const QQmlJSScope::ConstPtr &type) const; |
177 | bool isIntegral(const QQmlJSScope::ConstPtr &type) const; |
178 | bool isSignedInteger(const QQmlJSScope::ConstPtr &type) const; |
179 | bool isUnsignedInteger(const QQmlJSScope::ConstPtr &type) const; |
180 | |
181 | bool canHold(const QQmlJSScope::ConstPtr &container, |
182 | const QQmlJSScope::ConstPtr &contained) const; |
183 | |
184 | QQmlJSMetaMethod selectConstructor( |
185 | const QQmlJSScope::ConstPtr &type, const QQmlJSScope::ConstPtr &argument, |
186 | bool *isExtension) const; |
187 | |
188 | bool areEquivalentLists(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const; |
189 | |
190 | protected: |
191 | |
192 | QQmlJSRegisterContent memberType(const QQmlJSScope::ConstPtr &type, const QString &name) const; |
193 | QQmlJSRegisterContent memberEnumType(const QQmlJSScope::ConstPtr &type, |
194 | const QString &name) const; |
195 | bool isPrimitive(const QQmlJSScope::ConstPtr &type) const; |
196 | bool checkEnums(const QQmlJSScope::ConstPtr &scope, const QString &name, |
197 | QQmlJSRegisterContent *result, QQmlJSScope::ExtensionKind mode) const; |
198 | bool canPrimitivelyConvertFromTo( |
199 | const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const; |
200 | QQmlJSRegisterContent lengthProperty(bool isWritable, const QQmlJSScope::ConstPtr &scope) const; |
201 | QQmlJSRegisterContent transformed( |
202 | const QQmlJSRegisterContent &origin, |
203 | QQmlJSScope::ConstPtr (QQmlJSTypeResolver::*op)(const QQmlJSScope::ConstPtr &) const) const; |
204 | |
205 | QQmlJSRegisterContent registerContentForName( |
206 | const QString &name, |
207 | const QQmlJSScope::ConstPtr &scopeType = QQmlJSScope::ConstPtr(), |
208 | bool hasObjectModuelPrefix = false) const; |
209 | |
210 | |
211 | QQmlJSScope::ConstPtr m_voidType; |
212 | QQmlJSScope::ConstPtr m_emptyType; |
213 | QQmlJSScope::ConstPtr m_nullType; |
214 | QQmlJSScope::ConstPtr m_numberPrototype; |
215 | QQmlJSScope::ConstPtr m_arrayType; |
216 | QQmlJSScope::ConstPtr m_realType; |
217 | QQmlJSScope::ConstPtr m_floatType; |
218 | QQmlJSScope::ConstPtr m_int8Type; |
219 | QQmlJSScope::ConstPtr m_uint8Type; |
220 | QQmlJSScope::ConstPtr m_int16Type; |
221 | QQmlJSScope::ConstPtr m_uint16Type; |
222 | QQmlJSScope::ConstPtr m_int32Type; |
223 | QQmlJSScope::ConstPtr m_uint32Type; |
224 | QQmlJSScope::ConstPtr m_int64Type; |
225 | QQmlJSScope::ConstPtr m_uint64Type; |
226 | QQmlJSScope::ConstPtr m_boolType; |
227 | QQmlJSScope::ConstPtr m_stringType; |
228 | QQmlJSScope::ConstPtr m_stringListType; |
229 | QQmlJSScope::ConstPtr m_byteArrayType; |
230 | QQmlJSScope::ConstPtr m_urlType; |
231 | QQmlJSScope::ConstPtr m_dateTimeType; |
232 | QQmlJSScope::ConstPtr m_dateType; |
233 | QQmlJSScope::ConstPtr m_timeType; |
234 | QQmlJSScope::ConstPtr m_variantListType; |
235 | QQmlJSScope::ConstPtr m_variantMapType; |
236 | QQmlJSScope::ConstPtr m_varType; |
237 | QQmlJSScope::ConstPtr m_jsValueType; |
238 | QQmlJSScope::ConstPtr m_jsPrimitiveType; |
239 | QQmlJSScope::ConstPtr m_listPropertyType; |
240 | QQmlJSScope::ConstPtr m_qObjectType; |
241 | QQmlJSScope::ConstPtr m_qObjectListType; |
242 | QQmlJSScope::ConstPtr m_metaObjectType; |
243 | QQmlJSScope::ConstPtr m_functionType; |
244 | QQmlJSScope::ConstPtr m_jsGlobalObject; |
245 | |
246 | QQmlJSScopesById m_objectsById; |
247 | QHash<QV4::CompiledData::Location, QQmlJSScope::ConstPtr> m_objectsByLocation; |
248 | QQmlJSImporter::ImportedTypes m_imports; |
249 | QHash<QQmlJS::SourceLocation, QQmlJSMetaSignalHandler> m_signalHandlers; |
250 | |
251 | ParentMode m_parentMode = UseParentProperty; |
252 | CloneMode m_cloneMode = CloneTypes; |
253 | QQmlJSLogger *m_logger = nullptr; |
254 | |
255 | struct TrackedType |
256 | { |
257 | // The type originally found via type analysis. |
258 | QQmlJSScope::ConstPtr original; |
259 | |
260 | // Any later replacement used to overwrite the contents of the clone. |
261 | QQmlJSScope::ConstPtr replacement; |
262 | |
263 | // A clone of original, used to track the type, |
264 | // contents possibly overwritten by replacement. |
265 | QQmlJSScope::Ptr clone; |
266 | }; |
267 | |
268 | std::unique_ptr<QHash<QQmlJSScope::ConstPtr, TrackedType>> m_trackedTypes; |
269 | }; |
270 | |
271 | QT_END_NAMESPACE |
272 | |
273 | #endif // QQMLJSTYPERESOLVER_P_H |
274 | |