diff options
Diffstat (limited to 'tests/auto/qml')
74 files changed, 1704 insertions, 460 deletions
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp index 9e5bc17623..97477370c8 100644 --- a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp +++ b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp @@ -56,7 +56,7 @@ QString QQmlDebugProcess::stateString() const void QQmlDebugProcess::start(const QStringList &arguments) { -#ifdef Q_OS_MAC +#ifdef Q_OS_MACOS // make sure m_executable points to the actual binary even if it's inside an app bundle QFileInfo binFile(m_executable); if (!binFile.isExecutable()) { diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 2e96de7819..cc5eae456d 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -98,7 +98,6 @@ built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js built-ins/Array/prototype/slice/length-exceeding-integer-limit.js fails built-ins/Array/prototype/some/15.4.4.17-3-28.js fails built-ins/Array/prototype/some/15.4.4.17-3-29.js fails -built-ins/Array/prototype/sort/comparefn-nonfunction-call-throws.js fails built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js fails built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js fails built-ins/Array/prototype/splice/create-ctor-non-object.js fails @@ -254,8 +253,6 @@ built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional.js fails built-ins/String/prototype/toLowerCase/Final_Sigma_U180E.js fails built-ins/String/prototype/toLowerCase/special_casing_conditional.js fails built-ins/TypedArray/prototype/constructor.js fails -built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan.js fails -built-ins/TypedArray/prototype/slice/bit-precision.js fails built-ins/TypedArray/prototype/sort/arraylength-internal.js fails built-ins/TypedArray/prototype/sort/comparefn-call-throws.js fails built-ins/TypedArray/prototype/sort/comparefn-calls.js fails diff --git a/tests/auto/qml/ecmascripttests/test262runner.cpp b/tests/auto/qml/ecmascripttests/test262runner.cpp index dc6d660e3d..d87a8a9552 100644 --- a/tests/auto/qml/ecmascripttests/test262runner.cpp +++ b/tests/auto/qml/ecmascripttests/test262runner.cpp @@ -223,8 +223,8 @@ void Test262Runner::createProcesses() }); QObject::connect(&p, &QProcess::finished, this, - [this, processCount, i](int, QProcess::ExitStatus status) { - if (status != QProcess::NormalExit) { + [this, processCount, i](int exitCode, QProcess::ExitStatus status) { + if (status != QProcess::NormalExit || exitCode != 0) { TestData &testData(currentTasks[i]); auto &result = testData.stillNeedStrictRun diff --git a/tests/auto/qml/linebylinelex/BLACKLIST b/tests/auto/qml/linebylinelex/BLACKLIST deleted file mode 100644 index 0fd7f604e3..0000000000 --- a/tests/auto/qml/linebylinelex/BLACKLIST +++ /dev/null @@ -1,5 +0,0 @@ -# QTBUG-105697 -[testFormatter] -android -[testLineByLineLex] -android diff --git a/tests/auto/qml/linebylinelex/CMakeLists.txt b/tests/auto/qml/linebylinelex/CMakeLists.txt index 8b05ca0527..92d956a972 100644 --- a/tests/auto/qml/linebylinelex/CMakeLists.txt +++ b/tests/auto/qml/linebylinelex/CMakeLists.txt @@ -10,12 +10,12 @@ endif() # Collect linebyline test data file(GLOB_RECURSE test_data_glob - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/.. - linebylinelex/data/*) + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + data/*) # Collect qmlformat test data file(GLOB_RECURSE test_data_glob2 - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/.. - qmlformat/data/*) + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + ../qmlformat/data/*) list(APPEND test_data ${test_data_glob} ${test_data_glob2}) qt_internal_add_test(tst_linebylinelex @@ -25,17 +25,5 @@ qt_internal_add_test(tst_linebylinelex Qt::Qml Qt::QuickTestUtilsPrivate TESTDATA ${test_data} -) - -## Scopes: -##################################################################### - -qt_internal_extend_target(tst_linebylinelex CONDITION ANDROID OR IOS - DEFINES - QT_QMLTEST_DATADIR=":/" -) - -qt_internal_extend_target(tst_linebylinelex CONDITION NOT ANDROID AND NOT IOS - DEFINES - QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/.." + BUILTIN_TESTDATA ) diff --git a/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp b/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp index d94f325020..040ccfa9a6 100644 --- a/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp +++ b/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp @@ -13,7 +13,7 @@ QT_USE_NAMESPACE using namespace Qt::StringLiterals; using namespace QQmlJS; -class TestLineByLineLex : public QQmlDataTest +class TestLineByLineLex : public QObject { Q_OBJECT @@ -21,7 +21,7 @@ public: TestLineByLineLex(); private Q_SLOTS: - void initTestCase() override; + void initTestCase(); void testLineByLineLex_data(); void testLineByLineLex(); @@ -34,17 +34,14 @@ private: QString m_qmljsrootgenPath; QString m_qmltyperegistrarPath; - QString m_baseDir; }; TestLineByLineLex::TestLineByLineLex() - : QQmlDataTest(QT_QMLTEST_DATADIR), m_baseDir(QString::fromLocal8Bit(QT_QMLTEST_DATADIR)) { } void TestLineByLineLex::initTestCase() { - QQmlDataTest::initTestCase(); } void TestLineByLineLex::testLineByLineLex_data() @@ -59,22 +56,18 @@ void TestLineByLineLex::testLineByLineLex() { QFETCH(QString, filename); - QString filePath = m_baseDir + u"/linebylinelex/data/"_s + filename; + QString filePath = QFINDTESTDATA("data/" + filename); runLex(filePath); } void TestLineByLineLex::testFormatter_data() { QTest::addColumn<QString>("filename"); - QDir formatData(m_baseDir + u"/qmlformat/data"_s); - bool hasTestData = false; // ### TODO: fix test to always have data + QDir formatData(QFINDTESTDATA("qmlformat/data")); for (const QFileInfo &fInfo : formatData.entryInfoList(QStringList({ u"*.qml"_s, u"*.js"_s }), QDir::Files)) { QTest::newRow(qPrintable(fInfo.fileName())) << fInfo.absoluteFilePath(); - hasTestData = true; } - if (!hasTestData) - QSKIP("No test data found!"); } void TestLineByLineLex::testFormatter() diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index daa16eba72..7bf3b34f86 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -5948,7 +5948,7 @@ void tst_QJSEngine::functionCtorGeneratedCUIsNotCollectedByGc() const QString program = "new Function('a', 'b', 'let x = \"Hello\"; return a + b');"; auto sumFunc = engine.evaluate(program); QVERIFY(sumFunc.isCallable()); - auto *function = QJSValuePrivate::asManagedType<QV4::FunctionObject>(&sumFunc); + auto *function = QJSValuePrivate::asManagedType<QV4::JavaScriptFunctionObject>(&sumFunc); auto *cu = function->d()->function->executableCompilationUnit(); QVERIFY(cu->runtimeStrings); // should exist for "Hello" QVERIFY(cu->runtimeStrings[0]->isMarked()); diff --git a/tests/auto/qml/qmlcachegen/CMakeLists.txt b/tests/auto/qml/qmlcachegen/CMakeLists.txt index 2dacff35b5..d88de460e9 100644 --- a/tests/auto/qml/qmlcachegen/CMakeLists.txt +++ b/tests/auto/qml/qmlcachegen/CMakeLists.txt @@ -28,6 +28,7 @@ qt_internal_add_test(tst_qmlcachegen Qt::Gui Qt::QmlPrivate Qt::QuickTestUtilsPrivate + Qt::QmlCompilerPrivate TESTDATA ${test_data} ) diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml new file mode 100644 index 0000000000..b48004dc87 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml @@ -0,0 +1,11 @@ +import QtQml + +QtObject { + property int i: 100 + property int j: i * 2 + + function s() : string { + let s = "abc" + return s + "def " + } +} diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml new file mode 100644 index 0000000000..3d96760e96 --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml @@ -0,0 +1,7 @@ +import QtQml + +QtObject { + property int i: Math.max(1, 2) // OK + function f() { return 1 } // Error: No specified return type + property string s: g() // Error: g? +} diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc b/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc new file mode 100644 index 0000000000..4f156ad2ef --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/cachegentest"> + <file alias="qmldir">qmldir</file> + </qresource> +</RCC> diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/qmldir b/tests/auto/qml/qmlcachegen/data/aotstats/qmldir new file mode 100644 index 0000000000..72047cc99d --- /dev/null +++ b/tests/auto/qml/qmlcachegen/data/aotstats/qmldir @@ -0,0 +1,3 @@ +module cachegentest +AotstatsClean 254.0 AotstatsClean.qml +AotstatsMixed 254.0 AotstatsMixed.qml diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp index 17a914c1dd..34ad3bbc98 100644 --- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp +++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp @@ -3,6 +3,7 @@ #include <qtest.h> +#include <QJsonDocument> #include <QQmlComponent> #include <QQmlEngine> #include <QProcess> @@ -11,6 +12,7 @@ #include <QSysInfo> #include <QLoggingCategory> #include <private/qqmlcomponent_p.h> +#include <private/qqmljscompilerstats_p.h> #include <private/qqmlscriptdata_p.h> #include <private/qv4compileddata_p.h> #include <qtranslator.h> @@ -67,6 +69,10 @@ private slots: void scriptStringCachegenInteraction(); void saveableUnitPointer(); + + void aotstatsSerialization(); + void aotstatsGeneration_data(); + void aotstatsGeneration(); }; // A wrapper around QQmlComponent to ensure the temporary reference counts @@ -895,6 +901,133 @@ void tst_qmlcachegen::saveableUnitPointer() QCOMPARE(unit.flags, flags); } +void tst_qmlcachegen::aotstatsSerialization() +{ + const auto createEntry = [](const auto &d, const auto &n, const auto &e, const auto &l, + const auto &c, const auto &s) -> QQmlJS::AotStatsEntry { + QQmlJS::AotStatsEntry entry; + entry.codegenDuration = d; + entry.functionName = n; + entry.errorMessage = e; + entry.line = l; + entry.column = c; + entry.codegenSuccessful = s; + return entry; + }; + + const auto equal = [](const auto &e1, const auto &e2) -> bool { + return e1.codegenDuration == e2.codegenDuration && e1.functionName == e2.functionName + && e1.errorMessage == e2.errorMessage && e1.line == e2.line + && e1.column == e2.column && e1.codegenSuccessful == e2.codegenSuccessful; + }; + + // AotStats + // +-ModuleA + // | +-File1 + // | | +-e1 + // | | +-e2 + // | +-File2 + // | | +-e3 + // +-ModuleB + // | +-File3 + // | | +-e4 + + QQmlJS::AotStats original; + QQmlJS::AotStatsEntry e1 = createEntry(std::chrono::microseconds(500), "f1", "", 1, 1, true); + QQmlJS::AotStatsEntry e2 = createEntry(std::chrono::microseconds(200), "f2", "err1", 5, 4, false); + QQmlJS::AotStatsEntry e3 = createEntry(std::chrono::microseconds(750), "f3", "", 20, 4, true); + QQmlJS::AotStatsEntry e4 = createEntry(std::chrono::microseconds(300), "f4", "err2", 5, 8, false); + original.addEntry("ModuleA", "File1", e1); + original.addEntry("ModuleA", "File1", e2); + original.addEntry("ModuleA", "File2", e3); + original.addEntry("ModuleB", "File3", e4); + + const auto parsed = QQmlJS::AotStats::fromJsonDocument(original.toJsonDocument()); + QCOMPARE(parsed.entries().size(), original.entries().size()); + + const auto &parsedA = parsed.entries()["ModuleA"]; + const auto &originalA = original.entries()["ModuleA"]; + QCOMPARE(parsedA.size(), originalA.size()); + QCOMPARE(parsedA["File1"].size(), originalA["File1"].size()); + QVERIFY(equal(parsedA["File1"][0], originalA["File1"][0])); + QVERIFY(equal(parsedA["File1"][1], originalA["File1"][1])); + QCOMPARE(parsedA["File2"].size(), originalA["File2"].size()); + QVERIFY(equal(parsedA["File2"][0], originalA["File2"][0])); + + const auto &parsedB = parsed.entries()["ModuleB"]; + const auto &originalB = original.entries()["ModuleB"]; + QCOMPARE(parsedB.size(), originalB.size()); + QCOMPARE(parsedB["File3"].size(), originalB["File3"].size()); + QVERIFY(equal(parsedB["File3"][0], originalB["File3"][0])); +} + +struct FunctionEntry +{ + QString name; + QString errorMessage; + bool codegenSuccessful; +}; + +void tst_qmlcachegen::aotstatsGeneration_data() +{ + QTest::addColumn<QString>("qmlFile"); + QTest::addColumn<QList<FunctionEntry>>("entries"); + + QTest::addRow("clean") << "AotstatsClean.qml" + << QList<FunctionEntry>{ { "j", "", true }, { "s", "", true } }; + + const QString fError = "function without return type annotation returns int. This may prevent " + "proper compilation to Cpp."; + const QString sError = "method g cannot be resolved."; + QTest::addRow("mixed") << "AotstatsMixed.qml" + << QList<FunctionEntry>{ { "i", "", true }, + { "f", fError, false }, + { "s", sError, false } }; +} + +void tst_qmlcachegen::aotstatsGeneration() +{ +#if defined(QTEST_CROSS_COMPILED) + QSKIP("Cannot call qmlcachegen on cross-compiled target."); +#endif + QFETCH(QString, qmlFile); + QFETCH(QList<FunctionEntry>, entries); + + QTemporaryDir dir; + QProcess proc; + proc.setProgram(QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) + "/qmlcachegen"_L1); + const QString cppOutput = dir.filePath(qmlFile + ".cpp"); + const QString aotstatsOutput = cppOutput + ".aotstats"; + proc.setArguments({ "--bare", + "--resource-path", "/cachegentest/data/aotstats/" + qmlFile, + "-i", testFile("aotstats/qmldir"), + "--resource", testFile("aotstats/cachegentest.qrc"), + "--dump-aot-stats", + "--module-id=Aotstats", + "-o", cppOutput, + testFile("aotstats/" + qmlFile) }); + proc.start(); + QVERIFY(proc.waitForFinished() && proc.exitStatus() == QProcess::NormalExit); + + QVERIFY(QFileInfo::exists(aotstatsOutput)); + QFile aotstatsFile(aotstatsOutput); + QVERIFY(aotstatsFile.open(QIODevice::Text | QIODevice::ReadOnly)); + const auto document = QJsonDocument::fromJson(aotstatsFile.readAll()); + const auto aotstats = QQmlJS::AotStats::fromJsonDocument(document); + QVERIFY(aotstats.entries().size() == 1); // One module + const auto &moduleEntries = aotstats.entries()["Aotstats"]; + QVERIFY(moduleEntries.size() == 1); // Only one qml file was compiled + const auto &fileEntries = moduleEntries[moduleEntries.keys().first()]; + + for (const auto &entry : entries) { + const auto it = std::find_if(fileEntries.cbegin(), fileEntries.cend(), + [&](const auto &e) { return e.functionName == entry.name; }); + QVERIFY(it != fileEntries.cend()); + QVERIFY(it->codegenSuccessful == entry.codegenSuccessful); + QVERIFY(it->errorMessage == entry.errorMessage); + } +} + const QQmlScriptString &ScriptStringProps::undef() const { return m_undef; diff --git a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt index 42ad6d23d6..715ad6162a 100644 --- a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt @@ -19,6 +19,8 @@ qt_internal_add_test(tst_qmlcppcodegen codegen_test_moduleplugin codegen_test_hidden codegen_test_hiddenplugin + codegen_test_stringbuilder + codegen_test_stringbuilderplugin ) qt_internal_add_test(tst_qmlcppcodegen_interpreted @@ -31,6 +33,8 @@ qt_internal_add_test(tst_qmlcppcodegen_interpreted codegen_test_moduleplugin codegen_test_hidden codegen_test_hiddenplugin + codegen_test_stringbuilder + codegen_test_stringbuilderplugin DEFINES QT_TEST_FORCE_INTERPRETER ) diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 8c5449d192..7f2e6ad967 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -346,6 +346,33 @@ add_dependencies(codegen_test_hidden Qt::Quick) qt_autogen_tools_initial_setup(codegen_test_hiddenplugin) +qt_policy(SET QTP0004 NEW) + +qt_add_library(codegen_test_stringbuilder STATIC) +qt_autogen_tools_initial_setup(codegen_test_stringbuilder) + +set_target_properties(codegen_test_stringbuilder PROPERTIES + # We really want qmlcachegen here, even if qmlsc is available + QT_QMLCACHEGEN_EXECUTABLE qmlcachegen + QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks +) + +target_compile_definitions(codegen_test_stringbuilder PRIVATE + -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache" + QT_USE_QSTRINGBUILDER +) + +qt6_add_qml_module(codegen_test_stringbuilder + URI StringBuilderTestTypes + SOURCES + writableVariantMap.h + QML_FILES + writeVariantMap.qml + OUTPUT_DIRECTORY stringbuilderTestTypes + __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE +) + +qt_autogen_tools_initial_setup(codegen_test_stringbuilderplugin) qt_add_library(codegen_test_module STATIC) qt_autogen_tools_initial_setup(codegen_test_module) @@ -356,7 +383,7 @@ set_target_properties(codegen_test_module PROPERTIES QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks ) -qt_policy(SET QTP0004 NEW) + target_compile_definitions(codegen_test_module PUBLIC -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache" diff --git a/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h b/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h new file mode 100644 index 0000000000..3c0fedd28b --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h @@ -0,0 +1,31 @@ +#pragma once +#include <QObject> +#include <QVariantMap> +#include <QtQml/qqmlregistration.h> + +class WritableVariantMap : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(QVariantMap data READ data WRITE setData NOTIFY dataChanged) + +public: + WritableVariantMap(QObject *parent = nullptr) : QObject(parent) { } + + QVariantMap data() const { return m_data; } + void setData(const QVariantMap &data) + { + if (m_data != data) { + m_data = data; + emit dataChanged(); + } + } + +signals: + void dataChanged(); + +private: + QVariantMap m_data; +}; + + diff --git a/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml b/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml new file mode 100644 index 0000000000..536e53b408 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml @@ -0,0 +1,10 @@ +pragma Strict +import StringBuilderTestTypes + +WritableVariantMap { + id: dragSource + property string modelData: "Drag Me" + data: ({ + "text/plain": "%" + dragSource.modelData + "%" + }) +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 9b66143f62..53cc068e8c 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -256,6 +256,7 @@ private slots: void voidConversion(); void voidFunction(); void writeBack(); + void writeVariantMap(); }; static QByteArray arg1() @@ -5107,6 +5108,22 @@ void tst_QmlCppCodegen::writeBack() QCOMPARE(person->property("ints"), QVariant::fromValue(QList<int>({12, 22, 2, 1, 0, 0, 33}))); } +void tst_QmlCppCodegen::writeVariantMap() +{ + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/StringBuilderTestTypes/writeVariantMap.qml"_s)); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + const QVariantMap v = object->property("data").toMap(); + QCOMPARE(v.size(), 1); + const QVariant textPlain = v[u"text/plain"_s]; + QCOMPARE(textPlain.metaType(), QMetaType::fromType<QString>()); + QCOMPARE(textPlain.toString(), u"%Drag Me%"_s); + +} + QTEST_MAIN(tst_QmlCppCodegen) #include "tst_qmlcppcodegen.moc" diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml new file mode 100644 index 0000000000..bbf978936f --- /dev/null +++ b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml @@ -0,0 +1,12 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Rectangle { + enum AxisAlignment { + Bottom = 0, + Left = 1, + Right = 2 + } +} diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.qml b/tests/auto/qml/qmlformat/data/enumWithValues.qml new file mode 100644 index 0000000000..2dbe7fbac5 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/enumWithValues.qml @@ -0,0 +1,12 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick + +Rectangle{ +enum AxisAlignment{ +Bottom = 0, +Left = 1, +Right = 2 +} +} diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index da3ebc69a2..11d4c9d2c7 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -390,7 +390,9 @@ void TestQmlformat::testFormat_data() QTest::newRow("javascriptBlock") << "javascriptBlock.qml" << "javascriptBlock.formatted.qml" << QStringList{} << RunOption::OnCopy; - + QTest::newRow("enumWithValues") + << "enumWithValues.qml" + << "enumWithValues.formatted.qml" << QStringList{} << RunOption::OnCopy; //plainJS QTest::newRow("nestedLambdaWithIfElse") << "lambdaWithIfElseInsideLambda.js" diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json b/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json index 028685f566..8860b629d1 100644 --- a/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json +++ b/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json @@ -10,29 +10,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -40,9 +36,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -50,12 +46,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json b/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json index 77faf99e6c..085d0bf6d4 100644 --- a/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json +++ b/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json @@ -5,24 +5,20 @@ "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -30,9 +26,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -40,12 +36,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json b/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json index cf446c33bd..c0cad1e3a1 100644 --- a/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json +++ b/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json @@ -10,29 +10,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -40,9 +36,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -50,12 +46,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json b/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json index 0a885f058e..3abcd58b1c 100644 --- a/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json @@ -1,23 +1,19 @@ [ { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -25,9 +21,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -35,12 +31,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/Imports.json b/tests/auto/qml/qmlimportscanner/data/Imports.json index 20b9c524c4..ee6903b1da 100644 --- a/tests/auto/qml/qmlimportscanner/data/Imports.json +++ b/tests/auto/qml/qmlimportscanner/data/Imports.json @@ -10,29 +10,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -40,9 +36,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -50,12 +46,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json index f07b7e8494..0e733b551f 100644 --- a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json @@ -1,39 +1,29 @@ [ { "classname": "QtQuick2Plugin", - "name": "QtQuick", "linkTarget": "Qt6::qtquick2plugin", + "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" - }, - { - "name": "Things", - "plugin": "doesNotExistPlugin", - "relativePath": "Things", "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -41,9 +31,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -51,12 +41,14 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" + "type": "module" }, { - "name": "QML", + "name": "Things", + "plugin": "doesNotExistPlugin", + "relativePath": "Things", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json b/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json index 3aa7bc8282..d0d427f595 100644 --- a/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json +++ b/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json @@ -5,29 +5,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -35,9 +31,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -45,12 +41,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/Simple.qml.json b/tests/auto/qml/qmlimportscanner/data/Simple.qml.json index 3aa7bc8282..d0d427f595 100644 --- a/tests/auto/qml/qmlimportscanner/data/Simple.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/Simple.qml.json @@ -5,29 +5,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -35,9 +31,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -45,12 +41,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/Singleton.json b/tests/auto/qml/qmlimportscanner/data/Singleton.json index 90f0ff19ad..1813d01efe 100644 --- a/tests/auto/qml/qmlimportscanner/data/Singleton.json +++ b/tests/auto/qml/qmlimportscanner/data/Singleton.json @@ -10,29 +10,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -40,9 +36,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -50,12 +46,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/Things.json b/tests/auto/qml/qmlimportscanner/data/Things.json index 7782dd7c5f..a6081c89d8 100644 --- a/tests/auto/qml/qmlimportscanner/data/Things.json +++ b/tests/auto/qml/qmlimportscanner/data/Things.json @@ -11,29 +11,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -41,9 +37,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -51,12 +47,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json b/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json index 8fe2da0078..7094d1c8e3 100644 --- a/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json @@ -1,27 +1,19 @@ [ { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", - "name": "QtQml", - "plugin": "qmlmetaplugin", - "pluginIsOptional": true, - "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" - }, - { "classname": "QtQmlPlugin", "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", + "name": "QtQml", "plugin": "qmlplugin", "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "prefer": ":/qt-project.org/imports/QtQml/", + "relativePath": "QtQml", + "type": "module" }, { - "name": "Methods.js", - "type": "javascript" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -29,9 +21,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -39,12 +31,12 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" + "type": "module" }, { - "name": "QML", - "type": "module" + "name": "Methods.js", + "type": "javascript" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/localImport.qml.json b/tests/auto/qml/qmlimportscanner/data/localImport.qml.json index 7782dd7c5f..a6081c89d8 100644 --- a/tests/auto/qml/qmlimportscanner/data/localImport.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/localImport.qml.json @@ -11,29 +11,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -41,9 +37,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -51,12 +47,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json b/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json index 3aa7bc8282..d0d427f595 100644 --- a/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json @@ -5,29 +5,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -35,9 +31,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -45,12 +41,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json b/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json index 7782dd7c5f..a6081c89d8 100644 --- a/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json @@ -11,29 +11,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -41,9 +37,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -51,12 +47,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json b/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json index 0a885f058e..3abcd58b1c 100644 --- a/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json +++ b/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json @@ -1,23 +1,19 @@ [ { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -25,9 +21,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -35,12 +31,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" } ] diff --git a/tests/auto/qml/qmlimportscanner/data/rootPath.json b/tests/auto/qml/qmlimportscanner/data/rootPath.json index b468a8acb1..41ce0f9a45 100644 --- a/tests/auto/qml/qmlimportscanner/data/rootPath.json +++ b/tests/auto/qml/qmlimportscanner/data/rootPath.json @@ -5,29 +5,25 @@ "name": "QtQuick", "plugin": "qtquick2plugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQuick/", "relativePath": "QtQuick", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQuick/" + "type": "module" }, { - "classname": "QtQmlMetaPlugin", - "linkTarget": "Qt6::QmlMeta", + "classname": "QtQmlPlugin", + "linkTarget": "Qt6::qmlplugin", "name": "QtQml", - "plugin": "qmlmetaplugin", + "plugin": "qmlplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/", "relativePath": "QtQml", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/" + "type": "module" }, { - "classname": "QtQmlPlugin", - "linkTarget": "Qt6::qmlplugin", - "name": "QtQml.Base", - "plugin": "qmlplugin", - "pluginIsOptional": true, - "relativePath": "QtQml/Base", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Base/" + "name": "QML", + "prefer": ":/qt-project.org/imports/QML/", + "relativePath": "QML", + "type": "module" }, { "classname": "QtQmlModelsPlugin", @@ -35,9 +31,9 @@ "name": "QtQml.Models", "plugin": "modelsplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/Models/", "relativePath": "QtQml/Models", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/Models/" + "type": "module" }, { "classname": "QtQmlWorkerScriptPlugin", @@ -45,12 +41,8 @@ "name": "QtQml.WorkerScript", "plugin": "workerscriptplugin", "pluginIsOptional": true, + "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/", "relativePath": "QtQml/WorkerScript", - "type": "module", - "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/" - }, - { - "name": "QML", "type": "module" }, { @@ -72,12 +64,12 @@ "type": "module" }, { - "name": "Imports", - "relativePath": "Imports", + "name": "Module", "type": "module" }, { - "name": "Module", + "name": "Imports", + "relativePath": "Imports", "type": "module" } ] diff --git a/tests/auto/qml/qmllint/data/Qtbug111015/qmldir b/tests/auto/qml/qmllint/data/Qtbug111015/qmldir new file mode 100644 index 0000000000..3bf1d48e13 --- /dev/null +++ b/tests/auto/qml/qmllint/data/Qtbug111015/qmldir @@ -0,0 +1,3 @@ +module Qtbug111015 +typeinfo qtbug111015.qmltypes +import QtQml diff --git a/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes b/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes new file mode 100644 index 0000000000..7de521a379 --- /dev/null +++ b/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes @@ -0,0 +1,20 @@ +import QtQuick.tooling 1.2 + +Module { + Component { + file: "typewithjsonobjectlist.h" + name: "TypeWithJsonObjectList" + exports: ["QmlLintTestLib/TypeWithJsonObjectList 1.0"] + accessSemantics: "reference" + prototype: "QObject" + Property { name: "jsonObjectList"; type: "QJsonObject"; isList: true; read: "getJsonObjectList"; index: 0; isReadonly: true } + } + Component { + file: "typewithjsonarray.h" + name: "TypeWithJsonArray" + exports: ["QmlLintTestLib/TypeWithJsonArray 1.0"] + accessSemantics: "reference" + prototype: "QObject" + Property { name: "jsonArray"; type: "QJsonArray"; read: "getJsonArray"; index: 0; isReadonly: true } + } +} diff --git a/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml b/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml new file mode 100644 index 0000000000..89c52e0e52 --- /dev/null +++ b/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml @@ -0,0 +1,8 @@ +import QtQuick +import Qtbug111015 1.0 + +Item { + TypeWithJsonArray { + jsonArray: [] + } +} diff --git a/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml b/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml new file mode 100644 index 0000000000..0a96fa9f92 --- /dev/null +++ b/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml @@ -0,0 +1,8 @@ +import QtQuick +import Qtbug111015 1.0 + +Item { + TypeWithJsonObjectList { + jsonObjectList: [] + } +} diff --git a/tests/auto/qml/qmllint/data/something.qml b/tests/auto/qml/qmllint/data/something.qml new file mode 100644 index 0000000000..38998f606d --- /dev/null +++ b/tests/auto/qml/qmllint/data/something.qml @@ -0,0 +1,2 @@ +import ModuleInImportPath +A {} diff --git a/tests/auto/qml/qmllint/lintplugin.cpp b/tests/auto/qml/qmllint/lintplugin.cpp index 65795c103c..58b174cb6b 100644 --- a/tests/auto/qml/qmllint/lintplugin.cpp +++ b/tests/auto/qml/qmllint/lintplugin.cpp @@ -23,7 +23,7 @@ public: void run(const QQmlSA::Element &element) override { auto property = element.property(u"radius"_s); - if (!property.isValid() || element.property(u"radius"_s).typeName() != u"qreal") { + if (!property.isValid() || element.property(u"radius"_s).typeName() != u"double") { emitWarning(u"Failed to verify radius property", plugin, element.sourceLocation()); return; } diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 57cb7228d8..02b0ea69d2 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -105,6 +105,7 @@ private Q_SLOTS: void valueTypesFromString(); void ignoreSettingsNotCommandLineOptions(); + void backslashedQmldirPath(); void environment_data(); void environment(); @@ -113,6 +114,7 @@ private Q_SLOTS: void testPlugin(); void quickPlugin(); #endif + private: enum DefaultImportOption { NoDefaultImports, UseDefaultImports }; enum ContainOption { StringNotContained, StringContained }; @@ -1026,7 +1028,7 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)", { Message { QStringLiteral("Ready") } } } }; QTest::newRow("nullBinding") << QStringLiteral("nullBinding.qml") << Result{ { Message{ QStringLiteral( - "Cannot assign literal of type null to qreal") } } }; + "Cannot assign literal of type null to double") } } }; QTest::newRow("missingRequiredAlias") << QStringLiteral("missingRequiredAlias.qml") << Result { { Message { @@ -1345,6 +1347,8 @@ void TestQmllint::cleanQmlCode_data() QTest::newRow("locale") << QStringLiteral("locale.qml"); QTest::newRow("constInvokable") << QStringLiteral("useConstInvokable.qml"); QTest::newRow("dontCheckJSTypes") << QStringLiteral("dontCheckJSTypes.qml"); + QTest::newRow("jsonObjectIsRecognized") << QStringLiteral("jsonObjectIsRecognized.qml"); + QTest::newRow("jsonArrayIsRecognized") << QStringLiteral("jsonArrayIsRecognized.qml"); } void TestQmllint::cleanQmlCode() @@ -1799,7 +1803,7 @@ void TestQmllint::settingsFile() .arg(testFile("settings/unusedImportWarning/unused.qml")))); QVERIFY(runQmllint("settings/bare/bare.qml", false, {}, false, false) .contains(QStringLiteral("Failed to find the following builtins: " - "builtins.qmltypes, jsroot.qmltypes"))); + "jsroot.qmltypes, builtins.qmltypes"))); QVERIFY(runQmllint("settings/qmltypes/qmltypes.qml", false, QStringList(), false) .contains(QStringLiteral("not a qmldir file. Assuming qmltypes."))); QVERIFY(runQmllint("settings/qmlimports/qmlimports.qml", true, QStringList(), false).isEmpty()); @@ -1907,7 +1911,7 @@ void TestQmllint::missingBuiltinsNoCrash() checkResult(warnings, Result { { Message { QStringLiteral("Failed to find the following builtins: " - "builtins.qmltypes, jsroot.qmltypes") } } }); + "jsroot.qmltypes, builtins.qmltypes") } } }); } void TestQmllint::absolutePath() @@ -2120,7 +2124,7 @@ void TestQmllint::quickPlugin() Message { u"SplitView attached property only works with Items"_s }, Message { u"ScrollIndicator must be attached to a Flickable"_s }, Message { u"ScrollBar must be attached to a Flickable or ScrollView"_s }, - Message { u"Accessible must be attached to an Item"_s }, + Message { u"Accessible must be attached to an Item or an Action"_s }, Message { u"EnterKey attached property only works with Items"_s }, Message { u"LayoutDirection attached property only works with Items and Windows"_s }, @@ -2252,5 +2256,14 @@ void TestQmllint::ignoreSettingsNotCommandLineOptions() QCOMPARE(output, QString()); } +void TestQmllint::backslashedQmldirPath() +{ + const QString qmldirPath + = testFile(u"ImportPath/ModuleInImportPath/qmldir"_s).replace('/', QDir::separator()); + const QString output = runQmllint( + testFile(u"something.qml"_s), true, QStringList{ u"-i"_s, qmldirPath }); + QVERIFY(output.isEmpty()); +} + QTEST_GUILESS_MAIN(TestQmllint) #include "tst_qmllint.moc" diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp index 31c27c3cd7..cdbd9695fd 100644 --- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp +++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp @@ -153,7 +153,7 @@ void tst_qmltc_qprocess::noBuiltins() QVERIFY(file.rename(original)); }; - for (QString builtin : { u"builtins.qmltypes"_s, u"jsroot.qmltypes"_s }) { + for (QString builtin : { u"jsroot.qmltypes"_s, u"builtins.qmltypes"_s }) { const auto path = QLibraryInfo::path(QLibraryInfo::QmlImportsPath) + u"/"_s + builtin; QScopeGuard scope(std::bind(renameBack, path)); diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index 822caea0d0..282ad3eba0 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -682,7 +682,6 @@ void tst_qmltyperegistrar::constructibleValueType() name: "Constructible" accessSemantics: "value" exports: ["QmlTypeRegistrarTest/constructible 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] Method { name: "Constructible" @@ -701,7 +700,6 @@ void tst_qmltyperegistrar::structuredValueType() name: "Structured" accessSemantics: "value" exports: ["QmlTypeRegistrarTest/structured 1.0"] - isCreatable: true isStructured: true exportMetaObjectRevisions: [256] Property { name: "i"; type: "int"; index: 0; isFinal: true } @@ -735,51 +733,50 @@ void tst_qmltyperegistrar::typedEnum() accessSemantics: "reference" prototype: "QObject" exports: ["QmlTypeRegistrarTest/TypedEnum 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] Enum { name: "UChar" - type: "uchar" + type: "quint8" values: ["V0"] } Enum { name: "Int8_T" - type: "int8_t" + type: "qint8" values: ["V1"] } Enum { name: "UInt8_T" - type: "uint8_t" + type: "quint8" values: ["V2"] } Enum { name: "Int16_T" - type: "int16_t" + type: "short" values: ["V3"] } Enum { name: "UInt16_T" - type: "uint16_t" + type: "ushort" values: ["V4"] } Enum { name: "Int32_T" - type: "int32_t" + type: "int" values: ["V5"] } Enum { name: "UInt32_T" - type: "uint32_t" + type: "uint" values: ["V6"] } Enum { name: "S" - type: "qint16" + type: "short" values: ["A", "B", "C"] } Enum { name: "T" - type: "quint16" + type: "ushort" values: ["D", "E", "F"] } Enum { @@ -805,7 +802,7 @@ void tst_qmltyperegistrar::listSignal() prototype: "QObject" Signal { name: "objectListHappened" - Parameter { type: "QList<QObject*>" } + Parameter { type: "QObjectList" } } })")); } @@ -833,7 +830,6 @@ void tst_qmltyperegistrar::withNamespace() accessSemantics: "reference" prototype: "Testing::Foo" exports: ["QmlTypeRegistrarTest/Bar 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] Property { name: "barProp"; type: "int"; read: "bar"; index: 0; isReadonly: true; isConstant: true } })")); @@ -853,7 +849,6 @@ void tst_qmltyperegistrar::withNamespace() prototype: "Testing::Bar" extension: "Bar" exports: ["QmlTypeRegistrarTest/Baz 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] attachedType: "Testing::Foo" })")); @@ -937,7 +932,6 @@ void tst_qmltyperegistrar::nameExplosion() "QmlTypeRegistrarTest/Name2 1.0", "QmlTypeRegistrarTest/NameExplosion 1.0" ] - isCreatable: true exportMetaObjectRevisions: [256] })")); @@ -962,7 +956,6 @@ void tst_qmltyperegistrar::javaScriptExtension() extension: "SymbolPrototype" extensionIsJavaScript: true exports: ["QmlTypeRegistrarTest/JavaScriptExtension 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] })")); } @@ -978,7 +971,6 @@ void tst_qmltyperegistrar::relatedAddedInVersion() "QmlTypeRegistrarTest/AddedIn1_0 1.0", "QmlTypeRegistrarTest/AddedIn1_0 1.5" ] - isCreatable: true exportMetaObjectRevisions: [256, 261] })")); } @@ -991,12 +983,11 @@ void tst_qmltyperegistrar::longNumberTypes() accessSemantics: "reference" prototype: "QObject" exports: ["QmlTypeRegistrarTest/LongNumberTypes 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] - Property { name: "a"; type: "qint64"; index: 0 } - Property { name: "b"; type: "int64_t"; index: 1 } - Property { name: "c"; type: "quint64"; index: 2 } - Property { name: "d"; type: "uint64_t"; index: 3 } + Property { name: "a"; type: "qlonglong"; index: 0 } + Property { name: "b"; type: "qlonglong"; index: 1 } + Property { name: "c"; type: "qulonglong"; index: 2 } + Property { name: "d"; type: "qulonglong"; index: 3 } })")); } @@ -1017,10 +1008,67 @@ void tst_qmltyperegistrar::constReturnType() accessSemantics: "reference" prototype: "QObject" exports: ["QmlTypeRegistrarTest/ConstInvokable 1.0"] - isCreatable: true exportMetaObjectRevisions: [256] Method { name: "getObject"; type: "QObject"; isPointer: true; isConstant: true } })")); } +void tst_qmltyperegistrar::usingDeclaration() +{ + QVERIFY(qmltypesData.contains(R"(Component { + file: "tst_qmltyperegistrar.h" + name: "WithMyInt" + accessSemantics: "reference" + prototype: "QObject" + exports: ["QmlTypeRegistrarTest/WithMyInt 1.0"] + exportMetaObjectRevisions: [256] + Property { name: "a"; type: "int"; read: "a"; index: 0; isReadonly: true; isConstant: true } + })")); +} + +void tst_qmltyperegistrar::enumsRegistered() +{ + QCOMPARE(QMetaType::fromName("SizeEnums::Unit"), QMetaType::fromType<SizeEnums::Unit>()); + QCOMPARE(QMetaType::fromName("Local::Flag"), QMetaType::fromType<Local::Flag>()); + QCOMPARE(QMetaType::fromName("Local::Flags"), QMetaType::fromType<Local::Flags>()); + QCOMPARE(QMetaType::fromName("ValueTypeWithEnum1::Quality"), + QMetaType::fromType<ValueTypeWithEnum1::Quality>()); + QCOMPARE(QMetaType::fromName("ValueTypeWithEnum2::Quality"), + QMetaType::fromType<ValueTypeWithEnum2::Quality>()); + QCOMPARE(QMetaType::fromName("BaseNamespace::BBB"), QMetaType::fromType<BaseNamespace::BBB>()); + QCOMPARE(QMetaType::fromName("ExtensionValueType::EEE"), + QMetaType::fromType<ExtensionValueType::EEE>()); + QCOMPARE(QMetaType::fromName("TypedEnum::UChar"), QMetaType::fromType<TypedEnum::UChar>()); + QCOMPARE(QMetaType::fromName("TypedEnum::Int8_T"), QMetaType::fromType<TypedEnum::Int8_T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::UInt8_T"), QMetaType::fromType<TypedEnum::UInt8_T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::Int16_T"), QMetaType::fromType<TypedEnum::Int16_T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::UInt16_T"), QMetaType::fromType<TypedEnum::UInt16_T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::Int32_T"), QMetaType::fromType<TypedEnum::Int32_T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::UInt32_T"), QMetaType::fromType<TypedEnum::UInt32_T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::S"), QMetaType::fromType<TypedEnum::S>()); + QCOMPARE(QMetaType::fromName("TypedEnum::T"), QMetaType::fromType<TypedEnum::T>()); + QCOMPARE(QMetaType::fromName("TypedEnum::U"), QMetaType::fromType<TypedEnum::U>()); + QCOMPARE(QMetaType::fromName("TypedEnum::V"), QMetaType::fromType<TypedEnum::V>()); + QCOMPARE(QMetaType::fromName("NetworkManager::NM"), QMetaType::fromType<NetworkManager::NM>()); + QCOMPARE(QMetaType::fromName("NotNamespace::Abc"), QMetaType::fromType<NotNamespace::Abc>()); +} + +void tst_qmltyperegistrar::doNotDuplicateQtNamespace() +{ + QVERIFY(!qmltypesData.contains(R"(file: "qnamespace.h")")); +} + +void tst_qmltyperegistrar::slotsBeforeInvokables() +{ + QVERIFY(qmltypesData.contains(R"(Component { + file: "tst_qmltyperegistrar.h" + name: "SlotsBeforeInvokables" + accessSemantics: "reference" + prototype: "QObject" + Method { name: "bar" } + Method { name: "foo" } + Method { name: "baz" } + })")); +} + QTEST_MAIN(tst_qmltyperegistrar) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index 371fb840d1..1eff2af024 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -17,6 +17,7 @@ #include <QtQml/qqmlcomponent.h> #include <QtCore/qabstractitemmodel.h> +#include <QtCore/qnamespace.h> #include <QtCore/qproperty.h> #include <QtCore/qrect.h> #include <QtCore/qtemporaryfile.h> @@ -792,6 +793,45 @@ public: Q_INVOKABLE const QObject *getObject() { return nullptr; } }; +using myint = int; + +struct IntAlias +{ + Q_GADGET + QML_FOREIGN(myint) + QML_USING(int); +}; + +class WithMyInt : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(myint a READ a CONSTANT) +public: + myint a() const { return 10; } +}; + +class UsesQtNamespace : public QObject +{ + Q_OBJECT + QML_ANONYMOUS + Q_PROPERTY(Qt::Key key READ key CONSTANT) +public: + Qt::Key key() const { return Qt::Key_Escape; } +}; + +class SlotsBeforeInvokables : public QObject +{ + Q_OBJECT + QML_ANONYMOUS +public: + Q_INVOKABLE void foo() {} +public Q_SLOTS: + void bar() {} +public: + Q_INVOKABLE void baz() {} +}; + class tst_qmltyperegistrar : public QObject { Q_OBJECT @@ -865,6 +905,11 @@ private slots: void enumList(); void constReturnType(); + void usingDeclaration(); + void enumsRegistered(); + void doNotDuplicateQtNamespace(); + void slotsBeforeInvokables(); + private: QByteArray qmltypesData; }; diff --git a/tests/auto/qml/qqmlbinding/CMakeLists.txt b/tests/auto/qml/qqmlbinding/CMakeLists.txt index 0419240921..0249bb0f25 100644 --- a/tests/auto/qml/qqmlbinding/CMakeLists.txt +++ b/tests/auto/qml/qqmlbinding/CMakeLists.txt @@ -28,6 +28,7 @@ qt_internal_add_test(tst_qqmlbinding Qt::Gui Qt::GuiPrivate Qt::QmlPrivate + Qt::QmlMetaPrivate Qt::QuickPrivate Qt::QuickTestUtilsPrivate TESTDATA ${test_data} @@ -42,6 +43,7 @@ qt_internal_add_test(tst_qqmlbinding_no_deferred_properties Qt::Gui Qt::GuiPrivate Qt::QmlPrivate + Qt::QmlMetaPrivate Qt::QuickPrivate Qt::QuickTestUtilsPrivate TESTDATA ${test_data} diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp index 494d765798..b13379a103 100644 --- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -1,13 +1,17 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <qtest.h> + +#include "WithBindableProperties.h" + +#include <private/qmlutils_p.h> +#include <private/qqmlbind_p.h> +#include <private/qqmlcomponentattached_p.h> +#include <private/qquickrectangle_p.h> + +#include <QtTest/qtest.h> + #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> -#include <QtQml/private/qqmlbind_p.h> -#include <QtQml/private/qqmlcomponentattached_p.h> -#include <QtQuick/private/qquickrectangle_p.h> -#include <QtQuickTestUtils/private/qmlutils_p.h> -#include "WithBindableProperties.h" class tst_qqmlbinding : public QQmlDataTest { diff --git a/tests/auto/qml/qqmlconnections/CMakeLists.txt b/tests/auto/qml/qqmlconnections/CMakeLists.txt index dd1814fed1..0e6947370d 100644 --- a/tests/auto/qml/qqmlconnections/CMakeLists.txt +++ b/tests/auto/qml/qqmlconnections/CMakeLists.txt @@ -27,6 +27,7 @@ qt_internal_add_test(tst_qqmlconnections Qt::Gui Qt::GuiPrivate Qt::QmlPrivate + Qt::QmlMetaPrivate Qt::QuickPrivate Qt::QuickTestUtilsPrivate TESTDATA ${test_data} diff --git a/tests/auto/qml/qqmlimport/CMakeLists.txt b/tests/auto/qml/qqmlimport/CMakeLists.txt index 803234787b..b8b720f5dc 100644 --- a/tests/auto/qml/qqmlimport/CMakeLists.txt +++ b/tests/auto/qml/qqmlimport/CMakeLists.txt @@ -35,6 +35,7 @@ qt_internal_add_test(tst_qqmlimport SOURCES tst_qqmlimport.cpp LIBRARIES + Qt::CorePrivate Qt::Gui Qt::Qml Qt::QmlPrivate @@ -58,6 +59,13 @@ qt_internal_add_resource(tst_qqmlimport "preferred2" "qmldir" ) +qt_internal_add_resource(tst_qqmlimport "qtconf" + PREFIX + "/" + FILES + "qmlimports.qt.conf" +) + ## Scopes: ##################################################################### diff --git a/tests/auto/qml/qqmlimport/qmlimports.qt.conf b/tests/auto/qml/qqmlimport/qmlimports.qt.conf new file mode 100644 index 0000000000..3a63cc797f --- /dev/null +++ b/tests/auto/qml/qqmlimport/qmlimports.qt.conf @@ -0,0 +1,3 @@ +[Paths] +Prefix = "" +QmlImports = ":/a/path", ":/another/path", ":/even/more/path" diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp index ff1513d0d6..fe14281387 100644 --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp @@ -17,6 +17,7 @@ #include <QtCore/qscopeguard.h> #include <QtCore/qlibraryinfo.h> +#include <QtCore/private/qlibraryinfo_p.h> class TheThing : public QObject { @@ -68,6 +69,7 @@ private slots: void qualifiedScriptImport(); void invalidImportUrl(); void registerTypesFromImplicitImport(); + void containsAllQtConfEntries(); private: QQmlModuleRegistration noimportRegistration; @@ -202,6 +204,22 @@ void tst_QQmlImport::registerTypesFromImplicitImport() QCOMPARE(t->m_width, 640); } +void tst_QQmlImport::containsAllQtConfEntries() +{ + QString qtConfPath(u":/qmlimports.qt.conf"); + QLibraryInfoPrivate::setQtconfManualPath(&qtConfPath); + QLibraryInfoPrivate::reload(); + auto cleanup = qScopeGuard([](){ + QLibraryInfoPrivate::setQtconfManualPath(nullptr); + QLibraryInfoPrivate::reload(); + }); + QQmlEngine engine; + auto importPaths = engine.importPathList(); + QVERIFY(importPaths.contains(u"qrc:/a/path")); + QVERIFY(importPaths.contains(u"qrc:/another/path")); + QVERIFY(importPaths.contains(u"qrc:/even/more/path")); +} + void tst_QQmlImport::testDesignerSupported() { std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>(); diff --git a/tests/auto/qml/qqmllanguage/data/asValueType.qml b/tests/auto/qml/qqmllanguage/data/asValueType.qml index 6a5500e344..b51dc9c6ec 100644 --- a/tests/auto/qml/qqmllanguage/data/asValueType.qml +++ b/tests/auto/qml/qqmllanguage/data/asValueType.qml @@ -10,4 +10,11 @@ QtObject { property var e: ({x: 10, y: 20}) as point property var f: "red" as withString property var g: "green" as string + property rect bb + property var p: bb as size; + property var q: this as size; + property var r: ({}) as size; + property var s: 11 as size; + property var t: Component as size; + property var u: Qt as size; } diff --git a/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml b/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml new file mode 100644 index 0000000000..777ada3848 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml @@ -0,0 +1,35 @@ +pragma ValueTypeBehavior: Assertable +import QtQml as Q +import StaticTest as S + +Q.QtObject { + property var a + property rect b: a as Q.rect + property bool c: a instanceof Q.rect + property bool d: ({x: 10, y: 20}) instanceof Q.point + property var e: ({x: 10, y: 20}) as Q.point + property var f: "red" as S.withString + property var g: "green" as Q.string + + property var h: new S.withString("red") + property var i: { + let p = new Q.point; + p.x = 10 + p.y = 20 + return p + } + + property var j: 4.0 as Q.int + property var k: (4.5 / 1.5) as Q.int + property var l: 5 as Q.double + property var m: "something" as Q.var + property var n: 1 as Q.bool + property var o: Infinity as Q.int + + property var p: b as Q.size; + property var q: this as Q.size; + property var r: ({}) as Q.size; + property var s: 11 as Q.size; + property var t: Q.Component as Q.size; + property var u: Q.Qt as Q.size; +} diff --git a/tests/auto/qml/qqmllanguage/data/invokableCtors.qml b/tests/auto/qml/qqmllanguage/data/invokableCtors.qml new file mode 100644 index 0000000000..35a8d7bf08 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/invokableCtors.qml @@ -0,0 +1,12 @@ +import QtQml as QQ +import Test as VV + +QQ.QtObject { + property QQ.QtObject oo: new QQ.QtObject() + property QQ.QtObject pp: new QQ.QtObject(oo) + property VV.vv v: new VV.vv("green") + + property VV.InvokableSingleton i: new VV.InvokableSingleton(5, oo) + property VV.InvokableExtended k: new VV.InvokableExtended() + property VV.InvokableUncreatable l: new VV.InvokableUncreatable() +} diff --git a/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml b/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml new file mode 100644 index 0000000000..5bd563a288 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml @@ -0,0 +1,191 @@ +import QtQml +import TypeWithQJsonArrayProperty + +TypeWithQJsonArrayProperty { + function jsArray() { return [1, 2, 3] } + + jsonArray: jsArray() + + property list<int> concatenatedJsonArray: jsonArray.concat([4, 5, 6]) + property list<int> concatenatedJsArray: jsArray().concat([4, 5, 6]) + + property bool entriesMatch: { + var iterator = jsonArray.entries(); + for (var [index, element] of jsArray().entries()) { + var v = iterator.next().value; + if (index !== v[0] || element !== v[1]) { + console.log(index, v[0], element, v[1]); + return false; + } + } + + var iterator = jsArray().entries(); + for (var [index, element] of jsonArray.entries()) { + var v = iterator.next().value; + if (index !== v[0] || element !== v[1]) { + console.log(index, v[0], element, v[1]); + return false; + } + } + + return true; + } + + property bool jsonArrayEvery: jsonArray.every(element => element != 0) + property bool jsArrayEvery: jsArray().every(element => element != 0) + + property list<int> jsonArrayFiltered: jsonArray.filter(element => element > 2) + property list<int> jsArrayFiltered: jsArray().filter(element => element > 2) + + property int jsonArrayFind: jsonArray.find(element => element === 2) + property int jsArrayFind: jsArray().find(element => element === 2) + + property int jsonArrayFindIndex: jsonArray.findIndex(element => element === 1) + property int jsArrayFindIndex: jsArray().findIndex(element => element === 1) + + property string jsonArrayForEach + property string jsArrayForEach + + property bool jsonArrayIncludes: jsonArray.includes(3) + property bool jsArrayIncludes: jsArray().includes(3) + + property int jsonArrayIndexOf: jsonArray.indexOf(2) + property int jsArrayIndexOf: jsArray().indexOf(2) + + property string jsonArrayJoin: jsonArray.join() + property string jsArrayJoin: jsArray().join() + + property bool keysMatch: { + var iterator = jsonArray.keys(); + for (var index of jsArray().keys()) { + var v = iterator.next().value; + if (index !== v) { + console.log(index, v); + return false; + } + } + + var iterator = jsArray().keys(); + for (var index of jsonArray.keys()) { + var v = iterator.next().value; + if (index !== v) { + console.log(index, v); + return false; + } + } + + return true; + } + + property int jsonArrayLastIndexOf: jsonArray.lastIndexOf(1) + property int jsArrayLastIndexOf: jsArray().lastIndexOf(1) + + property list<string> jsonArrayMap: jsonArray.map(element => element.toString()) + property list<string> jsArrayMap: jsArray().map(element => element.toString()) + + property int jsonArrayReduce: jsonArray.reduce((acc, element) => acc - element, 40) + property int jsArrayReduce: jsArray().reduce((acc, element) => acc - element, 40) + + property string jsonArrayReduceRight: jsonArray.reduceRight((acc, element) => acc + element.toString(), "") + property string jsArrayReduceRight: jsArray().reduceRight((acc, element) => acc + element.toString(), "") + + property list<int> jsonArraySlice: jsonArray.slice(0, 1) + property list<int> jsArraySlice: jsArray().slice(0, 1) + + property bool jsonArraySome: jsonArray.some(element => element === 1) + property bool jsArraySome: jsArray().some(element => element === 1) + + property string stringifiedLocaleJsonArray: jsonArray.toLocaleString() + property string stringifiedLocaleJsArray: jsArray().toLocaleString() + + property string stringifiedJsonArray: jsonArray.toString() + property string stringifiedJsArray: jsArray().toString() + + property bool valuesMatch: { + var iterator = jsonArray.values(); + for (var obj of jsArray().values()) { + var v = iterator.next().value; + if (obj !== v) { + console.log(obj, v); + return false; + } + } + + var iterator = jsArray().values(); + for (var obj of jsonArray.values()) { + var v = iterator.next().value; + if (obj !== v) { + console.log(obj, v); + return false; + } + } + + return true; + } + + // In-place mutation methods. + // Set by onCompleted if mutating jsonArray and then accessing it + // respects the mutation and the mutation behaves as for an array. + property bool jsonArrayWasCopiedWithin: false + property bool jsonArrayWasFilled: false + property bool jsonArrayWasPopped: false + property bool jsonArrayWasPushed: false + property bool jsonArrayWasReversed: false + property bool jsonArrayWasShifted: false + property bool jsonArrayWasSpliced: false + property bool jsonArrayWasUnshifted: false + property bool jsonArrayWasSorted: false + + Component.onCompleted: { + function equals(lhs, rhs) { + return lhs.toString() === rhs.toString() + } + + jsonArray.forEach(element => jsonArrayForEach += "-" + element + "-"); + jsArray().forEach(element => jsArrayForEach += "-" + element + "-"); + + var array = jsArray() + + jsonArray.copyWithin(1, 0, 1) + array.copyWithin(1, 0, 1) + jsonArrayWasCopiedWithin = equals(jsonArray, array) + + jsonArray.fill(7, 0, 1) + array.fill(7, 0, 1) + jsonArrayWasFilled = equals(jsonArray, array) + + jsonArray.pop() + array.pop() + jsonArrayWasPopped = equals(jsonArray, array) + + jsonArray.push(23) + jsonArray.push(11) + jsonArray.push(54) + jsonArray.push(42) + array.push(23) + array.push(11) + array.push(54) + array.push(42) + jsonArrayWasPushed = equals(jsonArray, array) + + jsonArray.reverse() + array.reverse() + jsonArrayWasReversed = equals(jsonArray, array) + + jsonArray.shift() + array.shift() + jsonArrayWasShifted = equals(jsonArray, array) + + jsonArray.splice(2, 1, [1, 2], 7, [1, 5]) + array.splice(2, 1, [1, 2], 7, [1, 5]) + jsonArrayWasSpliced = equals(jsonArray, array) + + jsonArray.unshift(4, 71) + array.unshift(4, 71) + jsonArrayWasUnshifted = equals(jsonArray, array) + + jsonArray.sort() + array.sort() + jsonArrayWasSorted = equals(jsonArray, array) + } +} diff --git a/tests/auto/qml/qqmllanguage/data/nestedVectors.qml b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml new file mode 100644 index 0000000000..0bcea52133 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml @@ -0,0 +1,27 @@ +import Test +import QtQml + +NestedVectors { + id: self + + property var list1 + + Component.onCompleted: { + list1 = self.getList() + + let list2 = [] + let data1 = [] + data1.push(2) + data1.push(3) + data1.push(4) + + let data2 = [] + data2.push(5) + data2.push(6) + + list2.push(data1) + list2.push(data2) + + self.setList(list2) + } +} diff --git a/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml b/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml new file mode 100644 index 0000000000..32765895a0 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml @@ -0,0 +1,14 @@ +import QtQml + +QtObject { + id: root + + property int changes: 0 + + property list<int> numbers: [1, 2, 3, 4, 5] + onNumbersChanged: ++changes + + property var one: numbers.shift.bind([1,2,3])() + + Component.onCompleted: root.numbers.shift() +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index ffff0a6979..526cca4b5b 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -174,6 +174,14 @@ void registerTypes() qmlRegisterTypesAndRevisions<NonSingleton>("EnumScopeTest", 1); qmlRegisterTypesAndRevisions<EnumProviderSingletonQml>("EnumScopeTest", 1); + qmlRegisterTypesAndRevisions<TypeWithQJsonArrayProperty>("TypeWithQJsonArrayProperty", 1); + qmlRegisterTypesAndRevisions< + InvokableSingleton, + InvokableExtended, + InvokableUncreatable, + InvokableValueType + >("Test", 1); + qmlRegisterTypesAndRevisions<NestedVectors>("Test", 1); } QVariant myCustomVariantTypeConverter(const QString &data) diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index bcf02c1cf9..ce6abf3504 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -6,6 +6,7 @@ #include <QtCore/qobject.h> #include <QtCore/qrect.h> #include <QtCore/qdatetime.h> +#include <QtCore/qjsonarray.h> #include <QtGui/qtransform.h> #include <QtGui/qcolor.h> #include <QtGui/qvector2d.h> @@ -2942,4 +2943,104 @@ public: } }; +class TypeWithQJsonArrayProperty : public QObject { + Q_OBJECT + QML_ELEMENT + + Q_PROPERTY(QJsonArray jsonArray READ jsonArray WRITE setJsonArray NOTIFY jsonArrayChanged) + +public: + TypeWithQJsonArrayProperty(QObject *parent = nullptr) : QObject(parent) {} + + const QJsonArray& jsonArray() { return m_jsonArray; } + void setJsonArray(const QJsonArray& a) { m_jsonArray = a; } + +signals: + void jsonArrayChanged(); + +private: + QJsonArray m_jsonArray; +}; + +class InvokableSingleton : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_SINGLETON +public: + InvokableSingleton() = default; + Q_INVOKABLE InvokableSingleton(int a, QObject *parent) : QObject(parent), m_a(a) {} + + int m_a = 0; +}; + +class InvokableExtension : public QObject +{ + Q_OBJECT +public: + Q_INVOKABLE InvokableExtension(QObject *parent = nullptr) : QObject(parent) {} +}; + +class InvokableExtended : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_EXTENDED(InvokableExtension) + +public: + Q_INVOKABLE InvokableExtended() = default; +}; + +class InvokableUncreatable : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("no") + +public: + Q_INVOKABLE InvokableUncreatable() = default; +}; + +class InvokableValueType +{ + Q_GADGET + QML_VALUE_TYPE(vv) +public: + Q_INVOKABLE InvokableValueType() = default; + Q_INVOKABLE InvokableValueType(const QString &s) : m_s(s) {} + QString m_s; +}; + +class NestedVectors : public QObject +{ + Q_OBJECT + QML_ELEMENT +public: + NestedVectors(QObject *parent = nullptr) : QObject(parent) + { + std::vector<int> data; + data.push_back(1); + data.push_back(2); + data.push_back(3); + m_list.push_back(data); + data.clear(); + data.push_back(4); + data.push_back(5); + m_list.push_back(data); + } + + Q_INVOKABLE std::vector<std::vector<int>> getList() + { + return m_list; + } + + Q_INVOKABLE void setList(std::vector<std::vector<int>> list) + { + m_list = list; + } + +private: + std::vector<std::vector<int>> m_list; +}; + #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 2f382e8d8e..01caa18cce 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -38,7 +38,7 @@ #include <deque> -#if defined(Q_OS_MAC) +#if defined(Q_OS_DARWIN) #include <unistd.h> #endif @@ -48,7 +48,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES) static inline bool isCaseSensitiveFileSystem(const QString &path) { Q_UNUSED(path); -#if defined(Q_OS_MAC) +#if defined(Q_OS_DARWIN) return pathconf(path.toLatin1().constData(), _PC_CASE_SENSITIVE); #elif defined(Q_OS_WIN) return false; @@ -410,7 +410,9 @@ private slots: void objectAndGadgetMethodCallsRejectThisObject(); void objectAndGadgetMethodCallsAcceptThisObject(); + void asValueType(); + void asValueTypeGood(); void longConversion(); @@ -453,6 +455,12 @@ private slots: void enumScopes(); void typedObjectList(); + void invokableCtors(); + + void jsonArrayPropertyBehavesLikeAnArray(); + + void nestedVectors(); + void optimizedSequenceShift(); private: QQmlEngine engine; @@ -5411,24 +5419,30 @@ void tst_qqmllanguage::namespacedPropertyTypes() void tst_qqmllanguage::qmlTypeCanBeResolvedByName_data() { QTest::addColumn<QUrl>("componentUrl"); + QTest::addColumn<QString>("name"); // Built-in C++ types - QTest::newRow("C++ - Anonymous") << testFileUrl("quickTypeByName_anon.qml"); - QTest::newRow("C++ - Named") << testFileUrl("quickTypeByName_named.qml"); + QTest::newRow("C++ - Anonymous") << testFileUrl("quickTypeByName_anon.qml") + << QStringLiteral("QtQuick/Item"); + QTest::newRow("C++ - Named") << testFileUrl("quickTypeByName_named.qml") + << QStringLiteral("QtQuick/Item"); // Composite types with a qmldir - QTest::newRow("QML - Anonymous - qmldir") << testFileUrl("compositeTypeByName_anon_qmldir.qml"); - QTest::newRow("QML - Named - qmldir") << testFileUrl("compositeTypeByName_named_qmldir.qml"); + QTest::newRow("QML - Anonymous - qmldir") << testFileUrl("compositeTypeByName_anon_qmldir.qml") + << QStringLiteral("SimpleType"); + QTest::newRow("QML - Named - qmldir") << testFileUrl("compositeTypeByName_named_qmldir.qml") + << QStringLiteral("SimpleType"); } void tst_qqmllanguage::qmlTypeCanBeResolvedByName() { QFETCH(QUrl, componentUrl); + QFETCH(QString, name); QQmlEngine engine; QQmlComponent component(&engine, componentUrl); VERIFY_ERRORS(0); - QTest::ignoreMessage(QtMsgType::QtWarningMsg, "[object Object]"); // a bit crude, but it will do + QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(name)); QScopedPointer<QObject> o(component.create()); QVERIFY(!o.isNull()); @@ -8059,7 +8073,60 @@ void tst_qqmllanguage::asValueType() QTest::ignoreMessage( QtWarningMsg, + "Could not find any constructor for value type QQmlRectFValueType " + "to call with value undefined"); + + QTest::ignoreMessage( + QtWarningMsg, qPrintable(url.toString() + ":7:5: Unable to assign [undefined] to QRectF"_L1)); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":10: Coercing a value to QML/point using a type " + "assertion. This behavior is deprecated. Add 'pragma " + "ValueTypeBehavior: Assertable' to prevent it."_L1)); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":14: Coercing between incompatible value types mistakenly " + "yields null rather than undefined. Add 'pragma " + "ValueTypeBehavior: Assertable' to prevent this."_L1)); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":15: Coercing from instances of object types to value " + "types mistakenly yields null rather than undefined. Add " + "'pragma ValueTypeBehavior: Assertable' to prevent " + "this."_L1)); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":16: Coercing a value to QML/size using a type " + "assertion. This behavior is deprecated. Add 'pragma " + "ValueTypeBehavior: Assertable' to prevent it."_L1)); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":11: Coercing a value to StaticTest/withString using a " + "type assertion. This behavior is deprecated. Add 'pragma " + "ValueTypeBehavior: Assertable' to prevent it."_L1)); + QTest::ignoreMessage( + QtWarningMsg, + "Could not find any constructor for value type QQmlSizeFValueType to call " + "with value 11"); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":18: Coercing a value to QML/size using a type " + "assertion. This behavior is deprecated. Add 'pragma " + "ValueTypeBehavior: Assertable' to prevent it."_L1)); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":19: Coercing a value to QML/size using a type " + "assertion. This behavior is deprecated. Add 'pragma " + "ValueTypeBehavior: Assertable' to prevent it."_L1)); + QScopedPointer<QObject> o(c.create()); QCOMPARE(o->property("a"), QVariant()); @@ -8082,6 +8149,84 @@ void tst_qqmllanguage::asValueType() const QVariant string = o->property("g"); QCOMPARE(string.metaType(), QMetaType::fromType<QString>()); QCOMPARE(string.toString(), u"green"); + + const QVariant p = o->property("p"); + QCOMPARE(p.metaType(), QMetaType::fromType<std::nullptr_t>()); + + const QVariant q = o->property("q"); + QCOMPARE(q.metaType(), QMetaType::fromType<std::nullptr_t>()); + + const QVariant r = o->property("r"); + QCOMPARE(r.metaType(), QMetaType::fromType<QSizeF>()); + QCOMPARE(r.value<QSizeF>(), QSizeF()); + + const QVariant s = o->property("s"); + QCOMPARE(s.metaType(), QMetaType()); + + const QVariant t = o->property("t"); + QCOMPARE(t.metaType(), QMetaType::fromType<QSizeF>()); + QCOMPARE(t.value<QSizeF>(), QSizeF()); + + const QVariant u = o->property("u"); + QCOMPARE(u.metaType(), QMetaType::fromType<QSizeF>()); + QCOMPARE(u.value<QSizeF>(), QSizeF()); +} + +void tst_qqmllanguage::asValueTypeGood() +{ + QQmlEngine engine; + const QUrl url = testFileUrl("asValueTypeGood.qml"); + QQmlComponent c(&engine, url); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url.toString() + ":7:5: Unable to assign [undefined] to QRectF"_L1)); + QScopedPointer<QObject> o(c.create()); + + QCOMPARE(o->property("a"), QVariant()); + QCOMPARE(o->property("b").value<QRectF>(), QRectF()); + QVERIFY(!o->property("c").toBool()); + + const QRectF rect(1, 2, 3, 4); + o->setProperty("a", QVariant(rect)); + QCOMPARE(o->property("b").value<QRectF>(), rect); + QVERIFY(o->property("c").toBool()); + + QVERIFY(!o->property("d").toBool()); + QVERIFY(!o->property("e").isValid()); + QVERIFY(!o->property("f").isValid()); + + const QVariant string = o->property("g"); + QCOMPARE(string.metaType(), QMetaType::fromType<QString>()); + QCOMPARE(string.toString(), u"green"); + + const ValueTypeWithString withString = o->property("h").value<ValueTypeWithString>(); + QCOMPARE(withString.toString(), u"red"); + + const QPointF point = o->property("i").value<QPointF>(); + QCOMPARE(point.x(), 10.0); + QCOMPARE(point.y(), 20.0); + + const QVariant j = o->property("j"); + QCOMPARE(j.metaType(), QMetaType::fromType<int>()); + QCOMPARE(j.toInt(), 4); + + QVERIFY(!o->property("k").isValid()); + QVERIFY(!o->property("l").isValid()); + + const QVariant m = o->property("m"); + QCOMPARE(m.metaType(), QMetaType::fromType<QString>()); + QCOMPARE(m.toString(), u"something"); + + QVERIFY(!o->property("n").isValid()); + QVERIFY(!o->property("o").isValid()); + QVERIFY(!o->property("p").isValid()); + QVERIFY(!o->property("q").isValid()); + QVERIFY(!o->property("r").isValid()); + QVERIFY(!o->property("s").isValid()); + QVERIFY(!o->property("t").isValid()); + QVERIFY(!o->property("u").isValid()); } void tst_qqmllanguage::typedEnums_data() @@ -8659,6 +8804,128 @@ void tst_qqmllanguage::typedObjectList() QVERIFY(list.at(&list, 0) != nullptr); } +void tst_qqmllanguage::jsonArrayPropertyBehavesLikeAnArray() { + QQmlEngine e; + QQmlComponent c(&e, testFileUrl("jsonArrayProperty.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("concatenatedJsonArray"), o->property("concatenatedJsArray")); + QVERIFY(o->property("entriesMatch").toBool()); + QCOMPARE(o->property("jsonArrayEvery"), o->property("jsArrayEvery")); + QCOMPARE(o->property("jsonArrayFiltered"), o->property("jsArrayFiltered")); + QCOMPARE(o->property("jsonArrayFind"), o->property("jsArrayFind")); + QCOMPARE(o->property("jsonArrayFindIndex"), o->property("jsArrayFindIndex")); + QCOMPARE(o->property("jsonArrayForEach"), o->property("jsArrayForEach")); + QCOMPARE(o->property("jsonArrayIncludes"), o->property("jsArrayIncludes")); + QCOMPARE(o->property("jsonArrayIndexOf"), o->property("jsArrayIndexOf")); + QCOMPARE(o->property("jsonArrayJoin"), o->property("jsArrayJoin")); + QVERIFY(o->property("keysMatch").toBool()); + QCOMPARE(o->property("jsonArrayLastIndexOf"), o->property("jsArrayLastIndexOf")); + QCOMPARE(o->property("jsonArrayMap"), o->property("jsArrayMap")); + QCOMPARE(o->property("jsonArrayReduce"), o->property("jsArrayReduce")); + QCOMPARE(o->property("jsonArrayReduceRight"), o->property("jsArrayReduceRight")); + QCOMPARE(o->property("jsonArraySlice"), o->property("jsArraySlice")); + QCOMPARE(o->property("jsonArraySome"), o->property("jsArraySome")); + QCOMPARE(o->property("stringifiedLocaleJsonArray"), o->property("stringifiedLocaleJsArray")); + QCOMPARE(o->property("stringifiedJsonArray"), o->property("stringifiedJsArray")); + QVERIFY(o->property("valuesMatch").toBool()); + + QVERIFY(o->property("jsonArrayWasCopiedWithin").toBool()); + QVERIFY(o->property("jsonArrayWasFilled").toBool()); + QVERIFY(o->property("jsonArrayWasPopped").toBool()); + QVERIFY(o->property("jsonArrayWasPushed").toBool()); + QVERIFY(o->property("jsonArrayWasReversed").toBool()); + QVERIFY(o->property("jsonArrayWasShifted").toBool()); + QVERIFY(o->property("jsonArrayWasSpliced").toBool()); + QVERIFY(o->property("jsonArrayWasUnshifted").toBool()); + QVERIFY(o->property("jsonArrayWasSorted").toBool()); +} + +void tst_qqmllanguage::invokableCtors() +{ + QQmlEngine e; + + const QUrl url = testFileUrl("invokableCtors.qml"); + + QQmlComponent c(&e, url); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + const QString urlString = url.toString(); + QTest::ignoreMessage(QtWarningMsg, qPrintable( + urlString + ":9: You are calling a Q_INVOKABLE constructor of " + "InvokableSingleton which is a singleton in QML.")); + + // Extended types look like types without any constructors. + // Therefore they aren't even FunctionObjects. + QTest::ignoreMessage(QtWarningMsg, qPrintable( + urlString + ":10: TypeError: Type error")); + + QTest::ignoreMessage(QtWarningMsg, qPrintable( + urlString + ":11: You are calling a Q_INVOKABLE constructor of " + "InvokableUncreatable which is uncreatable in QML.")); + + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QObject *oo = qvariant_cast<QObject *>(o->property("oo")); + QVERIFY(oo); + QObject *pp = qvariant_cast<QObject *>(o->property("pp")); + QVERIFY(pp); + QCOMPARE(pp->parent(), oo); + + InvokableValueType vv = qvariant_cast<InvokableValueType>(o->property("v")); + QCOMPARE(vv.m_s, "green"); + + InvokableSingleton *i = qvariant_cast<InvokableSingleton *>(o->property("i")); + QVERIFY(i); + QCOMPARE(i->m_a, 5); + QCOMPARE(i->parent(), oo); + + QVariant k = o->property("k"); + QCOMPARE(k.metaType(), QMetaType::fromType<InvokableExtended *>()); + QCOMPARE(k.value<InvokableExtended *>(), nullptr); + + InvokableUncreatable *l = qvariant_cast<InvokableUncreatable *>(o->property("l")); + QVERIFY(l); +} + +void tst_qqmllanguage::nestedVectors() +{ + QQmlEngine e; + QQmlComponent c(&e, testFileUrl("nestedVectors.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + NestedVectors *n = qobject_cast<NestedVectors *>(o.data()); + QVERIFY(n); + + const std::vector<std::vector<int>> expected1 { { 1, 2, 3 }, { 4, 5 } }; + const QVariant list1 = n->property("list1"); + QCOMPARE(list1.metaType(), QMetaType::fromType<std::vector<std::vector<int>>>()); + QCOMPARE(list1.value<std::vector<std::vector<int>>>(), expected1); + + const std::vector<std::vector<int>> expected2 { { 2, 3, 4 }, { 5, 6 } }; + QCOMPARE(n->getList(), expected2); +} + +void tst_qqmllanguage::optimizedSequenceShift() +{ + QQmlEngine e; + QQmlComponent c(&e, testFileUrl("optimizedSequenceShift.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("changes").toInt(), 2); + + const QVariant one = o->property("one"); + QCOMPARE(one.metaType(), QMetaType::fromType<int>()); + QCOMPARE(one.toInt(), 1); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp index e57eb1b65a..67e1591b8b 100644 --- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp +++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp @@ -17,7 +17,7 @@ #include <QtQuickShapes/private/qquickshapesglobal_p.h> -#if defined(Q_OS_MAC) +#if defined(Q_OS_DARWIN) // For _PC_CASE_SENSITIVE #include <unistd.h> #endif @@ -242,9 +242,9 @@ void tst_qqmlmoduleplugin::incorrectPluginCase() QString expectedError = QLatin1String("module \"org.qtproject.WrongCase\" plugin \"PluGin\" not found"); -#if defined(Q_OS_MAC) || defined(Q_OS_WIN32) +#if defined(Q_OS_DARWIN) || defined(Q_OS_WIN32) bool caseSensitive = true; -#if defined(Q_OS_MAC) +#if defined(Q_OS_DARWIN) int res = pathconf(QDir::currentPath().toLatin1().constData(), _PC_CASE_SENSITIVE); if (res == -1) QSKIP("Could not establish case sensitivity of file system"); diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp index eb8c6c260f..0a8411ddcf 100644 --- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp +++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp @@ -34,6 +34,10 @@ private slots: void codeLocationsWithContinuationStringLiteral_data(); void noSubstitutionTemplateLiteral(); void templateLiteral(); + void numericSeparator_data(); + void numericSeparator(); + void invalidNumericSeparator_data(); + void invalidNumericSeparator(); void leadingSemicolonInClass(); void templatedReadonlyProperty(); void qmlImportInJS(); @@ -496,6 +500,74 @@ void tst_qqmlparser::templateLiteral() QVERIFY(e); } +void tst_qqmlparser::numericSeparator_data() { + QTest::addColumn<QString>("code"); + QTest::addColumn<double>("expected_value"); + + QTest::newRow("Separator in decimal literal") << "1_000_000_000" << 1000000000.0; + QTest::newRow("Separator in fractional part") << "1000.22_33" << 1000.2233; + QTest::newRow("Separator in exponent part") << "1e1_0_0" << std::pow(10, 100); + QTest::newRow("Separator in positive exponent part") << "1e+1_0_0" << 1e100; + QTest::newRow("Separator in negative exponent part") << "1e-1_0_0" << 1e-100; + QTest::newRow("Separator in binary literal with b prefix") << "0b1010_0001_1000_0101" << static_cast<double>(0b1010000110000101); + QTest::newRow("Separator in binary literal with B prefix") << "0B01_10_01_10" << static_cast<double>(0b01100110); + QTest::newRow("Separator in octal literal with o prefix") << "0o1234_5670" << static_cast<double>(012345670); + QTest::newRow("Separator in octal literal with O prefix") << "0O7777_0000" << static_cast<double>(077770000); + QTest::newRow("Separator in hex literal with x prefix") << "0xA0_B0_C0" << static_cast<double>(0xA0B0C0); + QTest::newRow("Separator in hex literal with X prefix") << "0X1000_AAAA" << static_cast<double>(0x1000AAAA); +} + +void tst_qqmlparser::numericSeparator() { + using namespace QQmlJS; + + QFETCH(QString, code); + QFETCH(double, expected_value); + + QQmlJS::Engine engine; + + QQmlJS::Lexer lexer(&engine); + lexer.setCode(code, 1); + + QQmlJS::Parser parser(&engine); + QVERIFY(parser.parseExpression()); + + AST::ExpressionNode *expression = parser.expression(); + QVERIFY(expression); + + auto *literal = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expression); + QVERIFY(literal); + + QCOMPARE(literal->value, expected_value); + QCOMPARE(literal->firstSourceLocation().begin(), 0u); + QCOMPARE(literal->lastSourceLocation().end(), quint32(code.size())); +} + +void tst_qqmlparser::invalidNumericSeparator_data() { + QTest::addColumn<QString>("code"); + QTest::addColumn<QString>("error"); + + QTest::newRow("Trailing numeric separator") << "1_" << "A trailing numeric separator is not allowed in numeric literals"; + QTest::newRow("Multiple numeric separators") << "1__2" << "There can be at most one numeric separator beetwen digits"; +} + +void tst_qqmlparser::invalidNumericSeparator() { + using namespace QQmlJS; + + QFETCH(QString, code); + QFETCH(QString, error); + + QQmlJS::Engine engine; + + QQmlJS::Lexer lexer(&engine); + lexer.setCode(code, 1); + + QQmlJS::Parser parser(&engine); + QVERIFY(!parser.parseExpression()); + + QVERIFY(lexer.errorCode() != Lexer::NoError); + QCOMPARE(lexer.errorMessage(), error); +} + void tst_qqmlparser::leadingSemicolonInClass() { QQmlJS::Engine engine; diff --git a/tests/auto/qml/qqmlqt/data/qtbug_125495.qml b/tests/auto/qml/qqmlqt/data/qtbug_125495.qml new file mode 100644 index 0000000000..88f9cb259f --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/qtbug_125495.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +Item { + property font fontProperty: Qt.font({ styleName: "Some Style" }); +} diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index 9fea41104d..8139ec48d7 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -85,6 +85,8 @@ private slots: void timeRoundtrip_data(); void timeRoundtrip(); + void fontSetsStyleName(); + private: QQmlEngine engine; }; @@ -1469,6 +1471,18 @@ void tst_qqmlqt::timeRoundtrip() QCOMPARE(tp.m_getTime, tp.m_putTime); } +void tst_qqmlqt::fontSetsStyleName() { + QQmlComponent component(&engine, testFileUrl("qtbug_125495.qml")); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(object != nullptr); + + QFont f; + f.setStyleName("Some Style"); + + QCOMPARE(qvariant_cast<QFont>(object->property("fontProperty")), f); +} + QTEST_MAIN(tst_qqmlqt) #include "tst_qqmlqt.moc" diff --git a/tests/auto/qml/qqmltimer/CMakeLists.txt b/tests/auto/qml/qqmltimer/CMakeLists.txt index f66e054dc6..88d596be85 100644 --- a/tests/auto/qml/qqmltimer/CMakeLists.txt +++ b/tests/auto/qml/qqmltimer/CMakeLists.txt @@ -21,6 +21,7 @@ qt_internal_add_test(tst_qqmltimer Qt::Gui Qt::GuiPrivate Qt::QmlPrivate + Qt::QmlMetaPrivate Qt::QuickPrivate ) diff --git a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp index a6c61abd57..495f7044f6 100644 --- a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp +++ b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp @@ -1,14 +1,18 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <QtTest/QSignalSpy> -#include <qtest.h> -#include <QtQml/qqmlengine.h> -#include <QtQml/qqmlcomponent.h> -#include <QtQml/private/qqmltimer_p.h> -#include <QtQuick/qquickitem.h> -#include <QDebug> -#include <QtCore/QPauseAnimation> + #include <private/qabstractanimation_p.h> +#include <private/qqmltimer_p.h> + +#include <QtQuick/qquickitem.h> + +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlengine.h> + +#include <QtTest/qsignalspy.h> +#include <QtTest/qtest.h> + +#include <QtCore/qpauseanimation.h> void consistentWait(int ms) { diff --git a/tests/auto/qml/qqmlvaluetypes/data/constructors.qml b/tests/auto/qml/qqmlvaluetypes/data/constructors.qml new file mode 100644 index 0000000000..d94d6d8ad4 --- /dev/null +++ b/tests/auto/qml/qqmlvaluetypes/data/constructors.qml @@ -0,0 +1,14 @@ +import QtQuick as Q + +Q.QtObject { + property var point: new Q.point() + property var size: new Q.size() + property var rect: new Q.rect() + property var color: new Q.color() + property var vector2d: new Q.vector2d() + property var vector3d: new Q.vector3d() + property var vector4d: new Q.vector4d() + property var quaternion: new Q.quaternion() + property var matrix4x4: new Q.matrix4x4() + property var font: new Q.font() +} diff --git a/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml b/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml index c28901956d..1827b57ca9 100644 --- a/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml +++ b/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml @@ -1,4 +1,4 @@ -import QtQuick 2.0 +import QtQuick Item { property bool success: false @@ -6,6 +6,7 @@ Item { property variant m1: Qt.matrix4x4(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4) property variant m2: Qt.matrix4x4(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8) property variant m3: Qt.matrix4x4(123,22,6,42,55,54,67,77,777,1,112,22,55,6696,77,777) + property matrix4x4 m4: PlanarTransform.fromAffineMatrix(1, 2, 3, 4, 5, 6) property variant v1: Qt.vector4d(1,2,3,4) property variant v2: Qt.vector3d(1,2,3) property real factor: 2.23 @@ -101,6 +102,7 @@ Item { if (m1.transposed() != Qt.matrix4x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)) success = false; if (m1.fuzzyEquals(m2)) success = false; if (!m1.fuzzyEquals(m2, 10)) success = false; + if (m4 != Qt.matrix4x4(1, 3, 0, 5, 2, 4, 0, 6, 0, 0, 1, 0, 0, 0, 0, 1)) success = false; if (!testTransformation()) success = false; if (!testMatrixMapping()) success = false; } diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp index 2634044238..ea521053ae 100644 --- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp +++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp @@ -78,6 +78,7 @@ private slots: void writeBackOnFunctionCall(); void valueTypeConversions(); void readReferenceOnGetOwnProperty(); + void constructors(); private: QQmlEngine engine; @@ -1832,6 +1833,28 @@ void tst_qqmlvaluetypes::readReferenceOnGetOwnProperty() QVERIFY(o->property("allo").toBool()); } +void tst_qqmlvaluetypes::constructors() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("constructors.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QScopedPointer<QObject> o(c.create()); + QVERIFY(!o.isNull()); + + QCOMPARE(o->property("point"), QVariant(QPointF())); + QCOMPARE(o->property("size"), QVariant(QSizeF())); + QCOMPARE(o->property("rect"), QVariant(QRectF())); + QCOMPARE(o->property("color"), QVariant(QColor())); + QCOMPARE(o->property("vector2d"), QVariant(QVector2D())); + QCOMPARE(o->property("vector3d"), QVariant(QVector3D())); + QCOMPARE(o->property("vector4d"), QVariant(QVector4D())); + QCOMPARE(o->property("quaternion"), QVariant(QQuaternion())); + QCOMPARE(o->property("matrix4x4"), QVariant(QMatrix4x4())); + QCOMPARE(o->property("font"), QVariant(QFont())); + +} + #undef CHECK_TYPE_IS_NOT_VALUETYPE QTEST_MAIN(tst_qqmlvaluetypes) diff --git a/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp b/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp index eebe4a6c05..bb6e59cb17 100644 --- a/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp +++ b/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp @@ -321,14 +321,12 @@ void tst_QQmlXmlListModel::headers() QTRY_COMPARE_WITH_TIMEOUT(qvariant_cast<QQmlXmlListModel::Status>(model->property("status")), QQmlXmlListModel::Error, 10000); - QVariantMap expectedHeaders; - expectedHeaders["Accept"] = "application/xml,*/*"; + QLatin1String expectedAcceptHeader = "application/xml,*/*"_L1; - QCOMPARE(factory.lastSentHeaders.size(), expectedHeaders.size()); - for (auto it = expectedHeaders.cbegin(), end = expectedHeaders.cend(); it != end; ++it) { - QVERIFY(factory.lastSentHeaders.contains(it.key())); - QCOMPARE(factory.lastSentHeaders[it.key()].toString(), it.value().toString()); - } + QCOMPARE(factory.lastSentHeaders.size(), 1); + QVariant acceptHeader = factory.lastSentHeaders["accept"]; + QVERIFY(acceptHeader.isValid()); + QCOMPARE(acceptHeader.toString(), expectedAcceptHeader); } void tst_QQmlXmlListModel::source() diff --git a/tests/auto/qml/qv4estable/tst_qv4estable.cpp b/tests/auto/qml/qv4estable/tst_qv4estable.cpp index 45df62b23e..7d137ae7d2 100644 --- a/tests/auto/qml/qv4estable/tst_qv4estable.cpp +++ b/tests/auto/qml/qv4estable/tst_qv4estable.cpp @@ -18,7 +18,7 @@ void tst_qv4estable::checkRemoveAvoidsHeapBufferOverflow() QV4::ESTable estable; // Fill the ESTable with values so it is at max capacity. - QCOMPARE_EQ(estable.m_capacity, 8); + QCOMPARE_EQ(estable.m_capacity, 8U); for (uint i = 0; i < estable.m_capacity; ++i) { estable.set(QV4::Value::fromUInt32(i), QV4::Value::fromUInt32(i)); } @@ -27,8 +27,8 @@ void tst_qv4estable::checkRemoveAvoidsHeapBufferOverflow() for (uint i = 0; i < estable.m_capacity; ++i) { QVERIFY(estable.m_keys[i].sameValueZero(QV4::Value::fromUInt32(i))); } - QCOMPARE_EQ(estable.m_capacity, 8); - QCOMPARE_EQ(estable.m_size, 8); + QCOMPARE_EQ(estable.m_capacity, 8U); + QCOMPARE_EQ(estable.m_size, 8U); // Remove the first item from the set to verify that asan does not trip. // Relies on the CI platform propagating asan flag to all tests. diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp index 5bcdcd4624..a414199181 100644 --- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp +++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp @@ -13,6 +13,8 @@ #include <private/qv4identifiertable_p.h> #include <private/qv4arraydata_p.h> #include <private/qqmlcomponentattached_p.h> +#include <private/qv4mapobject_p.h> +#include <private/qv4setobject_p.h> #include <QtQuickTestUtils/private/qmlutils_p.h> @@ -37,6 +39,7 @@ private slots: void sharedInternalClassDataMarking(); void gcTriggeredInOnDestroyed(); void weakValuesAssignedAfterThePhaseThatShouldHandleWeakValues(); + void mapAndSetKeepValuesAlive(); }; tst_qv4mm::tst_qv4mm() @@ -502,6 +505,149 @@ void tst_qv4mm::weakValuesAssignedAfterThePhaseThatShouldHandleWeakValues() QVERIFY(ddata->jsWrapper.valueRef()->heapObject()->inUse()); } +void tst_qv4mm::mapAndSetKeepValuesAlive() +{ + { + QJSEngine jsEngine; + QV4::ExecutionEngine &engine = *jsEngine.handle(); + + QV4::Scope scope(&engine); + auto map = jsEngine.evaluate("new Map()"); + QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object + QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map); + + QVERIFY(!engine.memoryManager->gcBlocked); + // no scoped classes, as that would defeat the point of the test + // we block the gc instead so that the allocation can't trigger the gc + engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection; + QV4::Heap::String *key = engine.newString(QString::fromLatin1("key")); + QV4::Heap::String *value = engine.newString(QString::fromLatin1("value")); + QV4::Value values[2] = { QV4::Value::fromHeapObject(key), QV4::Value::fromHeapObject(value) }; + engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked; + QVERIFY(!key->isMarked()); + QVERIFY(!value->isMarked()); + + auto sm = engine.memoryManager->gcStateMachine.get(); + sm->reset(); + while (sm->state != QV4::GCState::HandleQObjectWrappers) { + QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)]; + sm->state = stateInfo.execute(sm, sm->stateData); + } + QV4::MapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2); + QVERIFY(key->isMarked()); + QVERIFY(value->isMarked()); + bool gcComplete = engine.memoryManager->tryForceGCCompletion(); + QVERIFY(gcComplete); + QVERIFY(key->inUse()); + QVERIFY(value->inUse()); + gc(engine); + QCOMPARE(map.property("size").toInt(), 1); + } + { + QJSEngine jsEngine; + QV4::ExecutionEngine &engine = *jsEngine.handle(); + + QV4::Scope scope(&engine); + auto map = jsEngine.evaluate("new WeakMap()"); + QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object + QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map); + + QVERIFY(!engine.memoryManager->gcBlocked); + // no scoped classes, as that would defeat the point of the test + // we block the gc instead so that the allocation can't trigger the gc + engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection; + QV4::Heap::Object *key = engine.newObject(); + QV4::Heap::String *value = engine.newString(QString::fromLatin1("value")); + QV4::Value values[2] = { QV4::Value::fromHeapObject(key), QV4::Value::fromHeapObject(value) }; + engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked; + QVERIFY(!key->isMarked()); + QVERIFY(!value->isMarked()); + + auto sm = engine.memoryManager->gcStateMachine.get(); + sm->reset(); + while (sm->state != QV4::GCState::HandleQObjectWrappers) { + QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)]; + sm->state = stateInfo.execute(sm, sm->stateData); + } + QV4::WeakMapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2); + QVERIFY(!engine.hasException); + QVERIFY(key->isMarked()); + QVERIFY(value->isMarked()); + bool gcComplete = engine.memoryManager->tryForceGCCompletion(); + QVERIFY(gcComplete); + QVERIFY(key->inUse()); + QVERIFY(value->inUse()); + gc(engine); + QCOMPARE(map.property("size").toInt(), 0); + } + { + QJSEngine jsEngine; + QV4::ExecutionEngine &engine = *jsEngine.handle(); + + QV4::Scope scope(&engine); + auto map = jsEngine.evaluate("new Set()"); + QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object + QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map); + + QVERIFY(!engine.memoryManager->gcBlocked); + // no scoped classes, as that would defeat the point of the test + // we block the gc instead so that the allocation can't trigger the gc + engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection; + QV4::Heap::Object *key = engine.newObject(); + QV4::Value values[1] = { QV4::Value::fromHeapObject(key) }; + engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked; + QVERIFY(!key->isMarked()); + + auto sm = engine.memoryManager->gcStateMachine.get(); + sm->reset(); + while (sm->state != QV4::GCState::HandleQObjectWrappers) { + QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)]; + sm->state = stateInfo.execute(sm, sm->stateData); + } + QV4::SetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1); + QVERIFY(!engine.hasException); + QVERIFY(key->isMarked()); + bool gcComplete = engine.memoryManager->tryForceGCCompletion(); + QVERIFY(gcComplete); + QVERIFY(key->inUse()); + gc(engine); + QCOMPARE(map.property("size").toInt(), 1); + } + { + QJSEngine jsEngine; + QV4::ExecutionEngine &engine = *jsEngine.handle(); + + QV4::Scope scope(&engine); + auto map = jsEngine.evaluate("new WeakSet()"); + QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object + QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map); + + QVERIFY(!engine.memoryManager->gcBlocked); + // no scoped classes, as that would defeat the point of the test + // we block the gc instead so that the allocation can't trigger the gc + engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection; + QV4::Heap::Object *key = engine.newObject(); + QV4::Value values[1] = { QV4::Value::fromHeapObject(key) }; + engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked; + QVERIFY(!key->isMarked()); + + auto sm = engine.memoryManager->gcStateMachine.get(); + sm->reset(); + while (sm->state != QV4::GCState::HandleQObjectWrappers) { + QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)]; + sm->state = stateInfo.execute(sm, sm->stateData); + } + QV4::WeakSetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1); + QVERIFY(!engine.hasException); + QVERIFY(key->isMarked()); + bool gcComplete = engine.memoryManager->tryForceGCCompletion(); + QVERIFY(gcComplete); + QVERIFY(key->inUse()); + gc(engine); + QCOMPARE(map.property("size").toInt(), 0); + } +} + QTEST_MAIN(tst_qv4mm) #include "tst_qv4mm.moc" |