diff options
| author | Sami Shalayel <sami.shalayel@qt.io> | 2024-02-14 17:34:58 +0100 |
|---|---|---|
| committer | Sami Shalayel <sami.shalayel@qt.io> | 2024-02-29 12:08:08 +0100 |
| commit | 4aa1deee1be966a6491ab5a1c1de09707a5e8215 (patch) | |
| tree | ae0ced58db9ada0fd79c5f5b42f65a3c28a3273f /src/qmlcompiler/qqmljsimportvisitor.cpp | |
| parent | 7bd3dc561afa49d01f9ef0451f129eb78b34d55e (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.cpp | 56 |
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")); |
