diff options
| author | Olivier De Cannière <olivier.decanniere@qt.io> | 2025-06-05 16:50:26 +0200 |
|---|---|---|
| committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2025-06-10 13:25:50 +0200 |
| commit | f64ba5dec875927163bb917597bac51540eb4097 (patch) | |
| tree | 5b8e88662728c56e92730bb3f9ecd444a62bc90a /src/qml/jsruntime/qv4function.cpp | |
| parent | 6cc919ab3f1782f37b05f3f445dad62672fe9895 (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.cpp | 66 |
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 ¶m) { + 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 ¶m, + 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() |
