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>
This commit is contained in:
parent
373782c1c0
commit
afb51a7e91
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import QtQuick
|
||||
|
||||
Item {
|
||||
ListModel {
|
||||
ListElement { a: 5 }
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue