aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSami Shalayel <sami.shalayel@qt.io>2022-12-21 16:31:20 +0100
committerSami Shalayel <sami.shalayel@qt.io>2023-01-06 18:28:31 +0100
commit3df8eba0f5e9f9b0142914d53c1183c5a05030e7 (patch)
treec7b9be965fa265823904155c66afb372285db6e3
parent4e1fe071ff05b92ed12fdf59a2185e1254b411cf (diff)
qmltc: generate code into namespaces
Generate code into namespaces to avoid clashes between qmltc-generated and user code. Code generated by qmltc will by default be put in the URI_OF_MODULE namespace, and will generate subnamespaces to follow the module hierarchy if URI_OF_MODULE contains dots('.'). Also fix the test to use the new namespaces. [ChangeLog][Qml][qmltc] The type compiler will generate C++-code into a namespace by default. The new default namespace is inferred from the module's URI, where dots are interpreted as separating subnamespaces from each other, e.g., a type in module MyCompany.MyModule.Sub will be generated in the namespace MyCompany::MyModule::Sub. Fixes: QTBUG-109274 Change-Id: I3bfe2697b81e90bb63a079dc44c2810fc9925f97 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--src/qml/Qt6QmlMacros.cmake7
-rw-r--r--src/qml/doc/snippets/qmltc/tst_qmltc_examples.cpp2
-rw-r--r--src/qml/doc/src/cmake/qt_add_qml_module.qdoc11
-rw-r--r--tests/auto/qml/qmltc/CMakeLists.txt2
-rw-r--r--tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt41
-rw-r--r--tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp59
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h1
-rw-r--r--tools/qmltc/qmltccodewriter.cpp24
10 files changed, 118 insertions, 35 deletions
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index 2f7659c2a0..c0df7a92f0 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -664,10 +664,15 @@ function(qt6_add_qml_module target)
endif()
if (arg_ENABLE_TYPE_COMPILER)
+ if (DEFINED arg_TYPE_COMPILER_NAMESPACE AND NOT $<STREQUAL:"${arg_TYPE_COMPILER_NAMESPACE}","">)
+ set(qmltc_namespace ${arg_TYPE_COMPILER_NAMESPACE})
+ else()
+ string(REPLACE "." "::" qmltc_namespace "${arg_URI}")
+ endif()
_qt_internal_target_enable_qmltc(${target}
QML_FILES ${arg_QML_FILES}
IMPORT_PATHS ${arg_IMPORT_PATH}
- NAMESPACE ${arg_TYPE_COMPILER_NAMESPACE}
+ NAMESPACE ${qmltc_namespace}
)
endif()
diff --git a/src/qml/doc/snippets/qmltc/tst_qmltc_examples.cpp b/src/qml/doc/snippets/qmltc/tst_qmltc_examples.cpp
index a78da416e2..7bda70f985 100644
--- a/src/qml/doc/snippets/qmltc/tst_qmltc_examples.cpp
+++ b/src/qml/doc/snippets/qmltc/tst_qmltc_examples.cpp
@@ -53,7 +53,7 @@ void tst_qmltc_examples::app()
QQmlEngine e;
QQuickWindow window;
- QScopedPointer<myApp> documentRoot(new myApp(&e));
+ QScopedPointer<QmltcExample::myApp> documentRoot(new QmltcExample::myApp(&e));
documentRoot->setParentItem(window.contentItem());
window.setHeight(documentRoot->height());
diff --git a/src/qml/doc/src/cmake/qt_add_qml_module.qdoc b/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
index 9bef299970..7617d19033 100644
--- a/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
+++ b/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
@@ -655,4 +655,15 @@ with \l{QML Type Compiler}{qmltc}. Files with the source property
C++ code resides. By default, no namespace is specified for user projects. The
code generated from Qt's own sources is put under a QT_NAMESPACE namespace.
+\c TYPE_COMPILER_NAMESPACE argument allows to override the namespace in which
+\l{QML Type Compiler}{qmltc} generates code.
+By default, the namespace of the generated code follows the module
+hierarchy as depicted in the URI,
+e.g., \c MyModule for a module with URI \c MyModule or
+\c com::example::Module for URI \c com.example.MyModule.
+By specifying the \c TYPE_COMPILER_NAMESPACE option, the generated code
+can be put instead in a custom namespace, where different subnamespaces are to
+be separated by a "::", e.g. "MyNamespace::MySubnamespace" for the namespace MySubnamespace that
+is inside the MyNamespace. Apart from the "::", C++ namespace naming rules
+apply.
*/
diff --git a/tests/auto/qml/qmltc/CMakeLists.txt b/tests/auto/qml/qmltc/CMakeLists.txt
index d71d1ac557..4b86a6c018 100644
--- a/tests/auto/qml/qmltc/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/CMakeLists.txt
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(QmltcTests)
+add_subdirectory(NamespaceTest/Subfolder)
set(test_sources
nameconflict.h nameconflict.cpp
@@ -16,6 +17,7 @@ set(qmltc_module_libs
# - Properly see C++ types exposed to QML in the engine (we need C++
# automatic type registration that comes from the plugin)
qmltc_test_moduleplugin
+ qmltc_namespace_test_module
)
qt_internal_add_test(tst_qmltc_diskcache
SOURCES ${test_sources}
diff --git a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
new file mode 100644
index 0000000000..a93698655c
--- /dev/null
+++ b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
@@ -0,0 +1,41 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+set(cpp_sources
+)
+
+set(qml_sources
+ Type.qml
+)
+
+set(js_sources
+)
+
+set(common_libraries
+ Qt::Core
+ Qt::QmlPrivate
+ Qt::QuickPrivate
+ Qt::TestPrivate
+ Qt::Gui # QColor, QMatrix4x4, ...
+)
+
+qt_add_library(qmltc_namespace_test_module STATIC)
+qt_autogen_tools_initial_setup(qmltc_namespace_test_module)
+
+target_link_libraries(qmltc_namespace_test_module PUBLIC ${common_libraries})
+
+qt6_add_qml_module(qmltc_namespace_test_module
+ VERSION 1.0
+ URI NamespaceTest.Subfolder
+ AUTO_RESOURCE_PREFIX
+ SOURCES
+ ${cpp_sources}
+ QML_FILES
+ ${qml_sources}
+ ${js_sources}
+ DEPENDENCIES
+ QtQuick
+ ENABLE_TYPE_COMPILER
+)
+
+qt_autogen_tools_initial_setup(qmltc_namespace_test_moduleplugin)
diff --git a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
new file mode 100644
index 0000000000..101e9f69a1
--- /dev/null
+++ b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string data
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
index cfb1469a38..870d21f61d 100644
--- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
@@ -180,7 +180,6 @@ qt6_add_qml_module(qmltc_test_module
LIBRARIES
qmltc_test_module_translation_by_id
ENABLE_TYPE_COMPILER
- TYPE_COMPILER_NAMESPACE QmltcTest
)
qt_autogen_tools_initial_setup(qmltc_test_moduleplugin)
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index 4e65554e45..1fa4030642 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -82,6 +82,7 @@
#include "singletons.h"
#include "mysignals.h"
#include "namespacedtypes.h"
+#include "type.h"
// Qt:
#include <QtCore/qstring.h>
@@ -103,7 +104,7 @@
# error "QMLTC_TESTS_DISABLE_CACHE is supposed to be defined and be equal to either 0 or 1"
#endif
-#define PREPEND_NAMESPACE(name) ::QmltcTest::name // silent contract that the namespace is QmltcTest
+#define PREPEND_NAMESPACE(name) QmltcTests::name // silent contract that the namespace is QmltcTest
using namespace Qt::StringLiterals;
@@ -1647,7 +1648,7 @@ void tst_qmltc::defaultAlias()
QScopedPointer<QObject> fromEngine(c.create());
QVERIFY2(fromEngine, qPrintable(c.errorString()));
- auto *child = static_cast<QmltcTest::defaultAlias_QtObject *>(created.child());
+ auto *child = static_cast<PREPEND_NAMESPACE(defaultAlias_QtObject) *>(created.child());
QVERIFY(fromEngine->property("child").canConvert<QObject *>());
QObject *childFromEngine = fromEngine->property("child").value<QObject *>();
QVERIFY(childFromEngine);
@@ -2653,23 +2654,23 @@ void tst_qmltc::appendToQQmlListProperty()
}
// test classes to access protected member typecount
-class myInlineComponentA : public QmltcTest::inlineComponents_A
+class myInlineComponentA : public PREPEND_NAMESPACE(inlineComponents_A)
{
friend class tst_qmltc;
};
-class myInlineComponentB : public QmltcTest::inlineComponents_B
+class myInlineComponentB : public PREPEND_NAMESPACE(inlineComponents_B)
{
friend class tst_qmltc;
};
-class myInlineComponentMyComponent : public QmltcTest::inlineComponents_MyComponent
+class myInlineComponentMyComponent : public PREPEND_NAMESPACE(inlineComponents_MyComponent)
{
friend class tst_qmltc;
};
-class myInlineComponentAPlus : public QmltcTest::inlineComponents_APlus
+class myInlineComponentAPlus : public PREPEND_NAMESPACE(inlineComponents_APlus)
{
friend class tst_qmltc;
};
-class myInlineComponentAPlusPlus : public QmltcTest::inlineComponents_APlusPlus
+class myInlineComponentAPlusPlus : public PREPEND_NAMESPACE(inlineComponents_APlusPlus)
{
friend class tst_qmltc;
};
@@ -2730,10 +2731,10 @@ void tst_qmltc::inlineComponents()
// test if nonrecursive components behave well
{
- auto *myMyComponentFromQmltc = (QmltcTest::inlineComponents_MyComponent_3 *)
- createdByQmltc.myMyComponentComponent();
- auto *myMyComponentFromQmltc2 = (QmltcTest::inlineComponents_MyComponent_4 *)
- createdByQmltc.myMyComponentComponent2();
+ auto *myMyComponentFromQmltc = (PREPEND_NAMESPACE(
+ inlineComponents_MyComponent_3) *)createdByQmltc.myMyComponentComponent();
+ auto *myMyComponentFromQmltc2 = (PREPEND_NAMESPACE(
+ inlineComponents_MyComponent_4) *)createdByQmltc.myMyComponentComponent2();
QVERIFY(myMyComponentFromQmltc);
QVERIFY(myMyComponentFromQmltc2);
auto *myMyComponentFromComponent =
@@ -2795,10 +2796,12 @@ void tst_qmltc::inlineComponents()
QCOMPARE(myMyComponentFromQmltc->children().size(), 1);
QCOMPARE(myMyComponentFromQmltc2->children().size(), 1);
auto *childFromQmltc =
- (QmltcTest::inlineComponents_MyComponent_Item *)myMyComponentFromQmltc->children()
+ (PREPEND_NAMESPACE(inlineComponents_MyComponent_Item) *)myMyComponentFromQmltc
+ ->children()
.front();
auto *childFromQmltc2 =
- (QmltcTest::inlineComponents_MyComponent_Item *)myMyComponentFromQmltc2->children()
+ (PREPEND_NAMESPACE(inlineComponents_MyComponent_Item) *)myMyComponentFromQmltc2
+ ->children()
.front();
QVERIFY(childFromQmltc);
@@ -2855,15 +2858,18 @@ void tst_qmltc::inlineComponents()
// test if recursive components are behaving well
{
- auto *myAFromQmltc = (QmltcTest::inlineComponents_A_1 *)createdByQmltc.myAComponent();
- auto *innerBFromQmltc = (QmltcTest::inlineComponents_A_B *)myAFromQmltc->b();
+ auto *myAFromQmltc =
+ (PREPEND_NAMESPACE(inlineComponents_A_1) *)createdByQmltc.myAComponent();
+ auto *innerBFromQmltc = (PREPEND_NAMESPACE(inlineComponents_A_B) *)myAFromQmltc->b();
QVERIFY(innerBFromQmltc);
- auto *innerAFromQmltc = (QmltcTest::inlineComponents_A_B_A *)innerBFromQmltc->a();
+ auto *innerAFromQmltc = (PREPEND_NAMESPACE(inlineComponents_A_B_A) *)innerBFromQmltc->a();
QVERIFY(innerAFromQmltc);
constexpr bool typeNotCompiledAsQQmlComponent =
- std::is_same_v<decltype(myAFromQmltc->b()), QmltcTest::inlineComponents_B *>;
+ std::is_same_v<decltype(myAFromQmltc->b()),
+ PREPEND_NAMESPACE(inlineComponents_B) *>;
constexpr bool typeNotCompiledAsQQmlComponent2 =
- std::is_same_v<decltype(innerBFromQmltc->a()), QmltcTest::inlineComponents_A *>;
+ std::is_same_v<decltype(innerBFromQmltc->a()),
+ PREPEND_NAMESPACE(inlineComponents_A) *>;
QVERIFY(typeNotCompiledAsQQmlComponent);
QVERIFY(typeNotCompiledAsQQmlComponent2);
@@ -2880,10 +2886,11 @@ void tst_qmltc::inlineComponents()
// test if ids in inlineComponents are not getting mixed up with those from the root component
{
auto *conflictingComponentTomFromQmltc =
- createdByQmltc.tom().value<QmltcTest::inlineComponents_ConflictingComponent_1 *>();
+ createdByQmltc.tom()
+ .value<PREPEND_NAMESPACE(inlineComponents_ConflictingComponent_1) *>();
auto *conflictingComponentJerryFromQmltc =
createdByQmltc.jerry()
- .value<QmltcTest::inlineComponents_ConflictingComponent_2 *>();
+ .value<PREPEND_NAMESPACE(inlineComponents_ConflictingComponent_2) *>();
auto *conflictingComponentTomFromComponent =
createdByComponent->property("tom").value<QObject *>();
@@ -2941,8 +2948,8 @@ void tst_qmltc::inlineComponents()
// check that inline components are resolved in the correct order
{
- auto componentFromQmltc =
- createdByQmltc.inlineComponentOrder().value<QmltcTest::inlineComponents_IC2_1 *>();
+ auto componentFromQmltc = createdByQmltc.inlineComponentOrder()
+ .value<PREPEND_NAMESPACE(inlineComponents_IC2_1) *>();
auto componentFromComponent =
createdByComponent->property("inlineComponentOrder").value<QObject *>();
@@ -3193,4 +3200,12 @@ void tst_qmltc::cppNamespaces()
QCOMPARE(createdByQmltc.myObject()->property("value"), 55);
}
+void tst_qmltc::namespacedName()
+{
+ // cmake script should be able to auto-fill the namespace of the generated modules, and to
+ // replace . with ::
+ NamespaceTest::Subfolder::Type *t;
+ Q_UNUSED(t);
+}
+
QTEST_MAIN(tst_qmltc)
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index a2d656bae7..af084dcc01 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -92,4 +92,5 @@ private slots:
void singletons();
void constSignalParameters();
void cppNamespaces();
+ void namespacedName();
};
diff --git a/tools/qmltc/qmltccodewriter.cpp b/tools/qmltc/qmltccodewriter.cpp
index c4c5c30f83..8010f1066c 100644
--- a/tools/qmltc/qmltccodewriter.cpp
+++ b/tools/qmltc/qmltccodewriter.cpp
@@ -149,24 +149,28 @@ void QmltcCodeWriter::writeGlobalHeader(QmltcOutputWrapper &code, const QString
code.rawAppendToCpp(u""); // blank line
code.rawAppendToCpp(u"QT_USE_NAMESPACE // avoid issues with QT_NAMESPACE");
- if (!outNamespace.isEmpty()) {
- code.rawAppendToHeader(u""); // blank line
- code.rawAppendToHeader(u"namespace %1 {"_s.arg(outNamespace));
- code.rawAppendToCpp(u""); // blank line
- code.rawAppendToCpp(u"namespace %1 {"_s.arg(outNamespace));
+
+ code.rawAppendToHeader(u""); // blank line
+
+ const QStringList namespaces = outNamespace.split(u"::"_s);
+
+ for (const QString &currentNamespace : namespaces) {
+ code.rawAppendToHeader(u"namespace %1 {"_s.arg(currentNamespace));
+ code.rawAppendToCpp(u"namespace %1 {"_s.arg(currentNamespace));
}
}
void QmltcCodeWriter::writeGlobalFooter(QmltcOutputWrapper &code, const QString &sourcePath,
const QString &outNamespace)
{
- if (!outNamespace.isEmpty()) {
- code.rawAppendToCpp(u"} // namespace %1"_s.arg(outNamespace));
- code.rawAppendToCpp(u""); // blank line
- code.rawAppendToHeader(u"} // namespace %1"_s.arg(outNamespace));
- code.rawAppendToHeader(u""); // blank line
+ const QStringList namespaces = outNamespace.split(u"::"_s);
+
+ for (auto it = namespaces.crbegin(), end = namespaces.crend(); it != end; it++) {
+ code.rawAppendToCpp(u"} // namespace %1"_s.arg(*it));
+ code.rawAppendToHeader(u"} // namespace %1"_s.arg(*it));
}
+ code.rawAppendToHeader(u""); // blank line
code.rawAppendToHeader(u"#endif // %1_H"_s.arg(urlToMacro(sourcePath)));
code.rawAppendToHeader(u""); // blank line
}