aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4function.cpp
diff options
context:
space:
mode:
authorOlivier De Cannière <olivier.decanniere@qt.io>2025-06-05 16:50:26 +0200
committerOlivier De Cannière <olivier.decanniere@qt.io>2025-06-10 13:25:50 +0200
commitf64ba5dec875927163bb917597bac51540eb4097 (patch)
tree5b8e88662728c56e92730bb3f9ecd444a62bc90a /src/qml/jsruntime/qv4function.cpp
parent6cc919ab3f1782f37b05f3f445dad62672fe9895 (diff)
Qml: Warn about using enums as type annotations in functions
The warning emitted when calling functions with parameters type annotated with enums does not communicate what's wrong or how to fix it: "1 should be coerced to void because the function called is insufficiently annotated. The original value is retained. This will change in a future version of Qt." Until we support a proper representation of enums in the type system, all we can do is warn the user that this does not work. Add another warning that fires once when the function is constructed that has a better description of what is going wrong. This should provide the user with the info to solve the issue unlike the original warning. This does mean that we warn more for the same issue but it should still be beneficial overall. Task-number: QTBUG-135255 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: Icd8f8d80c6a4b9bd2b33c660394b9cf5a228a346 Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4function.cpp')
-rw-r--r--src/qml/jsruntime/qv4function.cpp66
1 files changed, 64 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 02c17d5de3..20dbff4cea 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -148,7 +148,66 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
QQmlTypeLoader *typeLoader = engine->typeLoader();
- auto findQmlType = [&](const CompiledData::ParameterType &param) {
+ const auto isEnumUsedAsType = [&](const QV4::ExecutableCompilationUnit *unit,
+ int elementNameId, QQmlTypeLoader *typeLoader,
+ const quint16 *parameter = nullptr) {
+ const QStringView name = unit->baseCompilationUnit()->stringAt(elementNameId);
+ const auto split = name.tokenize(u'.').toContainer<QVarLengthArray<QStringView, 4>>();
+ if (split.size() != 2)
+ return false;
+
+ const QStringView scopeName = split[0];
+ const QStringView enumName = split[1];
+
+ auto *pengine = QQmlEnginePrivate::get(engine);
+ const auto warn = [&] {
+ QQmlError error;
+ auto where = parameter ? QStringLiteral("parameter ") + QString::number(*parameter)
+ : QStringLiteral("return type");
+ auto msg = QStringLiteral("Type annotation for %1 of function %2: Enumerations are "
+ "not types. Use underlying type (int or double) instead.")
+ .arg(where, this->name()->toQString());
+ error.setDescription(msg);
+ error.setUrl(QUrl(sourceFile()));
+ error.setLine(this->sourceLocation().line);
+ error.setColumn(this->sourceLocation().column);
+ error.setMessageType(QtWarningMsg);
+ pengine->warning(error);
+ };
+
+ bool ok;
+ if (scopeName == QStringLiteral("Qt")) {
+ const QMetaObject *mo = &Qt::staticMetaObject;
+ for (int i = 0; i < mo->enumeratorCount(); ++i) {
+ if (mo->enumerator(i).name() == enumName.toLatin1()) {
+ warn();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ const QQmlType scope = unit->typeNameCache()->query<QQmlImport::AllowRecursion>(
+ scopeName, typeLoader).type;
+ if (!scope.isValid())
+ return false;
+
+ scope.scopedEnumIndex(typeLoader, enumName.toString(), &ok);
+ if (ok) {
+ warn();
+ return true;
+ }
+ scope.unscopedEnumIndex(typeLoader, enumName.toString(), &ok);
+ if (ok) {
+ warn();
+ return true;
+ }
+
+ return false;
+ };
+
+ auto findQmlType = [&](const CompiledData::ParameterType &param,
+ const quint16 *parameter = nullptr) {
const quint32 type = param.typeNameIndexOrCommonType();
if (param.indexIsCommonType()) {
return QQmlMetaType::qmlType(QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(
@@ -158,6 +217,9 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
if (type == 0 || !typeLoader)
return QQmlType();
+ if (isEnumUsedAsType(unit, type, typeLoader, parameter))
+ return QQmlType();
+
const QQmlType qmltype = QQmlTypePrivate::visibleQmlTypeByName(unit, type, typeLoader);
return qmltype.typeId().isValid() ? qmltype : QQmlType();
};
@@ -167,7 +229,7 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
jsTypedFunction.types.reserve(nFormals + 1);
jsTypedFunction.types.append(findQmlType(compiledFunction->returnType));
for (quint16 i = 0; i < nFormals; ++i)
- jsTypedFunction.types.append(findQmlType(formalsIndices[i].type));
+ jsTypedFunction.types.append(findQmlType(formalsIndices[i].type, &i));
}
Function::~Function()