aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Shalayel <[email protected]>2025-01-27 15:41:40 +0100
committerSami Shalayel <[email protected]>2025-03-06 19:23:04 +0100
commit313d473d700e2dfda8e060d3ce577b598314d0d3 (patch)
treef8c3438f611f56c6fed3d572e4d7607eeda0fdfa
parent7d3b8d0c649aa8a2846ae7a2546e9c751c3b2d98 (diff)
qdslintplugin: add UnsupportedRootTypeInQmlUi warning
Implement ErrUnsupportedTypeInQmlUi that warns about unsupported root types in .ui.qml files. Also reuse the same warning message. Task-number: QTBUG-129308 Change-Id: I83a2cb39367ea3fe6ac65ab1e0b16c04cf467d73 Reviewed-by: Ulf Hermann <[email protected]>
-rw-r--r--src/plugins/qmllint/qds/plugin.json5
-rw-r--r--src/plugins/qmllint/qds/qdslintplugin.cpp67
-rw-r--r--tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement.ui.qml3
-rw-r--r--tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement2.ui.qml7
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp16
5 files changed, 83 insertions, 15 deletions
diff --git a/src/plugins/qmllint/qds/plugin.json b/src/plugins/qmllint/qds/plugin.json
index a77ef0398b..9d9d482510 100644
--- a/src/plugins/qmllint/qds/plugin.json
+++ b/src/plugins/qmllint/qds/plugin.json
@@ -29,6 +29,11 @@
"name": "InvalidIdeInVisualDesigner",
"settingsName": "InvalidIdeInVisualDesigner",
"description": "Warn about ambiguous id names in ui.qml files"
+ },
+ {
+ "name": "UnsupportedRootTypeInQmlUi",
+ "settingsName": "UnsupportedRootTypeInQmlUi",
+ "description": "Warn about unsupported root types in ui.qml files"
}
]
}
diff --git a/src/plugins/qmllint/qds/qdslintplugin.cpp b/src/plugins/qmllint/qds/qdslintplugin.cpp
index 04a5620c33..9855ac3a52 100644
--- a/src/plugins/qmllint/qds/qdslintplugin.cpp
+++ b/src/plugins/qmllint/qds/qdslintplugin.cpp
@@ -7,6 +7,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qhash.h>
#include <QtCore/qset.h>
+#include <QtCore/qspan.h>
QT_BEGIN_NAMESPACE
@@ -29,6 +30,9 @@ static constexpr LoggerWarningId ErrUnsupportedTypeInQmlUi{
static constexpr LoggerWarningId ErrInvalidIdeInVisualDesigner{
"QtDesignStudio.InvalidIdeInVisualDesigner"
};
+static constexpr LoggerWarningId ErrUnsupportedRootTypeInQmlUi{
+ "QtDesignStudio.UnsupportedRootTypeInQmlUi"
+};
class FunctionCallValidator : public PropertyPass
{
@@ -71,7 +75,16 @@ private:
std::make_pair("QtQml.Models"_L1, "Package"_L1),
std::make_pair("QtQuick"_L1, "ShaderEffect"_L1),
};
+ using UnsupportedName = decltype(s_unsupportedElementNames)::value_type;
std::array<Element, s_unsupportedElementNames.size()> m_unsupportedElements;
+
+ static constexpr std::array s_unsupportedRootNames = {
+ std::make_pair("QtQml.Models"_L1, "ListModel"_L1),
+ std::make_pair("QtQml.Models"_L1, "Package"_L1),
+ std::make_pair("QtQml"_L1, "Timer"_L1),
+ };
+ std::array<Element, s_unsupportedRootNames.size()> m_unsupportedRootElements;
+ Element m_qtObject;
};
void QdsBindingValidator::onRead(const QQmlSA::Element &element, const QString &propertyName,
@@ -216,25 +229,49 @@ void FunctionCallValidator::onCall(const Element &element, const QString &proper
QdsElementValidator::QdsElementValidator(PassManager *manager) : ElementPass(manager)
{
- for (qsizetype i = 0; i < qsizetype(s_unsupportedElementNames.size()); ++i) {
- if (!manager->hasImportedModule(s_unsupportedElementNames[i].first))
- continue;
- m_unsupportedElements[i] = resolveType(s_unsupportedElementNames[i].first,
- s_unsupportedElementNames[i].second);
- }
+ auto loadTypes = [&manager, this](QSpan<const UnsupportedName> names, QSpan<Element> output) {
+ for (qsizetype i = 0; i < qsizetype(names.size()); ++i) {
+ if (!manager->hasImportedModule(names[i].first))
+ continue;
+ output[i] = resolveType(names[i].first, names[i].second);
+ }
+ };
+ loadTypes(s_unsupportedElementNames, m_unsupportedElements);
+ loadTypes(s_unsupportedRootNames, m_unsupportedRootElements);
+ m_qtObject = resolveType("QtQml"_L1, "QtObject"_L1);
}
void QdsElementValidator::run(const Element &element)
{
- for (const auto &unsupportedElement : m_unsupportedElements) {
- if (!unsupportedElement || !element.inherits(unsupportedElement))
- continue;
-
- emitWarning(u"This type (%1) is not supported in a UI file (.ui.qml)."_s.arg(
- element.baseTypeName()),
- ErrUnsupportedTypeInQmlUi, element.sourceLocation());
- break;
- }
+ enum WarningType { ForElements, ForRootElements };
+ auto warnIfElementIsUnsupported = [this, &element](WarningType warningType) {
+ QSpan<const Element> unsupportedComponents = warningType == ForElements
+ ? QSpan<const Element>(m_unsupportedElements)
+ : QSpan<const Element>(m_unsupportedRootElements);
+ const QStringView message = warningType == ForElements
+ ? u"This type (%1) is not supported in a UI file (.ui.qml)."
+ : u"This type (%1) is not supported as a root element of a UI file (.ui.qml).";
+ const LoggerWarningId &id = warningType == ForElements ? ErrUnsupportedTypeInQmlUi
+ : ErrUnsupportedRootTypeInQmlUi;
+
+ for (const auto &unsupportedElement : unsupportedComponents) {
+ if (!unsupportedElement || !element.inherits(unsupportedElement))
+ continue;
+
+ emitWarning(message.arg(element.baseTypeName()), id, element.sourceLocation());
+ break;
+ }
+
+ // special case: we don't want to warn on types indirectly inheriting from QtObject, for
+ // example Item.
+ if (warningType == ForRootElements && element.baseType() == m_qtObject)
+ emitWarning(message.arg(element.baseTypeName()), id, element.sourceLocation());
+ };
+
+ if (element.isFileRootComponent())
+ warnIfElementIsUnsupported(ForRootElements);
+ warnIfElementIsUnsupported(ForElements);
+
if (QString id = resolveElementToId(element, element); !id.isEmpty()) {
static constexpr std::array unsupportedNames = {
"action"_L1, "alias"_L1, "anchors"_L1, "as"_L1, "baseState"_L1,
diff --git a/tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement.ui.qml b/tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement.ui.qml
new file mode 100644
index 0000000000..4611af3533
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement.ui.qml
@@ -0,0 +1,3 @@
+import QtQuick
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement2.ui.qml b/tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement2.ui.qml
new file mode 100644
index 0000000000..46c1db7a61
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qdsPlugin/UnsupportedRootElement2.ui.qml
@@ -0,0 +1,7 @@
+import QtQuick
+import QtQml.Models
+
+ListModel {
+
+}
+
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index 7ca19a029b..93994a2926 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -2612,6 +2612,22 @@ void TestQmllint::qdsPlugin_data()
QTest::addRow("SupportedElements")
<< u"qdsPlugin/SupportedElements.ui.qml"_s
<< Result::clean();
+
+ QTest::addRow("UnsupportedRootElement")
+ << u"qdsPlugin/UnsupportedRootElement.ui.qml"_s
+ << Result{ {
+ Message{
+ u"This type (QtObject) is not supported as a root element of a UI file (.ui.qml)."_s,
+ 3, 1 },
+ } };
+
+ QTest::addRow("UnsupportedRootElement2")
+ << u"qdsPlugin/UnsupportedRootElement2.ui.qml"_s
+ << Result{ {
+ Message{
+ u"This type (ListModel) is not supported as a root element of a UI file (.ui.qml)."_s,
+ 4, 1 },
+ } };
}
void TestQmllint::qdsPlugin()