diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2025-04-11 13:02:07 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2025-04-15 19:27:07 +0200 |
commit | afb51a7e91607a6c99c14d0ae8cd46f8d2954fd2 (patch) | |
tree | 206d99310ab677d79dcaaab50dd67db20a2ed60c | |
parent | 373782c1c094c22f0efe03b5d2f726631f9ccf46 (diff) |
qmltc: Cleanly reject custom parsed properties
Process all properties of custom parsed types and generate errors if the
custom parsed properties are actually used. Then print an extra error
stating that qmltc does not support custom parsers.
Pick-to: 6.9 6.8
Fixes: QTBUG-134206
Change-Id: I37e4f3f8d0ee4e0926c0d64c99a4a521b093a1ab
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 17 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmltc_qprocess/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmltc_qprocess/data/customParsed.qml | 7 | ||||
-rw-r--r-- | tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp | 16 | ||||
-rw-r--r-- | tools/qmltc/main.cpp | 8 | ||||
-rw-r--r-- | tools/qmltc/qmltcvisitor.cpp | 7 | ||||
-rw-r--r-- | tools/qmltc/qmltcvisitor.h | 5 |
8 files changed, 57 insertions, 8 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 6ac9a73a61..7af1cff209 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -603,7 +603,7 @@ void QQmlJSImportVisitor::processDefaultProperties() QQmlJSScope::ConstPtr parentScope = it.key(); // We can't expect custom parser default properties to be sensible, discard them for now. - if (parentScope->isInCustomParserParent()) + if (checkCustomParser(parentScope)) continue; /* consider: @@ -1071,7 +1071,7 @@ void QQmlJSImportVisitor::processPropertyBindings() // 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()) + if (checkCustomParser(scope)) continue; // TODO: Can this be in a better suited category? @@ -1273,7 +1273,7 @@ void QQmlJSImportVisitor::addDefaultProperties() m_pendingDefaultProperties[m_currentScope->parentScope()] << m_currentScope; - if (parentScope->isInCustomParserParent()) + if (checkCustomParser(parentScope)) return; /* consider: @@ -1370,7 +1370,7 @@ void QQmlJSImportVisitor::checkGroupedAndAttachedScopes(QQmlJSScope::ConstPtr sc { // 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()) + if (checkCustomParser(scope)) return; auto children = scope->childScopes(); @@ -1396,6 +1396,11 @@ void QQmlJSImportVisitor::checkGroupedAndAttachedScopes(QQmlJSScope::ConstPtr sc } } +bool QQmlJSImportVisitor::checkCustomParser(const QQmlJSScope::ConstPtr &scope) +{ + return scope->isInCustomParserParent(); +} + void QQmlJSImportVisitor::flushPendingSignalParameters() { const QQmlJSMetaSignalHandler handler = m_signalHandlers[m_pendingSignalHandler]; @@ -2390,7 +2395,7 @@ void QQmlJSImportVisitor::endVisit(UiArrayBinding *arrayBinding) const auto propertyName = getScopeName(m_currentScope, QQmlSA::ScopeType::QMLScope); leaveEnvironment(); - if (m_currentScope->isInCustomParserParent()) { + if (checkCustomParser(m_currentScope)) { // These warnings do not apply for custom parsers and their children and need to be handled // on a case by case basis return; @@ -2951,7 +2956,7 @@ void QQmlJSImportVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob) } } - if (m_currentScope->isInCustomParserParent()) { + if (checkCustomParser(m_currentScope)) { // These warnings do not apply for custom parsers and their children and need to be handled // on a case by case basis } else { diff --git a/src/qmlcompiler/qqmljsimportvisitor_p.h b/src/qmlcompiler/qqmljsimportvisitor_p.h index abaca7a691..c56f6a9f99 100644 --- a/src/qmlcompiler/qqmljsimportvisitor_p.h +++ b/src/qmlcompiler/qqmljsimportvisitor_p.h @@ -159,6 +159,8 @@ protected: void throwRecursionDepthError() override; + virtual bool checkCustomParser(const QQmlJSScope::ConstPtr &scope); + QString m_implicitImportDirectory; QStringList m_qmldirFiles; QQmlJSScope::Ptr m_currentScope; @@ -266,7 +268,7 @@ protected: template<typename ErrorHandler> bool checkTypeResolved(const QQmlJSScope::ConstPtr &type, ErrorHandler handle) { - if (type->isFullyResolved() || type->isInCustomParserParent()) + if (type->isFullyResolved() || checkCustomParser(type)) return true; // Note: ignore duplicates, but only after we are certain that the type diff --git a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt index bcde6ac3bb..0145c48657 100644 --- a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt +++ b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt @@ -48,6 +48,7 @@ qt6_add_qml_module(tst_qmltc_qprocess data/componentDefinitionInnerRequiredProperty.qml data/componentDefinitionInnerRequiredPropertyFromOutside.qml data/innerLevelRequiredProperty.qml + data/customParsed.qml NO_GENERATE_EXTRA_QMLDIRS ) diff --git a/tests/auto/qml/qmltc_qprocess/data/customParsed.qml b/tests/auto/qml/qmltc_qprocess/data/customParsed.qml new file mode 100644 index 0000000000..c33aa2f0c8 --- /dev/null +++ b/tests/auto/qml/qmltc_qprocess/data/customParsed.qml @@ -0,0 +1,7 @@ +import QtQuick + +Item { + ListModel { + ListElement { a: 5 } + } +} diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp index 0caff18ebf..13b2caa330 100644 --- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp +++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp @@ -58,6 +58,7 @@ private slots: void componentDefinitionInnerRequiredProperty(); void componentDefinitionInnerRequiredPropertyFromOutside(); void innerLevelRequiredProperty(); + void customParsed(); }; #ifndef TST_QMLTC_QPROCESS_RESOURCES @@ -364,5 +365,20 @@ void tst_qmltc_qprocess::innerLevelRequiredProperty() } } +void tst_qmltc_qprocess::customParsed() +{ + const auto errors = runQmltc(u"customParsed.qml"_s, false); + QVERIFY(errors.contains( + u"customParsed.qml:5:9: Cannot assign to non-existent default property [missing-property]" + )); + QVERIFY(errors.contains( + u"customParsed.qml:5:23: Could not find property \"a\". [missing-property]" + )); + QVERIFY(errors.contains( + u"customParsed.qml:: qmltc does not support custom parsers such as ListModel or old forms " + "of Connections and PropertyChanges. [compiler]" + )); +} + QTEST_MAIN(tst_qmltc_qprocess) #include "tst_qmltc_qprocess.moc" diff --git a/tools/qmltc/main.cpp b/tools/qmltc/main.cpp index 3d412182ea..afc9cf95dc 100644 --- a/tools/qmltc/main.cpp +++ b/tools/qmltc/main.cpp @@ -291,8 +291,14 @@ int main(int argc, char **argv) QString(), QString(), QString()); passMan->analyze(QQmlJSScope::createQQmlSAElement(visitor.result())); - if (logger.hasErrors()) + if (logger.hasErrors()) { + if (visitor.hasSeenCustomParsers()) { + logger.log(QStringLiteral("qmltc does not support custom parsers such as ListModel or " + "old forms of Connections and PropertyChanges."), + qmlCompiler, QQmlJS::SourceLocation()); + } return EXIT_FAILURE; + } QList<QQmlJS::DiagnosticMessage> warnings = importer.takeGlobalWarnings(); if (!warnings.isEmpty()) { diff --git a/tools/qmltc/qmltcvisitor.cpp b/tools/qmltc/qmltcvisitor.cpp index dee3426598..2d1c61bc19 100644 --- a/tools/qmltc/qmltcvisitor.cpp +++ b/tools/qmltc/qmltcvisitor.cpp @@ -337,6 +337,13 @@ void QmltcVisitor::endVisit(QQmlJS::AST::UiProgram *program) checkNamesAndTypes(type); } +bool QmltcVisitor::checkCustomParser(const QQmlJSScope::ConstPtr &scope) +{ + if (QQmlJSImportVisitor::checkCustomParser(scope)) + m_seenCustomParsers = true; + return false; +} + QQmlJSScope::ConstPtr fetchType(const QQmlJSMetaPropertyBinding &binding) { switch (binding.bindingType()) { diff --git a/tools/qmltc/qmltcvisitor.h b/tools/qmltc/qmltcvisitor.h index b96c19063f..42b220ed97 100644 --- a/tools/qmltc/qmltcvisitor.h +++ b/tools/qmltc/qmltcvisitor.h @@ -135,6 +135,9 @@ public: enum Mode { Import, Compile }; void setMode(Mode mode) { m_mode = mode; } + bool checkCustomParser(const QQmlJSScope::ConstPtr &scope) override; + bool hasSeenCustomParsers() const { return m_seenCustomParsers; } + protected: QStringList m_qmlTypeNames; // names of QML types arranged as a stack QHash<QString, int> m_qmlTypeNameCounts; @@ -184,6 +187,8 @@ protected: QHash<QQmlJSScope::ConstPtr, int> m_typesWithId; Mode m_mode = Mode::Import; + + bool m_seenCustomParsers = false; }; QT_END_NAMESPACE |