diff options
author | Matthias Rauter <[email protected]> | 2025-02-18 17:20:09 +0100 |
---|---|---|
committer | Matthias Rauter <[email protected]> | 2025-03-05 10:06:19 +0100 |
commit | 351b7a31aa24a704dba09121d91cb34190892315 (patch) | |
tree | c5c1976f16eddcbb481cc77caa1123fbd84ae3d0 | |
parent | 611031e4f069aea6a0312b5c459247094204d5eb (diff) |
Add namespaces to qdbusxml2cpp
[ChangeLog][QtDBus][qdbusxml2cpp] The Qt D-Bus XML compiler
(qdbusxml2cpp) now supports the command-line argument -namespace
<namespace>, which encapsulates all generated classes within the
specified namespace to prevent class name conflicts.
Fixes: QTBUG-133611
Change-Id: Ic3473dfc33dcf22f5be727236fe546b70b2b015b
Reviewed-by: Ivan Solovev <[email protected]>
-rw-r--r-- | src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 41 | ||||
-rw-r--r-- | tests/auto/tools/qdbusxml2cpp/tst_qdbusxml2cpp.cpp | 47 |
2 files changed, 86 insertions, 2 deletions
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index d637854d2bb..7ab7241c962 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -80,6 +80,7 @@ private: QString globalClassName; QString parentClassName; + QString customNamespace; QString inputFile; bool skipNamespaces = false; bool includeMocs = false; @@ -608,6 +609,13 @@ void QDBusXmlToCpp::writeProxy(const QString &filename, cs << "#include \"" << headerName << "\"\n\n"; } + if (!customNamespace.isEmpty()) { + hs << "namespace " << customNamespace << " { \n" + "\n"; + cs << "namespace " << customNamespace << " { \n" + "\n"; + } + for (const QDBusIntrospection::Interface *interface : interfaces) { QString className = classNameForInterface(interface->name, Proxy); @@ -799,6 +807,13 @@ void QDBusXmlToCpp::writeProxy(const QString &filename, hs << "};\n\n"; } + if (!customNamespace.isEmpty()) { + hs << "} // end of namespace " << customNamespace << "\n" + << "\n"; + cs << "} // end of namespace " << customNamespace << "\n" + << "\n"; + } + if (!skipNamespaces) { QStringList last; QDBusIntrospection::Interfaces::ConstIterator it = interfaces.constBegin(); @@ -827,7 +842,8 @@ void QDBusXmlToCpp::writeProxy(const QString &filename, // add this class: if (!name.isEmpty()) { hs << QString(current.size() * 2, u' ') - << "using " << name << " = ::" << classNameForInterface(it->constData()->name, Proxy) + << "using " << name << " = " << (customNamespace.isEmpty() ? "" : "::") + << customNamespace << "::" << classNameForInterface(it->constData()->name, Proxy) << ";\n"; } @@ -836,6 +852,8 @@ void QDBusXmlToCpp::writeProxy(const QString &filename, ++it; last = current; } while (true); + + hs << "\n"; } // close the include guard @@ -937,6 +955,13 @@ void QDBusXmlToCpp::writeAdaptor(const QString &filename, if (parentClassName.isEmpty()) parent = u"QObject"_s; + if (!customNamespace.isEmpty()) { + hs << "namespace " << customNamespace << " { \n" + "\n"; + cs << "namespace " << customNamespace << " { \n" + "\n"; + } + for (const QDBusIntrospection::Interface *interface : interfaces) { QString className = classNameForInterface(interface->name, Adaptor); @@ -1134,6 +1159,13 @@ void QDBusXmlToCpp::writeAdaptor(const QString &filename, hs << "};\n\n"; } + if (!customNamespace.isEmpty()) { + hs << "} // end of namespace " << customNamespace << "\n" + << "\n"; + cs << "} // end of namespace " << customNamespace << "\n" + << "\n"; + } + // close the include guard hs << "#endif\n"; @@ -1188,6 +1220,10 @@ int QDBusXmlToCpp::run(const QCoreApplication &app) u"classname"_s); parser.addOption(classNameOption); + QCommandLineOption namespaceOption(QStringList{u"namespace"_s}, + u"Put all generated classes into the namespace <namespace>. "_s, u"namespace"_s); + parser.addOption(namespaceOption); + QCommandLineOption addIncludeOption(QStringList{u"i"_s, u"include"_s}, u"Add #include \"filename\" to the output"_s, u"filename"_s); parser.addOption(addIncludeOption); @@ -1205,7 +1241,7 @@ int QDBusXmlToCpp::run(const QCoreApplication &app) parser.addOption(mocIncludeOption); QCommandLineOption noNamespaceOption(QStringList{u"N"_s, u"no-namespaces"_s}, - u"Don't use namespaces"_s); + u"Do not export the generated class into the D-Bus specific namespace"_s); parser.addOption(noNamespaceOption); QCommandLineOption proxyCodeOption(QStringList{u"p"_s, u"proxy"_s}, @@ -1223,6 +1259,7 @@ int QDBusXmlToCpp::run(const QCoreApplication &app) includes = parser.values(addIncludeOption); globalIncludes = parser.values(addGlobalIncludeOption); parentClassName = parser.value(adapterParentOption); + customNamespace = parser.value(namespaceOption); includeMocs = parser.isSet(mocIncludeOption); skipNamespaces = parser.isSet(noNamespaceOption); QString proxyFile = parser.value(proxyCodeOption); diff --git a/tests/auto/tools/qdbusxml2cpp/tst_qdbusxml2cpp.cpp b/tests/auto/tools/qdbusxml2cpp/tst_qdbusxml2cpp.cpp index c51a0909f8d..5474c4f7470 100644 --- a/tests/auto/tools/qdbusxml2cpp/tst_qdbusxml2cpp.cpp +++ b/tests/auto/tools/qdbusxml2cpp/tst_qdbusxml2cpp.cpp @@ -25,6 +25,8 @@ private slots: void missingAnnotation(); void includeMoc_data(); void includeMoc(); + void customNamespace_data(); + void customNamespace(); }; struct BasicTypeList { @@ -482,6 +484,51 @@ void tst_qdbusxml2cpp::includeMoc() } } +void tst_qdbusxml2cpp::customNamespace_data() +{ + QTest::addColumn<QByteArray>("namesp"); + + QTest::newRow("simple") << QByteArray("lancetest"); + QTest::newRow("double") << QByteArray("lance::test"); +} + +void tst_qdbusxml2cpp::customNamespace() +{ + QFETCH(QByteArray, namesp); + + QProcess process; + QStringList flags = {"-", "--namespace", namesp}; + + runTool(process,QByteArray{},flags); + QCOMPARE(process.exitCode(), 0); + + QByteArray errOutput = process.readAllStandardError(); + QVERIFY2(errOutput.isEmpty(), errOutput); + + QByteArray fullOutput = process.readAll(); + QVERIFY(!fullOutput.isEmpty()); + + // twice: once in the header, once in the implementation + static constexpr qsizetype requiredNameSpaceCount = 2; + QCOMPARE(fullOutput.count("namespace " + namesp + " {"), requiredNameSpaceCount); + + static constexpr QByteArrayView endMarker("} // end of namespace "); + qsizetype startFrom = 0; + for (qsizetype i = 0; i < requiredNameSpaceCount; ++i) { + // make sure the namespace is there + qsizetype namespaceStart = fullOutput.indexOf("namespace " + namesp + " {", startFrom); + qsizetype namespaceEnd = fullOutput.indexOf(endMarker + namesp, namespaceStart); + QCOMPARE_GE(namespaceStart, 0); + QCOMPARE_GT(namespaceEnd, namespaceStart); + startFrom = namespaceEnd + endMarker.size() + namesp.size(); + + // make sure we cover a useful part of the source code with the namespace: + auto partOutput = QByteArrayView(fullOutput) + .slice(namespaceStart, startFrom - namespaceStart); + QCOMPARE(partOutput.count("{"), partOutput.count("}")); + } +} + QTEST_MAIN(tst_qdbusxml2cpp) #include "tst_qdbusxml2cpp.moc" |