diff options
author | Olivier De Cannière <olivier.decanniere@qt.io> | 2024-04-18 13:28:39 +0200 |
---|---|---|
committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2024-04-23 09:47:01 +0200 |
commit | d13a6ea1f30acc29ce3d90fb027acc41e6ee9be6 (patch) | |
tree | 2c56cd26b2c3a8187d314bfb6948e77ca7ab0b77 | |
parent | 1126785007af4e7867a17a83ba6c08f262c20ceb (diff) |
qmlcachegen: Improve warnings for missing return type annotations
Fixes: QTBUG-124220
Pick-to: 6.7
Change-Id: Ic31b90b0408d855a45e17647ab659fbbc6e17633
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
9 files changed, 93 insertions, 18 deletions
diff --git a/src/qmlcompiler/qqmljsregistercontent.cpp b/src/qmlcompiler/qqmljsregistercontent.cpp index fa89dbe0bc..2c5d562e5b 100644 --- a/src/qmlcompiler/qqmljsregistercontent.cpp +++ b/src/qmlcompiler/qqmljsregistercontent.cpp @@ -13,7 +13,6 @@ QString QQmlJSRegisterContent::descriptiveName() const if (m_storedType.isNull()) return u"(invalid type)"_s; - QString result = m_storedType->internalName() + u" of "_s; const auto scope = [this]() -> QString { if (m_scope.isNull()) return u"(invalid type)::"_s; @@ -25,36 +24,46 @@ QString QQmlJSRegisterContent::descriptiveName() const + u"::"_s; }; + QString result; switch (m_content.index()) { - case Type: - return result - + std::get<std::pair<QQmlJSScope::ConstPtr, int>>(m_content).first->internalName(); + case Type: { + auto contained = std::get<std::pair<QQmlJSScope::ConstPtr, int>>(m_content).first; + result += contained->internalName(); + if (m_storedType->internalName() != contained->internalName()) + result += u" stored as "_s + m_storedType->internalName(); + return result; + } case Property: { const QQmlJSMetaProperty prop = std::get<PropertyLookup>(m_content).property; - return result + scope() + prop.propertyName() + u" with type "_s + prop.typeName(); + result += scope() + prop.propertyName() + u" with type "_s + prop.typeName(); + if (m_storedType->internalName() != prop.typeName()) + result += u" (stored as "_s + m_storedType->internalName() + u")"; + return result; } case Method: { const auto methods = std::get<QList<QQmlJSMetaMethod>>(m_content); if (methods.isEmpty()) - return result + scope() + u"(unknown method)"_s; + result = scope() + u"(unknown method)"_s; else - return result + scope() + methods[0].methodName() + u"(...)"_s; + result = scope() + methods[0].methodName() + u"(...)"_s; + return result + u" (stored as "_s + m_storedType->internalName() + u")"; } case Enum: { const auto e = std::get<std::pair<QQmlJSMetaEnum, QString>>(m_content); if (e.second.isEmpty()) - return result + scope() + e.first.name(); + result = scope() + e.first.name(); else - return result + scope() + e.first.name() + u"::"_s + e.second; + result = scope() + e.first.name() + u"::"_s + e.second; + return result + u" (stored as "_s + m_storedType->internalName() + u")"; } case ImportNamespace: { return u"import namespace %1"_s.arg(std::get<uint>(m_content)); } case Conversion: { - return u"conversion to %1"_s.arg( - std::get<ConvertedTypes>(m_content).result->internalName()); + return u"conversion to %1"_s.arg(std::get<ConvertedTypes>(m_content).result->internalName()); } } + Q_UNREACHABLE_RETURN(result + u"wat?"_s); } diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 34e7bd975f..37b3a21130 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -90,8 +90,8 @@ void QQmlJSTypePropagator::generate_Ret() m_state.accumulatorIn(), m_typeResolver->voidType())) { // You can always return undefined. } else if (!m_returnType.isValid() && m_state.accumulatorIn().isValid()) { - setError(u"function without return type annotation returns %1"_s - .arg(m_state.accumulatorIn().descriptiveName())); + setError(u"function without return type annotation returns %1. This may prevent proper "_s + u"compilation to Cpp."_s.arg(m_state.accumulatorIn().descriptiveName())); if (m_function->isFullyTyped) { // Do not complain if the function didn't have a valid annotation in the first place. diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml new file mode 100644 index 0000000000..de142337b4 --- /dev/null +++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml @@ -0,0 +1,9 @@ +import QtQml +import QtQuick + +QtObject { + id: root + component Comp : Item { } + property Comp c: Comp{ } + function comp() { return root.c } +} diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml new file mode 100644 index 0000000000..0585ceceb2 --- /dev/null +++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml @@ -0,0 +1,5 @@ +import QtQuick + +QtObject { + function enumeration() { return Text.AlignRight } +} diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml new file mode 100644 index 0000000000..dc03311e73 --- /dev/null +++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml @@ -0,0 +1,6 @@ +import QtQml + +QtObject { + function f() { } + function method() { return f } +} diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml new file mode 100644 index 0000000000..bb79978d85 --- /dev/null +++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml @@ -0,0 +1,7 @@ +import QtQml + +QtObject { + id: root + property int i: 1 + function prop() { return root.i } +} diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml new file mode 100644 index 0000000000..78f02a8b67 --- /dev/null +++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml @@ -0,0 +1,5 @@ +import QtQml + +QtObject { + function type() { return 1 + 1 } +} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 4e69fc2e9e..f94b3e149e 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -1368,10 +1368,11 @@ void TestQmllint::compilerWarnings_data() QTest::newRow("qQmlV4Function") << QStringLiteral("varargs.qml") << Result::clean() << true; QTest::newRow("multiGrouped") << QStringLiteral("multiGrouped.qml") << Result::clean() << true; - QTest::newRow("shadowable") << QStringLiteral("shadowable.qml") - << Result { { Message { QStringLiteral( - "with type NotSoSimple can be shadowed") } } } - << true; + QTest::newRow("shadowable") + << QStringLiteral("shadowable.qml") + << Result { { Message {QStringLiteral( + "with type NotSoSimple (stored as QQuickItem) can be shadowed") } } } + << true; QTest::newRow("tooFewParameters") << QStringLiteral("tooFewParams.qml") << Result { { Message { QStringLiteral("No matching override found") } } } << true; @@ -1402,6 +1403,39 @@ void TestQmllint::compilerWarnings_data() QStringLiteral("Cannot retrieve a non-object type by ID: stateMachine") } } } << true; + QTest::newRow("returnTypeAnnotation-component") + << QStringLiteral("returnTypeAnnotation_component.qml") + << Result{ { { "Could not compile function comp: function without return type " + "annotation returns (component in" }, + { "returnTypeAnnotation_component.qml)::c with type Comp (stored as " + "QQuickItem). This may prevent proper compilation to Cpp." } } } + << true; + QTest::newRow("returnTypeAnnotation-enum") + << QStringLiteral("returnTypeAnnotation_enum.qml") + << Result{ { { "Could not compile function enumeration: function without return type " + "annotation returns QQuickText::HAlignment::AlignRight (stored as int). " + "This may prevent proper compilation to Cpp." } } } + << true; + QTest::newRow("returnTypeAnnotation-method") + << QStringLiteral("returnTypeAnnotation_method.qml") + << Result{ { { "Could not compile function method: function without return type " + "annotation returns (component in " }, // Don't check the build folder path + { "returnTypeAnnotation_method.qml)::f(...) (stored as QJSValue). This may " + "prevent proper compilation to Cpp." } } } + << true; + QTest::newRow("returnTypeAnnotation-property") + << QStringLiteral("returnTypeAnnotation_property.qml") + << Result{ { { "Could not compile function prop: function without return type " + "annotation returns (component in " }, // Don't check the build folder path + { "returnTypeAnnotation_property.qml)::i with type int. This may prevent " + "proper compilation to Cpp." } } } + << true; + QTest::newRow("returnTypeAnnotation-type") + << QStringLiteral("returnTypeAnnotation_type.qml") + << Result{ { { "Could not compile function type: function without return type " + "annotation returns double. This may prevent proper compilation to " + "Cpp." } } } + << true; } void TestQmllint::compilerWarnings() diff --git a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp index db81c77206..22aacc01b0 100644 --- a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp +++ b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp @@ -356,7 +356,7 @@ void tst_qqmljsscope::descriptiveNameOfNull() stored, property, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeProperty, QQmlJSScope::ConstPtr()); - QCOMPARE(unscoped.descriptiveName(), u"bar of (invalid type)::foo with type baz"_s); + QCOMPARE(unscoped.descriptiveName(), u"(invalid type)::foo with type baz (stored as bar)"_s); } void tst_qqmljsscope::groupedPropertiesConsistency() |