Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlcustomparser.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <private/qv4compileddata_p.h>
8#include <private/qqmlsourcecoordinate_p.h>
9
10#include <QtCore/qdebug.h>
11
13
30/*
31 \fn QByteArray QQmlCustomParser::compile(const QList<QQmlCustomParserProperty> & properties)
32
33 The custom parser processes \a properties, and returns
34 a QByteArray containing data meaningful only to the
35 custom parser; the type engine will pass this same data to
36 setCustomData() when making an instance of the data.
37
38 Errors must be reported via the error() functions.
39
40 The QByteArray may be cached between executions of the system, so
41 it must contain correctly-serialized data (not, for example,
42 pointers to stack objects).
43*/
44
45/*
46 \fn void QQmlCustomParser::setCustomData(QObject *object, const QByteArray &data)
47
48 This function sets \a object to have the properties defined
49 by \a data, which is a block of data previously returned by a call
50 to compile().
51
52 Errors should be reported using qmlWarning(object).
53
54 The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE.
55*/
56
58{
59 exceptions.clear();
60}
61
68{
70 error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
71 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
72 error.setDescription(description);
73
74 exceptions << error;
75}
76
85int QQmlCustomParser::evaluateEnum(const QString &script, bool *ok) const
86{
87 Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer");
88 *ok = false;
89
90 // we support one or two '.' in the enum phrase:
91 // * <TypeName>.<EnumValue>
92 // * <TypeName>.<ScopedEnumName>.<EnumValue>
93
94 auto nextDot = [&](int dot) {
95 const int nextDot = script.indexOf(u'.', dot + 1);
96 return (nextDot == script.size() - 1) ? -1 : nextDot;
97 };
98
99 int dot = nextDot(-1);
100 if (dot == -1)
101 return -1;
102
103 const QString scope = script.left(dot);
104
105 if (scope != QLatin1String("Qt")) {
106 if (!engine || imports.isNull())
107 return -1;
109
110 QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine);
111 Q_ASSERT(typeLoader);
112
113 if (imports.isT1()) {
114 QQmlImportNamespace *ns = nullptr;
115
116 // Pass &recursionDetected to resolveType because that implicitly allows recursion.
117 // This way we can find the QQmlType of the document we're currently validating.
118 bool recursionDetected = false;
119
120 if (!imports.asT1()->resolveType(
121 typeLoader, scope, &type, nullptr, &ns, nullptr,
122 QQmlType::AnyRegistrationType, &recursionDetected)) {
123 return -1;
124 }
125
126 if (!type.isValid() && ns != nullptr) {
127 dot = nextDot(dot);
128 if (dot == -1 || !imports.asT1()->resolveType(
129 typeLoader, script.left(dot), &type, nullptr, nullptr, nullptr,
130 QQmlType::AnyRegistrationType, &recursionDetected)) {
131 return -1;
132 }
133 }
134 } else {
135 // Allow recursion so that we can find enums from the same document.
137 = imports.asT2()->query<QQmlImport::AllowRecursion>(scope, typeLoader);
138 if (result.isValid()) {
139 type = result.type;
140 } else if (result.importNamespace) {
141 dot = nextDot(dot);
142 if (dot != -1) {
144 script.left(dot), typeLoader).type;
145 }
146 }
147 }
148
149 if (!type.isValid())
150 return -1;
151
152 const int dot2 = nextDot(dot);
153 const bool dot2Valid = (dot2 != -1);
154 const QString enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1);
155 const QString scopedEnumName = dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QString();
156
157 // If we're currently validating the same document, we won't be able to find its enums using
158 // the QQmlType. However, we do have the property cache already, and that one contains the
159 // enums.
160 const QUrl documentUrl = validator ? validator->documentSourceUrl() : QUrl();
161 if (documentUrl.isValid() && documentUrl == type.sourceUrl()) {
162 Q_ASSERT(validator);
163 const QQmlPropertyCache::ConstPtr rootCache = validator->rootPropertyCache();
164 const int count = rootCache->qmlEnumCount();
165 for (int ii = 0; ii < count; ++ii) {
166 const QQmlEnumData *enumData = rootCache->qmlEnum(ii);
167 if (!scopedEnumName.isEmpty() && scopedEnumName != enumData->name)
168 continue;
169
170 for (int jj = 0; jj < enumData->values.size(); ++jj) {
171 const QQmlEnumValue value = enumData->values.at(jj);
172 if (value.namedValue == enumValue) {
173 *ok = true;
174 return value.value;
175 }
176 }
177 }
178 return -1;
179 }
180
181 if (!scopedEnumName.isEmpty())
182 return type.scopedEnumValue(engine, scopedEnumName, enumValue, ok);
183 else
184 return type.enumValue(engine, enumValue, ok);
185 }
186
187 const QString enumValue = script.mid(dot + 1);
188 const QMetaObject *mo = &Qt::staticMetaObject;
189 int i = mo->enumeratorCount();
190 while (i--) {
191 int v = mo->enumerator(i).keyToValue(enumValue.toUtf8().constData(), ok);
192 if (*ok)
193 return v;
194 }
195 return -1;
196}
197
203{
204 if (!engine || !imports.isT1())
205 return nullptr;
206 QQmlType qmltype;
207 if (!imports.asT1()->resolveType(QQmlTypeLoader::get(engine), name, &qmltype, nullptr, nullptr))
208 return nullptr;
209 return qmltype.metaObject();
210}
211
T * asT1() const
bool isNull() const
bool isT1() const
T2 * asT2() const
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
const QMetaObject * resolveType(const QString &) const
Resolves name to a type, or 0 if it is not a type.
void error(const QV4::CompiledData::Binding *binding, const QString &description)
int evaluateEnum(const QString &, bool *ok) const
If script is a simple enumeration expression (eg.
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDetected=nullptr) const
QQmlPropertyCache::ConstPtr rootPropertyCache() const
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
static QQmlTypeLoader * get(Engine *engine)
Result query(const QHashedStringRef &key, QQmlTypeLoader *typeLoader) const
@ AnyRegistrationType
Definition qqmltype_p.h:167
const QMetaObject * metaObject() const
Definition qqmltype.cpp:683
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString left(qsizetype n) const &
Definition qstring.h:363
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
QByteArray toUtf8() const &
Definition qstring.h:634
\inmodule QtCore
Definition qurl.h:94
auto mo
[7]
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLint location
GLsizei const GLfloat * v
[13]
GLenum GLenum GLsizei count
GLenum type
GLuint name
GLuint64EXT * result
[6]
static qreal dot(const QPointF &a, const QPointF &b)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
\inmodule QtCore