aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler/qqmljsimportvisitor.cpp
diff options
context:
space:
mode:
authorSami Shalayel <sami.shalayel@qt.io>2024-02-14 17:34:58 +0100
committerSami Shalayel <sami.shalayel@qt.io>2024-02-29 12:08:08 +0100
commit4aa1deee1be966a6491ab5a1c1de09707a5e8215 (patch)
treeae0ced58db9ada0fd79c5f5b42f65a3c28a3273f /src/qmlcompiler/qqmljsimportvisitor.cpp
parent7bd3dc561afa49d01f9ef0451f129eb78b34d55e (diff)
qmltc/importvisitor: warn about type annotations on methods
Warn when the types in method type annotations can't be resolved. This hinders qmltc from crashing when trying to compile a QML file with an invalid type annotation like `Qt.point`. To avoid copying and replacing lists, add helpers like mutableOwnMethodsRange() or mutableParametersRange() to obtain mutable iterators to the ownMethods of QQmlJSScope or the parameters of QQmlJSMetaMethod. Pick-to: 6.6 6.7 Fixes: QTBUG-122251 Change-Id: Iffc6ff712fbeaa2fe8b83f94b0bc5a8c278d186c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qmlcompiler/qqmljsimportvisitor.cpp')
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp56
1 files changed, 54 insertions, 2 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index aba0fb9238..9c7d498b11 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -465,6 +465,7 @@ void QQmlJSImportVisitor::endVisit(UiProgram *)
setAllBindings();
processDefaultProperties();
processPropertyTypes();
+ processMethodTypes();
processPropertyBindings();
processPropertyBindingObjects();
checkRequiredProperties();
@@ -666,6 +667,39 @@ void QQmlJSImportVisitor::processPropertyTypes()
}
}
+void QQmlJSImportVisitor::processMethodTypes()
+{
+ for (const auto &type : m_pendingMethodTypes) {
+
+ for (auto [it, end] = type.scope->mutableOwnMethodsRange(type.methodName); it != end;
+ ++it) {
+ if (const auto returnType =
+ QQmlJSScope::findType(it->returnTypeName(), m_rootScopeImports).scope) {
+ it->setReturnType({ returnType });
+ } else {
+ m_logger->log(u"\"%1\" was not found for the return type of method \"%2\"."_s.arg(
+ it->returnTypeName(), it->methodName()),
+ qmlUnresolvedType, type.location);
+ }
+
+ for (auto [parameter, parameterEnd] = it->mutableParametersRange();
+ parameter != parameterEnd; ++parameter) {
+ if (const auto parameterType =
+ QQmlJSScope::findType(parameter->typeName(), m_rootScopeImports)
+ .scope) {
+ parameter->setType({ parameterType });
+ } else {
+ m_logger->log(
+ u"\"%1\" was not found for the type of parameter \"%2\" in method \"%3\"."_s
+ .arg(parameter->typeName(), parameter->name(),
+ it->methodName()),
+ qmlUnresolvedType, type.location);
+ }
+ }
+ }
+ }
+}
+
void QQmlJSImportVisitor::processPropertyBindingObjects()
{
QSet<QPair<QQmlJSScope::Ptr, QString>> foundLiterals;
@@ -1687,6 +1721,7 @@ void QQmlJSImportVisitor::visitFunctionExpressionHelper(QQmlJS::AST::FunctionExp
{
using namespace QQmlJS::AST;
auto name = fexpr->name.toString();
+ bool pending = false;
if (!name.isEmpty()) {
QQmlJSMetaMethod method(name);
method.setMethodType(QQmlJSMetaMethodType::Method);
@@ -1713,6 +1748,15 @@ void QQmlJSImportVisitor::visitFunctionExpressionHelper(QQmlJS::AST::FunctionExp
} else {
anyFormalTyped = true;
method.addParameter(QQmlJSMetaParameter(parameter.id, type));
+ if (!pending) {
+ m_pendingMethodTypes << PendingMethodType{
+ m_currentScope,
+ name,
+ combine(parameter.typeAnnotation->firstSourceLocation(),
+ parameter.typeAnnotation->lastSourceLocation())
+ };
+ pending = true;
+ }
}
}
}
@@ -1724,9 +1768,17 @@ void QQmlJSImportVisitor::visitFunctionExpressionHelper(QQmlJS::AST::FunctionExp
// Methods with only untyped arguments return an untyped value.
// Methods with at least one typed argument but no explicit return type return void.
// In order to make a function without arguments return void, you have to specify that.
- if (parseTypes && fexpr->typeAnnotation)
+ if (parseTypes && fexpr->typeAnnotation) {
method.setReturnTypeName(fexpr->typeAnnotation->type->toString());
- else if (anyFormalTyped)
+ if (!pending) {
+ m_pendingMethodTypes << PendingMethodType{
+ m_currentScope, name,
+ combine(fexpr->typeAnnotation->firstSourceLocation(),
+ fexpr->typeAnnotation->lastSourceLocation())
+ };
+ pending = true;
+ }
+ } else if (anyFormalTyped)
method.setReturnTypeName(QStringLiteral("void"));
else
method.setReturnTypeName(QStringLiteral("var"));