qmltc: Test fail for unbound outside required property in component

`qmltc` should fail when it processes a QML file that defines a
component that has unbound inner-level required properties imported from
an outside type.

For example:

```
Item {
    Component {
        id: mycomp

        Item {
            TypeWithRequiredProperty {}
        }
    }
}
```

Where `TypeWithRequiredProperty` defines at least one required property.

To parse a QML file, `qmltc` uses `QQmlJSImportVisitor`, which will
produce an error on encountering such a case.

`qmltc` will in turn propagate the error and fail itself, thus acting
properly.

A new test was added to keep track of the behavior and ensure that
`qmltc` rejects a file when this erroneous form is encountered.

Fixes: QTBUG-120698
Change-Id: I7f4dab3501c792b2b2a3d97b20ad416748a3d4a9
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Luca Di Sera 2024-04-17 14:48:59 +02:00
parent 618b9af677
commit d48b5545a9
4 changed files with 59 additions and 0 deletions

View File

@ -27,6 +27,7 @@ qt6_add_qml_module(tst_qmltc_qprocess
URI QmltcQProcessTests
SOURCES
cpptypes/testtype.h
cpptypes/typewithrequiredproperty.h
DEPENDENCIES
QtQuick/auto
QML_FILES
@ -45,6 +46,7 @@ qt6_add_qml_module(tst_qmltc_qprocess
data/constructFromString.qml
data/unboundRequiredPropertyInInlineComponent.qml
data/componentDefinitionInnerRequiredProperty.qml
data/componentDefinitionInnerRequiredPropertyFromOutside.qml
)
set(common_libraries

View File

@ -0,0 +1,27 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHREQUIREDPROPERTY_H_
#define TYPEWITHREQUIREDPROPERTY_H_
#include <QtCore/qobject.h>
#include <QtCore/qproperty.h>
#include <QtQml/qqmlregistration.h>
class TypeWithRequiredProperty : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString requiredProperty READ requiredProperty WRITE setRequiredProperty REQUIRED)
QProperty<QString> m_requiredProperty;
public:
TypeWithRequiredProperty(QObject *parent = nullptr) : QObject(parent) { }
QString requiredProperty() const { return m_requiredProperty; }
void setRequiredProperty(const QString &s) { m_requiredProperty = s; }
};
#endif // TYPEWITHREQUIREDPROPERTY_H_

View File

@ -0,0 +1,18 @@
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QmltcQProcessTests
Item {
Component {
id: mycomp
Item {
// This introduces an inner required property
// without a binding that cannot be set later and should
// thus block the compilation.
TypeWithRequiredProperty {}
}
}
}

View File

@ -57,6 +57,7 @@ private slots:
void constructFromString();
void unboundRequiredPropertyInInlineComponent();
void componentDefinitionInnerRequiredProperty();
void componentDefinitionInnerRequiredPropertyFromOutside();
};
#ifndef TST_QMLTC_QPROCESS_RESOURCES
@ -362,5 +363,16 @@ void tst_qmltc_qprocess::componentDefinitionInnerRequiredProperty()
}
}
void tst_qmltc_qprocess::componentDefinitionInnerRequiredPropertyFromOutside()
{
{
const auto errors =
runQmltc(u"componentDefinitionInnerRequiredPropertyFromOutside.qml"_s, false);
QVERIFY(errors.contains(
u"componentDefinitionInnerRequiredPropertyFromOutside.qml:15:13: Component is missing required property requiredProperty from TypeWithRequiredProperty [required]"
));
}
}
QTEST_MAIN(tst_qmltc_qprocess)
#include "tst_qmltc_qprocess.moc"