aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlcustomparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlcustomparser.cpp')
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp123
1 files changed, 65 insertions, 58 deletions
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index b0df4f26dc..bd632d25a6 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -1,42 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qml/qqmlpropertyvalidator_p.h"
#include "qqmlcustomparser_p.h"
#include <private/qv4compileddata_p.h>
@@ -102,8 +67,8 @@ void QQmlCustomParser::clearErrors()
void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const QString &description)
{
QQmlError error;
- error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line));
- error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column));
+ error.setLine(qmlConvertSourceCoordinate<quint32, int>(location.line()));
+ error.setColumn(qmlConvertSourceCoordinate<quint32, int>(location.column()));
error.setDescription(description);
exceptions << error;
@@ -117,7 +82,7 @@ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const
A valid \a ok must be provided, or the function will assert.
*/
-int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
+int QQmlCustomParser::evaluateEnum(const QString &script, bool *ok) const
{
Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer");
*ok = false;
@@ -127,40 +92,57 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
// * <TypeName>.<ScopedEnumName>.<EnumValue>
auto nextDot = [&](int dot) {
- const int nextDot = script.indexOf('.', dot + 1);
- return (nextDot == script.length() - 1) ? -1 : nextDot;
+ const int nextDot = script.indexOf(u'.', dot + 1);
+ return (nextDot == script.size() - 1) ? -1 : nextDot;
};
int dot = nextDot(-1);
if (dot == -1)
return -1;
- QString scope = QString::fromUtf8(script.left(dot));
+ const QString scope = script.left(dot);
if (scope != QLatin1String("Qt")) {
- if (imports.isNull())
+ if (!engine || imports.isNull())
return -1;
QQmlType type;
+ QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine);
+ Q_ASSERT(typeLoader);
+
if (imports.isT1()) {
QQmlImportNamespace *ns = nullptr;
- if (!imports.asT1()->resolveType(scope, &type, nullptr, &ns))
+
+ // Pass &recursionDetected to resolveType because that implicitly allows recursion.
+ // This way we can find the QQmlType of the document we're currently validating.
+ bool recursionDetected = false;
+
+ if (!imports.asT1()->resolveType(
+ typeLoader, scope, &type, nullptr, &ns, nullptr,
+ QQmlType::AnyRegistrationType, &recursionDetected)) {
return -1;
+ }
+
if (!type.isValid() && ns != nullptr) {
dot = nextDot(dot);
- if (dot == -1 || !imports.asT1()->resolveType(QString::fromUtf8(script.left(dot)),
- &type, nullptr, nullptr)) {
+ if (dot == -1 || !imports.asT1()->resolveType(
+ typeLoader, script.left(dot), &type, nullptr, nullptr, nullptr,
+ QQmlType::AnyRegistrationType, &recursionDetected)) {
return -1;
}
}
} else {
- QQmlTypeNameCache::Result result = imports.asT2()->query(scope);
+ // Allow recursion so that we can find enums from the same document.
+ const QQmlTypeNameCache::Result result
+ = imports.asT2()->query<QQmlImport::AllowRecursion>(scope, typeLoader);
if (result.isValid()) {
type = result.type;
} else if (result.importNamespace) {
dot = nextDot(dot);
- if (dot != -1)
- type = imports.asT2()->query(QString::fromUtf8(script.left(dot))).type;
+ if (dot != -1) {
+ type = imports.asT2()->query<QQmlImport::AllowRecursion>(
+ script.left(dot), typeLoader).type;
+ }
}
}
@@ -169,19 +151,44 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
const int dot2 = nextDot(dot);
const bool dot2Valid = (dot2 != -1);
- QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1);
- QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray());
+ const QString enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1);
+ const QString scopedEnumName = dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QString();
+
+ // If we're currently validating the same document, we won't be able to find its enums using
+ // the QQmlType. However, we do have the property cache already, and that one contains the
+ // enums.
+ const QUrl documentUrl = validator ? validator->documentSourceUrl() : QUrl();
+ if (documentUrl.isValid() && documentUrl == type.sourceUrl()) {
+ Q_ASSERT(validator);
+ const QQmlPropertyCache::ConstPtr rootCache = validator->rootPropertyCache();
+ const int count = rootCache->qmlEnumCount();
+ for (int ii = 0; ii < count; ++ii) {
+ const QQmlEnumData *enumData = rootCache->qmlEnum(ii);
+ if (!scopedEnumName.isEmpty() && scopedEnumName != enumData->name)
+ continue;
+
+ for (int jj = 0; jj < enumData->values.size(); ++jj) {
+ const QQmlEnumValue value = enumData->values.at(jj);
+ if (value.namedValue == enumValue) {
+ *ok = true;
+ return value.value;
+ }
+ }
+ }
+ return -1;
+ }
+
if (!scopedEnumName.isEmpty())
return type.scopedEnumValue(engine, scopedEnumName, enumValue, ok);
else
- return type.enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok);
+ return type.enumValue(engine, enumValue, ok);
}
- QByteArray enumValue = script.mid(dot + 1);
+ const QString enumValue = script.mid(dot + 1);
const QMetaObject *mo = &Qt::staticMetaObject;
int i = mo->enumeratorCount();
while (i--) {
- int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
+ int v = mo->enumerator(i).keyToValue(enumValue.toUtf8().constData(), ok);
if (*ok)
return v;
}
@@ -194,10 +201,10 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
*/
const QMetaObject *QQmlCustomParser::resolveType(const QString& name) const
{
- if (!imports.isT1())
+ if (!engine || !imports.isT1())
return nullptr;
QQmlType qmltype;
- if (!imports.asT1()->resolveType(name, &qmltype, nullptr, nullptr, nullptr))
+ if (!imports.asT1()->resolveType(QQmlTypeLoader::get(engine), name, &qmltype, nullptr, nullptr))
return nullptr;
return qmltype.metaObject();
}