diff options
-rw-r--r-- | src/plugins/qmllint/quick/qquickliteralbindingcheck.cpp | 16 | ||||
-rw-r--r-- | src/plugins/qmllint/quick/qquickliteralbindingcheck_p.h | 8 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsliteralbindingcheck.cpp | 59 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsliteralbindingcheck_p.h | 6 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 11 |
5 files changed, 54 insertions, 46 deletions
diff --git a/src/plugins/qmllint/quick/qquickliteralbindingcheck.cpp b/src/plugins/qmllint/quick/qquickliteralbindingcheck.cpp index a39ea6d2c9..47db2e33ca 100644 --- a/src/plugins/qmllint/quick/qquickliteralbindingcheck.cpp +++ b/src/plugins/qmllint/quick/qquickliteralbindingcheck.cpp @@ -14,4 +14,20 @@ QQmlJSStructuredTypeError QQuickLiteralBindingCheck::check(const QString &typeNa return QQuickValueTypeFromStringCheck::check(typeName, value); } +void QQuickLiteralBindingCheck::onBinding( + const QQmlSA::Element &element, const QString &propertyName, const QQmlSA::Binding &binding, + const QQmlSA::Element &bindingScope, const QQmlSA::Element &value) +{ + Q_UNUSED(value); + Q_UNUSED(element); + + const auto property = getProperty(propertyName, binding, bindingScope); + if (!property.isValid()) + return; + + if (const auto propertyType = property.type()) + warnOnCheckedBinding(binding, propertyType); +} + + QT_END_NAMESPACE diff --git a/src/plugins/qmllint/quick/qquickliteralbindingcheck_p.h b/src/plugins/qmllint/quick/qquickliteralbindingcheck_p.h index 058b5f7f5c..31e735b6b8 100644 --- a/src/plugins/qmllint/quick/qquickliteralbindingcheck_p.h +++ b/src/plugins/qmllint/quick/qquickliteralbindingcheck_p.h @@ -29,8 +29,12 @@ class QQuickLiteralBindingCheck: public LiteralBindingCheckBase public: using LiteralBindingCheckBase::LiteralBindingCheckBase; - virtual QQmlJSStructuredTypeError check(const QString &typeName, - const QString &value) const override; + void onBinding( + const QQmlSA::Element &element, const QString &propertyName, + const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope, + const QQmlSA::Element &value) override; + + QQmlJSStructuredTypeError check(const QString &typeName, const QString &value) const override; }; QT_END_NAMESPACE diff --git a/src/qmlcompiler/qqmljsliteralbindingcheck.cpp b/src/qmlcompiler/qqmljsliteralbindingcheck.cpp index c2498afbed..f136bf38da 100644 --- a/src/qmlcompiler/qqmljsliteralbindingcheck.cpp +++ b/src/qmlcompiler/qqmljsliteralbindingcheck.cpp @@ -93,44 +93,26 @@ QQmlSA::Property LiteralBindingCheckBase::getProperty(const QString &propertyNam return bindingScope.property(unqualifiedPropertyName); } - -void LiteralBindingCheckBase::onBinding(const QQmlSA::Element &element, const QString &propertyName, - const QQmlSA::Binding &binding, - const QQmlSA::Element &bindingScope, - const QQmlSA::Element &value) +void LiteralBindingCheckBase::warnOnCheckedBinding( + const QQmlSA::Binding &binding, const QQmlSA::Element &propertyType) { - Q_UNUSED(value); - - const auto property = getProperty(propertyName, binding, bindingScope); - if (!property.isValid()) + auto construction = check(propertyType.internalId(), binding.stringValue()); + if (!construction.isValid()) return; - // If the property is defined in the same scope where it is set, - // we are in fact allowed to set it, even if it's not writable. - if (property.isReadonly() && !element.hasOwnProperty(propertyName)) { - emitWarning(u"Cannot assign to read-only property %1"_s.arg(propertyName), - qmlReadOnlyProperty, binding.sourceLocation()); + const QString warningMessage = + u"Construction from string is deprecated. Use structured value type " + u"construction instead for type \"%1\""_s.arg(propertyType.internalId()); + + if (construction.code.isEmpty()) { + emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation()); return; } - if (auto propertyType = property.type(); propertyType) { - auto construction = check(propertyType.internalId(), binding.stringValue()); - if (construction.isValid()) { - const QString warningMessage = - u"Construction from string is deprecated. Use structured value type " - u"construction instead for type \"%1\""_s.arg(propertyType.internalId()); - - if (!construction.code.isNull()) { - QQmlSA::FixSuggestion suggestion( - u"Replace string by structured value construction"_s, - binding.sourceLocation(), construction.code); - emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation(), suggestion); - return; - } - emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation()); - return; - } - } + const QQmlSA::FixSuggestion suggestion( + u"Replace string by structured value construction"_s, + binding.sourceLocation(), construction.code); + emitWarning(warningMessage, qmlIncompatibleType, binding.sourceLocation(), suggestion); } void QQmlJSLiteralBindingCheck::onBinding(const QQmlSA::Element &element, @@ -139,12 +121,23 @@ void QQmlJSLiteralBindingCheck::onBinding(const QQmlSA::Element &element, const QQmlSA::Element &bindingScope, const QQmlSA::Element &value) { - LiteralBindingCheckBase::onBinding(element, propertyName, binding, bindingScope, value); + Q_UNUSED(value); const auto property = getProperty(propertyName, binding, bindingScope); if (!property.isValid()) return; + // If the property is defined in the same scope where it is set, + // we are in fact allowed to set it, even if it's not writable. + if (property.isReadonly() && !element.hasOwnProperty(propertyName)) { + emitWarning(u"Cannot assign to read-only property %1"_s.arg(propertyName), + qmlReadOnlyProperty, binding.sourceLocation()); + return; + } + + if (const auto propertyType = property.type()) + warnOnCheckedBinding(binding, propertyType); + if (!canConvertForLiteralBinding(m_resolver, resolveLiteralType(binding), property.type())) { emitWarning(u"Cannot assign literal of type %1 to %2"_s.arg( literalPrettyTypeName(binding.bindingType()), diff --git a/src/qmlcompiler/qqmljsliteralbindingcheck_p.h b/src/qmlcompiler/qqmljsliteralbindingcheck_p.h index ca5c65e9b4..d4fac3f52a 100644 --- a/src/qmlcompiler/qqmljsliteralbindingcheck_p.h +++ b/src/qmlcompiler/qqmljsliteralbindingcheck_p.h @@ -30,15 +30,13 @@ class Q_QMLCOMPILER_EXPORT LiteralBindingCheckBase : public QQmlSA::PropertyPass public: using QQmlSA::PropertyPass::PropertyPass; - void onBinding(const QQmlSA::Element &element, const QString &propertyName, - const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope, - const QQmlSA::Element &value) override; - protected: virtual QQmlJSStructuredTypeError check(const QString &typeName, const QString &value) const = 0; QQmlSA::Property getProperty(const QString &propertyName, const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope) const; + + void warnOnCheckedBinding(const QQmlSA::Binding &binding, const QQmlSA::Element &propertyType); }; class Q_QMLCOMPILER_EXPORT QQmlJSLiteralBindingCheck: public LiteralBindingCheckBase diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index d90fb2c6b7..b871bcf7f7 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -36,8 +36,7 @@ public: ExitsNormally = 0x1, NoMessages = 0x2, AutoFixable = 0x4, - HasDuplicates = 0x8, - UseSettings = 0x10 + UseSettings = 0x8 }; Q_DECLARE_FLAGS(Flags, Flag) @@ -971,8 +970,7 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)", << Result{ { Message{ QStringLiteral("Cannot assign to read-only property activeFocus") } }, {}, - {}, - Result::HasDuplicates + {} }; QTest::newRow("AssignToReadOnlyProperty") << QStringLiteral("assignToReadOnlyProperty2.qml") @@ -1879,10 +1877,9 @@ void TestQmllint::checkResult(const QJsonArray &warnings, const Result &result, const auto firstDuplicate = std::adjacent_find(sortedWarnings.constBegin(), sortedWarnings.constEnd()); for (auto it = firstDuplicate; it != sortedWarnings.constEnd(); - it = std::adjacent_find(it + 1, sortedWarnings.constEnd())) + it = std::adjacent_find(it + 1, sortedWarnings.constEnd())) { qDebug() << "Found duplicate warning: " << it->toString(); - if (result.flags.testFlag(Result::HasDuplicates)) - QEXPECT_FAIL("", "TODO: remove duplicate warnings", Continue); + } QVERIFY2(firstDuplicate == sortedWarnings.constEnd(), "Found duplicate warnings!"); } |