1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39#ifndef QQMLTYPECOMPILER_P_H
40#define QQMLTYPECOMPILER_P_H
41
42//
43// W A R N I N G
44// -------------
45//
46// This file is not part of the Qt API. It exists purely as an
47// implementation detail. This header file may change from version to
48// version without notice, or even be removed.
49//
50// We mean it.
51//
52
53#include <qglobal.h>
54#include <qqmlerror.h>
55#include <qhash.h>
56#include <private/qqmltypeloader_p.h>
57#include <private/qqmlirbuilder_p.h>
58#include <private/qqmlpropertycachecreator_p.h>
59
60QT_BEGIN_NAMESPACE
61
62class QQmlEnginePrivate;
63class QQmlError;
64class QQmlTypeData;
65class QQmlImports;
66
67namespace QmlIR {
68struct Document;
69}
70
71namespace QV4 {
72namespace CompiledData {
73struct QmlUnit;
74struct Location;
75}
76}
77
78struct QQmlTypeCompiler
79{
80 Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
81public:
82 QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document,
83 const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
84 QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
85 const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
86
87 // --- interface used by QQmlPropertyCacheCreator
88 typedef QmlIR::Object CompiledObject;
89 const QmlIR::Object *objectAt(int index) const { return document->objects.at(index); }
90 int objectCount() const { return document->objects.count(); }
91 QString stringAt(int idx) const;
92 QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
93 QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
94 QV4::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
95 // ---
96
97 QQmlRefPointer<QV4::ExecutableCompilationUnit> compile();
98
99 QList<QQmlError> compilationErrors() const { return errors; }
100 void recordError(const QV4::CompiledData::Location &location, const QString &description);
101 void recordError(const QQmlJS::DiagnosticMessage &error);
102
103 int registerString(const QString &str);
104 int registerConstant(QV4::ReturnedValue v);
105
106 const QV4::CompiledData::Unit *qmlUnit() const;
107
108 QUrl url() const { return typeData->finalUrl(); }
109 QQmlEnginePrivate *enginePrivate() const { return engine; }
110 const QQmlImports *imports() const;
111 QVector<QmlIR::Object *> *qmlObjects() const;
112 void setPropertyCaches(QQmlPropertyCacheVector &&caches);
113 const QQmlPropertyCacheVector *propertyCaches() const;
114 QQmlPropertyCacheVector &&takePropertyCaches();
115 void setComponentRoots(const QVector<quint32> &roots) { m_componentRoots = roots; }
116 const QVector<quint32> &componentRoots() const { return m_componentRoots; }
117 QQmlJS::MemoryPool *memoryPool();
118 QStringRef newStringRef(const QString &string);
119 const QV4::Compiler::StringTableGenerator *stringPool() const;
120
121 const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
122
123 QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const;
124
125 void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
126
127 QV4::ResolvedTypeReference *resolvedType(int id) const
128 {
129 return resolvedTypes->value(id);
130 }
131
132private:
133 QList<QQmlError> errors;
134 QQmlEnginePrivate *engine;
135 QQmlTypeData *typeData;
136 const QV4::CompiledData::DependentTypesHasher &dependencyHasher;
137 QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
138 QmlIR::Document *document;
139 // index is string index of type name (use obj->inheritedTypeNameIndex)
140 QHash<int, QQmlCustomParser*> customParsers;
141
142 // index in first hash is component index, vector inside contains object indices of objects with id property
143 QVector<quint32> m_componentRoots;
144 QQmlPropertyCacheVector m_propertyCaches;
145};
146
147struct QQmlCompilePass
148{
149 QQmlCompilePass(QQmlTypeCompiler *typeCompiler);
150
151 QString stringAt(int idx) const { return compiler->stringAt(idx); }
152protected:
153 void recordError(const QV4::CompiledData::Location &location, const QString &description) const
154 { compiler->recordError(location, description); }
155 void recordError(const QQmlJS::DiagnosticMessage &error)
156 { compiler->recordError(error); }
157
158 QV4::ResolvedTypeReference *resolvedType(int id) const
159 { return compiler->resolvedType(id); }
160 bool containsResolvedType(int id) const
161 { return compiler->resolvedTypes->contains(id); }
162 QV4::ResolvedTypeReferenceMap::iterator insertResolvedType(
163 int id, QV4::ResolvedTypeReference *value)
164 { return compiler->resolvedTypes->insert(id, value); }
165
166 QQmlTypeCompiler *compiler;
167};
168
169// "Converts" signal expressions to full-fleged function declarations with
170// parameters taken from the signal declarations
171// It also updates the QV4::CompiledData::Binding objects to set the property name
172// to the final signal name (onTextChanged -> textChanged) and sets the IsSignalExpression flag.
173struct SignalHandlerConverter : public QQmlCompilePass
174{
175 Q_DECLARE_TR_FUNCTIONS(SignalHandlerConverter)
176public:
177 SignalHandlerConverter(QQmlTypeCompiler *typeCompiler);
178
179 bool convertSignalHandlerExpressionsToFunctionDeclarations();
180
181private:
182 bool convertSignalHandlerExpressionsToFunctionDeclarations(const QmlIR::Object *obj, const QString &typeName, QQmlPropertyCache *propertyCache);
183
184 QQmlEnginePrivate *enginePrivate;
185 const QVector<QmlIR::Object*> &qmlObjects;
186 const QQmlImports *imports;
187 const QHash<int, QQmlCustomParser*> &customParsers;
188 const QSet<QString> &illegalNames;
189 const QQmlPropertyCacheVector * const propertyCaches;
190};
191
192// ### This will go away when the codegen resolves all enums to constant expressions
193// and we replace the constant expression with a literal binding instead of using
194// a script.
195class QQmlEnumTypeResolver : public QQmlCompilePass
196{
197 Q_DECLARE_TR_FUNCTIONS(QQmlEnumTypeResolver)
198public:
199 QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler);
200
201 bool resolveEnumBindings();
202
203private:
204 bool assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject);
205 bool assignEnumToBinding(QmlIR::Binding *binding, const QString &enumName, int enumValue, bool isQtObject)
206 {
207 return assignEnumToBinding(binding, QStringRef(&enumName), enumValue, isQtObject);
208 }
209 bool tryQualifiedEnumAssignment(const QmlIR::Object *obj, const QQmlPropertyCache *propertyCache,
210 const QQmlPropertyData *prop,
211 QmlIR::Binding *binding);
212 int evaluateEnum(const QString &scope, const QStringRef &enumName, const QStringRef &enumValue, bool *ok) const;
213
214
215 const QVector<QmlIR::Object*> &qmlObjects;
216 const QQmlPropertyCacheVector * const propertyCaches;
217 const QQmlImports *imports;
218};
219
220class QQmlCustomParserScriptIndexer: public QQmlCompilePass
221{
222public:
223 QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler);
224
225 void annotateBindingsWithScriptStrings();
226
227private:
228 void scanObjectRecursively(int objectIndex, bool annotateScriptBindings = false);
229
230 const QVector<QmlIR::Object*> &qmlObjects;
231 const QHash<int, QQmlCustomParser*> &customParsers;
232};
233
234// Annotate properties bound to aliases with a flag
235class QQmlAliasAnnotator : public QQmlCompilePass
236{
237public:
238 QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler);
239
240 void annotateBindingsToAliases();
241private:
242 const QVector<QmlIR::Object*> &qmlObjects;
243 const QQmlPropertyCacheVector * const propertyCaches;
244};
245
246class QQmlScriptStringScanner : public QQmlCompilePass
247{
248public:
249 QQmlScriptStringScanner(QQmlTypeCompiler *typeCompiler);
250
251 void scan();
252
253private:
254 const QVector<QmlIR::Object*> &qmlObjects;
255 const QQmlPropertyCacheVector * const propertyCaches;
256};
257
258class QQmlComponentAndAliasResolver : public QQmlCompilePass
259{
260 Q_DECLARE_TR_FUNCTIONS(QQmlAnonymousComponentResolver)
261public:
262 QQmlComponentAndAliasResolver(QQmlTypeCompiler *typeCompiler);
263
264 bool resolve();
265
266protected:
267 void findAndRegisterImplicitComponents(const QmlIR::Object *obj, QQmlPropertyCache *propertyCache);
268 bool collectIdsAndAliases(int objectIndex);
269 bool resolveAliases(int componentIndex);
270 void propertyDataForAlias(QmlIR::Alias *alias, int *type, quint32 *propertyFlags);
271
272 enum AliasResolutionResult {
273 NoAliasResolved,
274 SomeAliasesResolved,
275 AllAliasesResolved
276 };
277
278 AliasResolutionResult resolveAliasesInObject(int objectIndex, QQmlJS::DiagnosticMessage *error);
279
280 QQmlEnginePrivate *enginePrivate;
281 QQmlJS::MemoryPool *pool;
282
283 QVector<QmlIR::Object*> *qmlObjects;
284
285 // indices of the objects that are actually Component {}
286 QVector<quint32> componentRoots;
287
288 // Deliberate choice of map over hash here to ensure stable generated output.
289 QMap<int, int> _idToObjectIndex;
290 QVector<int> _objectsWithAliases;
291
292 QQmlPropertyCacheVector propertyCaches;
293};
294
295class QQmlDeferredAndCustomParserBindingScanner : public QQmlCompilePass
296{
297public:
298 QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler);
299
300 bool scanObject();
301
302private:
303 bool scanObject(int objectIndex);
304
305 QVector<QmlIR::Object*> *qmlObjects;
306 const QQmlPropertyCacheVector * const propertyCaches;
307 const QHash<int, QQmlCustomParser*> &customParsers;
308
309 bool _seenObjectWithId;
310};
311
312class QQmlDefaultPropertyMerger : public QQmlCompilePass
313{
314public:
315 QQmlDefaultPropertyMerger(QQmlTypeCompiler *typeCompiler);
316
317 void mergeDefaultProperties();
318
319private:
320 void mergeDefaultProperties(int objectIndex);
321
322 const QVector<QmlIR::Object*> &qmlObjects;
323 const QQmlPropertyCacheVector * const propertyCaches;
324};
325
326QT_END_NAMESPACE
327
328#endif // QQMLTYPECOMPILER_P_H
329