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
qqmltccompiler_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 QQMLTCCOMPILER_P_H
6#define QQMLTCCOMPILER_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
19#include <private/qqmltctyperesolver_p.h>
20#include <private/qqmltcvisitor_p.h>
21#include <private/qqmltcoutputir_p.h>
22
23#include <QtCore/qcommandlineparser.h>
24#include <QtCore/qcoreapplication.h>
25#include <QtCore/qstring.h>
26#include <QtCore/qhash.h>
27
28#include <private/qqmljslogger_p.h>
29
30QT_BEGIN_NAMESPACE
31
32namespace QQmltc {
33
43
45{
49
50public:
51 Compiler(const QString &url, TypeResolver *resolver, Visitor *visitor,
52 QQmlJSLogger *logger);
53 void compile(const CompilerInfo &info);
54
56
57 /*! \internal
58
59 Returns \c true if \a binding is considered complex by the compiler
60 (requires special code generation)
61 */
62 static bool isComplexBinding(const QQmlJSMetaPropertyBinding &binding)
63 {
64 // TODO: translation bindings (once supported) are also complex?
65 return binding.bindingType() == QQmlSA::BindingType::Script;
66 }
67
68private:
69 QString m_url; // QML input file url
70 TypeResolver *m_typeResolver = nullptr;
71 Visitor *m_visitor = nullptr;
72 QQmlJSLogger *m_logger = nullptr;
73 CompilerInfo m_info {}; // miscellaneous input/output information
74 QString m_urlMethodName;
75 uint m_currentVariableNumber = 0;
76
77 struct UniqueStringId;
78 struct TypeLocalData;
79 // per-type, per-property code generation cache of created symbols
80 QHash<UniqueStringId, TypeLocalData> m_uniques;
81
82 void compileUrlMethod(Method &urlMethod, const QString &urlMethodName);
83 void
84 compileType(Type &current, const QQmlJSScope::ConstPtr &type,
85 std::function<void(Type &, const QQmlJSScope::ConstPtr &)> compileElements);
86 void compileTypeElements(Type &current, const QQmlJSScope::ConstPtr &type);
87 void compileEnum(Type &current, const QQmlJSMetaEnum &e);
88 void compileMethod(Type &current, const QQmlJSMetaMethod &m,
89 const QQmlJSScope::ConstPtr &owner);
90 void compileProperty(Type &current, const QQmlJSMetaProperty &p,
91 const QQmlJSScope::ConstPtr &owner);
92 void compileAlias(Type &current, const QQmlJSMetaProperty &alias,
93 const QQmlJSScope::ConstPtr &owner);
94 void compileExtraListMethods(Type &current, const QQmlJSMetaProperty &p);
95
96 QString uniqueVariableName(const QString &qmlName)
97 {
98 QString result = u"m_"_s + QString::number(++m_currentVariableNumber) + qmlName;
99 result.replace(u'.', u'_');
100 return result;
101 }
102
103 /*!
104 \internal
105
106 Helper structure that holds the information necessary for most bindings,
107 such as accessor name, which is used to reference the properties. For
108 example:
109 > (accessor.name)->(propertyName) results in "this->myProperty"
110
111 This data is also used in more advanced scenarios by attached and
112 grouped properties
113 */
114 struct BindingAccessorData
115 {
116 QQmlJSScope::ConstPtr scope; // usually the current type
117 QString name = QStringLiteral("this");
118 QString propertyName = QString();
119 bool isValueType = false;
120 };
121
122 QStringList unprocessedListBindings;
123 QQmlJSMetaProperty unprocessedListProperty;
124
125 void processLastListBindings(Type &current, const QQmlJSScope::ConstPtr &type,
126 const BindingAccessorData &accessor);
127
128 void compileBinding(Type &current, QList<QQmlJSMetaPropertyBinding>::iterator bindingStart,
129 QList<QQmlJSMetaPropertyBinding>::iterator bindingEnd,
130 const QQmlJSScope::ConstPtr &type, const BindingAccessorData &accessor);
131
132 void compileBindingByType(Type &current, const QQmlJSMetaPropertyBinding &binding,
133 const QQmlJSScope::ConstPtr &type,
134 const BindingAccessorData &accessor);
135
136 void compileObjectBinding(Type &current, const QQmlJSMetaPropertyBinding &binding,
137 const QQmlJSScope::ConstPtr &type,
138 const BindingAccessorData &accessor);
139
140 void compileValueSourceOrInterceptorBinding(Type &current,
141 const QQmlJSMetaPropertyBinding &binding,
142 const QQmlJSScope::ConstPtr &type,
143 const BindingAccessorData &accessor);
144
145 void compileAttachedPropertyBinding(Type &current, const QQmlJSMetaPropertyBinding &binding,
146 const QQmlJSScope::ConstPtr &type,
147 const BindingAccessorData &accessor);
148
149 void compileGroupPropertyBinding(Type &current, const QQmlJSMetaPropertyBinding &binding,
150 const QQmlJSScope::ConstPtr &type,
151 const BindingAccessorData &accessor);
152
153 void compileTranslationBinding(Type &current, const QQmlJSMetaPropertyBinding &binding,
154 const QQmlJSScope::ConstPtr &type,
155 const BindingAccessorData &accessor);
156
157 // special case (for simplicity)
158 void compileScriptBinding(Type &current, const QQmlJSMetaPropertyBinding &binding,
159 const QString &bindingSymbolName, const QQmlJSScope::ConstPtr &type,
160 const QString &propertyName,
161 const QQmlJSScope::ConstPtr &propertyType,
162 const BindingAccessorData &accessor);
163
164 void compilePropertyInitializer(Type &current, const QQmlJSScope::ConstPtr &type);
165
166 /*!
167 \internal
168 Helper structure that acts as a key in a hash-table of
169 QmltcType-specific data (such as local variable names). Using a
170 hash-table allows to avoid creating the same variables multiple times
171 during binding compilation, which leads to better code generation and
172 faster object creation. This is really something that the QML optimizer
173 should do, but we have only this home-grown alternative at the moment
174 */
175 struct UniqueStringId
176 {
177 QString unique;
178 UniqueStringId(const Type &context, const QString &property)
179 : unique(context.cppType + u"_" + property) // this is unique enough
180 {
181 Q_ASSERT(!context.cppType.isEmpty());
182 Q_ASSERT(!property.isEmpty());
183 }
184 friend bool operator==(const UniqueStringId &x, const UniqueStringId &y)
185 {
186 return x.unique == y.unique;
187 }
188 friend bool operator!=(const UniqueStringId &x, const UniqueStringId &y)
189 {
190 return !(x == y);
191 }
192 friend size_t qHash(const UniqueStringId &x, size_t seed = 0)
193 {
194 return qHash(x.unique, seed);
195 }
196 };
197
198 struct TypeLocalData
199 {
200 // empty QString() means that the local data is not present (yet)
201 QString qmlListVariableName;
202 QString onAssignmentObjectName;
203 QString attachedVariableName;
204 };
205
206 QHash<QString, qsizetype> m_symbols;
207 QString newSymbol(const QString &base);
208
209 bool hasErrors() const { return m_logger->hasErrors(); }
210 void recordError(const QQmlJS::SourceLocation &location, const QString &message,
211 QQmlJS::LoggerWarningId id = qmlCompiler)
212 {
213 // pretty much any compiler error is a critical error (we cannot
214 // generate code - compilation fails)
215 m_logger->log(message, id, location);
216 }
217 void recordError(const QV4::CompiledData::Location &location, const QString &message,
218 QQmlJS::LoggerWarningId id = qmlCompiler)
219 {
220 recordError(QQmlJS::SourceLocation { 0, 0, location.line(), location.column() }, message,
221 id);
222 }
223};
224
225} // namespace QQmltc
226
227QT_END_NAMESPACE
228
229#endif // QQMLTCCOMPILER_P_H
void compile(const CompilerInfo &info)
Compiler(const QString &url, TypeResolver *resolver, Visitor *visitor, QQmlJSLogger *logger)
static bool isComplexBinding(const QQmlJSMetaPropertyBinding &binding)
bool qIsReferenceTypeList(const QQmlJSMetaProperty &p)
static QList< QQmlJSMetaProperty > unboundRequiredProperties(const QQmlJSScope::ConstPtr &type, TypeResolver *resolver)
static std::pair< QQmlJSMetaProperty, int > getMetaPropertyIndex(const QQmlJSScope::ConstPtr &scope, const QString &propertyName)
static QString generate_callCompilationUnit(const QString &urlMethodName)
static Type compileScriptBindingPropertyChangeHandler(const QQmlJSMetaPropertyBinding &binding, const QQmlJSScope::ConstPtr &objectType, const QString &urlMethodName, const QString &functorCppType, const QString &objectCppType)
static void compileRequiredPropertiesBundle(Type &current, const QQmlJSScope::ConstPtr &type, TypeResolver *resolver)
static QStringList joinFrames(const QStack< AliasResolutionFrame > &frames, Projection project)
static QList< Variable > compileMethodParameters(const QList< QQmlJSMetaParameter > &parameterInfos, bool allowUnnamed=false)
static void unpackFrames(QStack< AliasResolutionFrame > &frames)
static void compileRootExternalConstructorBody(Type &current, const QQmlJSScope::ConstPtr &type)
static Iterator partitionBindings(Iterator first, Iterator last)