diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-20 15:04:21 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-02-29 12:08:08 +0100 |
commit | 7da544e862a92cc0a9d97cbed68a35c532699116 (patch) | |
tree | 9abdef4794520fed6d8a142dc15a5adecd222334 /tests/auto | |
parent | d289b67cedb1b910f1f7eb1b3c1f95a7413defdc (diff) |
QmlCompiler: Respect scoped enums
Correctly propagate the isClass and RegisterEnumClassesUnscoped
information from metatypes to qmltypes, then read it correctly, and
don't try to resolve unscoped values of scoped enums when resolving
types. Neither try to resolve the names of unscoped enums.
For historical reasons, enums are unscoped by default, even if they are
declared as "enum class".
Furthermore, QML enums can be accessed in both scoped and unscoped way.
Scoped C++ enums can only be accessed by explicitly stating the scope,
and unscoped C++ enums can only be accessed without scope. Since qmllint
now correctly analyzes this, we need to adapt the tests accordingly.
Finally, also fix the logic around populating the error message for
qmllint. We want to warn about the enum itself, not one of its values.
And we always want to setError() if something is wrong so that the
compilers don't try to continue from there.
Pick-to: 6.7 6.6 6.5 6.2
Fixes: QTBUG-107143
Change-Id: If1ee9a10479cffb46067ccb5e683906905c24160
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/enumproblems.h | 34 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml | 19 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 34 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/Things/plugins.qmltypes | 3 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 4 |
7 files changed, 93 insertions, 4 deletions
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 1149f4373e..69d1217544 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -235,6 +235,7 @@ set(qml_files revisions.qml scopeIdLookup.qml scopeVsObject.qml + scopedEnum.qml script.js script.mjs sequenceToIterable.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h index f640b1fc1c..36f97bec5a 100644 --- a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h +++ b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h @@ -82,4 +82,38 @@ public: Q_FLAG(Option) }; +class ScopedEnum : public QObject { + Q_OBJECT + QML_NAMED_ELEMENT(Data) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + enum class DType { + A = 27, B + }; + Q_ENUM(DType) + + enum EType { + C = 7, D + }; + Q_ENUM(EType) +}; + +class UnscopedEnum : public QObject { + Q_OBJECT + QML_NAMED_ELEMENT(Data2) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "true") + +public: + enum class DType { + A = 26, B + }; + Q_ENUM(DType) + + enum EType { + C = 6, D + }; + Q_ENUM(EType) +}; + #endif // ENUMPROBLEMS_H diff --git a/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml new file mode 100644 index 0000000000..8b9f161b06 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml @@ -0,0 +1,19 @@ +import QtQml +import TestTypes + +QtObject { + property int good: Data.DType.A + property int bad: Data.A + + property int wrong: Data.EType.C + property int right: Data.C + + property int notgood: Data2.DType.A + property int notbad: Data2.A + + property int notwrong: Data2.EType.C + property int notright: Data2.C + + property int passable: Enums.AppState.Blue + property int wild: Enums.Green +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 9363172a0e..da8652acf5 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -203,6 +203,7 @@ private slots: void scopeIdLookup(); void scopeObjectDestruction(); void scopeVsObject(); + void scopedEnum(); void sequenceToIterable(); void setLookupConversion(); void setLookupOriginalScope(); @@ -4125,6 +4126,39 @@ void tst_QmlCppCodegen::scopeVsObject() QCOMPARE(object->property("objectName").toString(), u"foobar"_s); } +void tst_QmlCppCodegen::scopedEnum() +{ + QQmlEngine engine; + const QString url = u"qrc:/qt/qml/TestTypes/scopedEnum.qml"_s; + QQmlComponent component(&engine, QUrl(url)); + QVERIFY2(!component.isError(), component.errorString().toUtf8()); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url + u":6:5: Unable to assign [undefined] to int"_s)); + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url + u":8: TypeError: Cannot read property 'C' of undefined"_s)); + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url + u":14: TypeError: Cannot read property 'C' of undefined"_s)); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QCOMPARE(object->property("good").toInt(), 27); + QCOMPARE(object->property("bad").toInt(), 0); + QCOMPARE(object->property("wrong").toInt(), 0); + QCOMPARE(object->property("right").toInt(), 7); + + QCOMPARE(object->property("notgood").toInt(), 26); + QCOMPARE(object->property("notbad").toInt(), 26); + QCOMPARE(object->property("notwrong").toInt(), 0); + QCOMPARE(object->property("notright").toInt(), 6); + + QCOMPARE(object->property("passable").toInt(), 2); + QCOMPARE(object->property("wild").toInt(), 1); +} + void tst_QmlCppCodegen::sequenceToIterable() { QQmlEngine engine; diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes index 45a6af32ab..453e81d57a 100644 --- a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes +++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes @@ -12,6 +12,7 @@ Module { exports: ["Things/SomethingEntirelyStrange 1.0"] Enum { name: "AnEnum" + isScoped: true values: { "AAA": 0, "BBB": 1, @@ -20,7 +21,7 @@ Module { } Enum { name: "TheEnum" - scoped: false + isScoped: false values: { "V1": 0, "V2": 1 diff --git a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml index 4847fc9196..ad88f1c58c 100644 --- a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml +++ b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml @@ -2,5 +2,5 @@ import Things 1.0 Something { property var a: SomethingEntirelyStrange {} - property var b: SomethingEntirelyStrange.AAA + property var b: SomethingEntirelyStrange.AnEnum.AAA } diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 753a4d3af9..9929d0c850 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -1060,8 +1060,8 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)", QTest::newRow("NotScopedEnumCpp") << QStringLiteral("NotScopedEnumCpp.qml") << Result{ { Message{ - QStringLiteral("You cannot access unscoped enum \"V1\" from here."), 5, - 57 } } }; + QStringLiteral("You cannot access unscoped enum \"TheEnum\" from here."), 5, + 49 } } }; QTest::newRow("unresolvedArrayBinding") << QStringLiteral("unresolvedArrayBinding.qml") |