diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 83383eb75c..0f5c308819 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -861,8 +861,12 @@ void QQmlJSImportVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob) const QString propertyName = group->name.toString(); QQmlJSMetaProperty property = m_currentScope->property(propertyName); - if (property.isValid() && !property.type().isNull() - && (uiob->hasOnToken || property.type()->canAssign(childScope))) { + + if (m_currentScope->isInCustomParserParent()) { + // These warnings do not apply for custom parsers and their children and need to be handled + // on a case by case basis + } else if (property.isValid() && !property.type().isNull() + && (uiob->hasOnToken || property.type()->canAssign(childScope))) { QQmlJSMetaPropertyBinding binding = m_currentScope->hasOwnPropertyBinding(propertyName) ? m_currentScope->ownPropertyBinding(propertyName) diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp index 6386659322..7d5e26bad9 100644 --- a/src/qmlcompiler/qqmljsscope.cpp +++ b/src/qmlcompiler/qqmljsscope.cpp @@ -493,4 +493,14 @@ bool QQmlJSScope::canAssign(const QQmlJSScope::ConstPtr &derived) const return internalName() == u"QVariant"_qs || internalName() == u"QJSValue"_qs; } +bool QQmlJSScope::isInCustomParserParent() const +{ + for (const auto *scope = this; scope; scope = scope->parentScope().get()) { + if (!scope->baseType().isNull() && scope->baseType()->hasCustomParser()) + return true; + } + + return false; +} + QT_END_NAMESPACE diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h index e03c2c1342..e3463c5192 100644 --- a/src/qmlcompiler/qqmljsscope_p.h +++ b/src/qmlcompiler/qqmljsscope_p.h @@ -355,6 +355,12 @@ public: */ bool canAssign(const QQmlJSScope::ConstPtr &derived) const; + /*! + \internal + Checks whether this type or its parents have a custom parser. + */ + bool isInCustomParserParent() const; + private: QQmlJSScope(ScopeType type, const QQmlJSScope::Ptr &parentScope = QQmlJSScope::Ptr()); diff --git a/tests/auto/qml/qmllint/data/customParser.recursive.qml b/tests/auto/qml/qmllint/data/customParser.recursive.qml new file mode 100644 index 0000000000..aa15460021 --- /dev/null +++ b/tests/auto/qml/qmllint/data/customParser.recursive.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +ListModel { + id: listModel + ListElement { dataType: "rect"; color: "green"; font.color: "red"; ListElement {} Behavior on FooBar {} } + ListElement { dataType: "image"; source: "../shared/images/qt-logo.png" } + ListElement { dataType: "rect"; color: "green" } + ListElement { dataType: "image"; source: "../shared/images/qt-logo.png" } + ListElement { dataType: "rect"; color: "blue" } + ListElement { dataType: "rect"; color: "blue" } + ListElement { dataType: "rect"; color: "blue" } + ListElement { dataType: "rect"; color: "blue" } + ListElement { dataType: "rect"; color: "blue" } + ListElement { dataType: "rect"; color: "blue" } +} + diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index f73b319042..89e535ac2e 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -738,6 +738,7 @@ void TestQmllint::cleanQmlCode_data() QTest::newRow("propertyOverride") << QStringLiteral("propertyOverride.qml"); QTest::newRow("propertyBindingValue") << QStringLiteral("propertyBindingValue.qml"); QTest::newRow("customParser") << QStringLiteral("customParser.qml"); + QTest::newRow("customParser.recursive") << QStringLiteral("customParser.recursive.qml"); QTest::newRow("2Behavior") << QStringLiteral("2behavior.qml"); QTest::newRow("interceptor") << QStringLiteral("interceptor.qml"); QTest::newRow("valueSource") << QStringLiteral("valueSource.qml"); diff --git a/tools/qmllint/findwarnings.cpp b/tools/qmllint/findwarnings.cpp index 3d0cedc393..4041cac8df 100644 --- a/tools/qmllint/findwarnings.cpp +++ b/tools/qmllint/findwarnings.cpp @@ -99,6 +99,11 @@ void FindWarningVisitor::checkInheritanceCycle(QQmlJSScope::ConstPtr scope) void FindWarningVisitor::checkGroupedAndAttachedScopes(QQmlJSScope::ConstPtr scope) { + // These warnings do not apply for custom parsers and their children and need to be handled on a + // case by case basis + if (scope->isInCustomParserParent()) + return; + auto children = scope->childScopes(); while (!children.isEmpty()) { auto childScope = children.takeFirst(); @@ -142,6 +147,11 @@ void FindWarningVisitor::checkDefaultProperty(const QQmlJSScope::ConstPtr &scope if (scope == m_exportedRootScope || scope->isArrayScope()) // inapplicable return; + // These warnings do not apply for custom parsers and their children and need to be handled on a + // case by case basis + if (scope->isInCustomParserParent()) + return; + const QQmlJSScope *scopeOfDefaultProperty = nullptr; QString defaultPropertyName; // NB: start looking for default property in parent scope (because this @@ -288,9 +298,10 @@ bool FindWarningVisitor::visit(QQmlJS::AST::UiScriptBinding *uisb) } if (!qmlScope->hasProperty(name.toString())) { - // These warnings do not apply for custom parsers and need to be handled on a case by - // case basis - if (qmlScope->baseType()->hasCustomParser()) + // These warnings do not apply for custom parsers and their children and need to be + // handled on a case by case basis + + if (qmlScope->isInCustomParserParent()) return true; // TODO: Can this be in a better suited category?