diff options
author | Kevin Ottens <kevin.ottens@kdab.com> | 2012-11-30 11:51:05 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-12-11 07:41:49 +0100 |
commit | 5b3e7c8dfa4856b04013ace24d19bbd104dc3bd0 (patch) | |
tree | dbaf1fa3c3ecf623b99807bc18c90e57de535991 | |
parent | fac02ddc39145963646ad0f36b9e41573e49e6c5 (diff) |
Generate the introspection string during parsing
Commit 0696071316b3dacb8d1ca15a269e4f4215642b9d moved away from QDom but
also lost the ability to fill the introspection field of the created
QDBusIntrospection::Interface instances. This commit now generate the
string again as we proceed with the QXmlStreamReader based parsing.
Task-number: QTBUG-26668
Change-Id: I8f406e1f4e9d3e667a8557db69da36cac369ba4f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/dbus/qdbusxmlparser.cpp | 156 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusxmlparser/qdbusxmlparser.pro | 2 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp | 99 |
3 files changed, 173 insertions, 84 deletions
diff --git a/src/dbus/qdbusxmlparser.cpp b/src/dbus/qdbusxmlparser.cpp index 315b4a2e24..c2c1b8daff 100644 --- a/src/dbus/qdbusxmlparser.cpp +++ b/src/dbus/qdbusxmlparser.cpp @@ -59,7 +59,8 @@ QT_BEGIN_NAMESPACE -static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection::Argument &argData) +static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection::Argument &argData, + QDBusIntrospection::Interface *ifaceData) { const QString argType = attributes.value(QLatin1String("type")).toString(); @@ -72,10 +73,21 @@ static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection: argData.name = attributes.value(QLatin1String("name")).toString(); argData.type = argType; + ifaceData->introspection += QLatin1String(" <arg"); + if (attributes.hasAttribute(QLatin1String("direction"))) { + const QString direction = attributes.value(QLatin1String("direction")).toString(); + ifaceData->introspection += QLatin1String(" direction=\"") + direction + QLatin1String("\""); + } + ifaceData->introspection += QLatin1String(" type=\"") + argData.type + QLatin1String("\""); + if (!argData.name.isEmpty()) + ifaceData->introspection += QLatin1String(" name=\"") + argData.name + QLatin1String("\""); + ifaceData->introspection += QLatin1String("/>\n"); + return ok; } -static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Annotations &annotations) +static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Annotations &annotations, + QDBusIntrospection::Interface *ifaceData, bool interfaceAnnotation = false) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("annotation")); @@ -87,12 +99,16 @@ static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Ann qPrintable(name)); return false; } - annotations.insert(name, attributes.value(QLatin1String("value")).toString()); + const QString value = attributes.value(QLatin1String("value")).toString(); + annotations.insert(name, value); + if (!interfaceAnnotation) + ifaceData->introspection += QLatin1String(" "); + ifaceData->introspection += QLatin1String(" <annotation value=\"") + value + QLatin1String("\" name=\"") + name + QLatin1String("\"/>\n"); return true; } static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &propertyData, - const QString &ifaceName) + QDBusIntrospection::Interface *ifaceData) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("property")); @@ -100,7 +116,7 @@ static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &p const QString propertyName = attributes.value(QLatin1String("name")).toString(); if (!QDBusUtil::isValidMemberName(propertyName)) { qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(propertyName), qPrintable(ifaceName)); + qPrintable(propertyName), qPrintable(ifaceData->name)); xml.skipCurrentElement(); return false; } @@ -112,7 +128,7 @@ static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &p if (!QDBusUtil::isValidSingleSignature(propertyData.type)) { // cannot be! qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", - qPrintable(propertyData.type), qPrintable(ifaceName), + qPrintable(propertyData.type), qPrintable(ifaceData->name), qPrintable(propertyName)); } @@ -125,18 +141,28 @@ static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &p propertyData.access = QDBusIntrospection::Property::ReadWrite; else { qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", - qPrintable(access), qPrintable(ifaceName), + qPrintable(access), qPrintable(ifaceData->name), qPrintable(propertyName)); return false; // invalid one! } - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("annotation")) { - parseAnnotation(xml, propertyData.annotations); - } else if (xml.prefix().isEmpty()) { - qDBusParserError() << "Unknown element" << xml.name() << "while checking for annotations"; - } - xml.skipCurrentElement(); + ifaceData->introspection += QLatin1String(" <property access=\"") + access + QLatin1String("\" type=\"") + propertyData.type + QLatin1String("\" name=\"") + propertyName + QLatin1String("\""); + + if (!xml.readNextStartElement()) { + ifaceData->introspection += QLatin1String("/>\n"); + } else { + ifaceData->introspection += QLatin1String(">\n"); + + do { + if (xml.name() == QLatin1String("annotation")) { + parseAnnotation(xml, propertyData.annotations, ifaceData); + } else if (xml.prefix().isEmpty()) { + qDBusParserError() << "Unknown element" << xml.name() << "while checking for annotations"; + } + xml.skipCurrentElement(); + } while (xml.readNextStartElement()); + + ifaceData->introspection += QLatin1String(" </property>\n"); } if (!xml.isEndElement() || xml.name() != QLatin1String("property")) { @@ -148,7 +174,7 @@ static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &p } static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &methodData, - const QString &ifaceName) + QDBusIntrospection::Interface *ifaceData) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("method")); @@ -156,35 +182,44 @@ static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &metho const QString methodName = attributes.value(QLatin1String("name")).toString(); if (!QDBusUtil::isValidMemberName(methodName)) { qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(methodName), qPrintable(ifaceName)); + qPrintable(methodName), qPrintable(ifaceData->name)); return false; } methodData.name = methodName; + ifaceData->introspection += QLatin1String(" <method name=\"") + methodName + QLatin1String("\""); QDBusIntrospection::Arguments outArguments; QDBusIntrospection::Arguments inArguments; QDBusIntrospection::Annotations annotations; - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("annotation")) { - parseAnnotation(xml, annotations); - } else if (xml.name() == QLatin1String("arg")) { - const QXmlStreamAttributes attributes = xml.attributes(); - const QString direction = attributes.value(QLatin1String("direction")).toString(); - QDBusIntrospection::Argument argument; - if (!attributes.hasAttribute(QLatin1String("direction")) - || direction == QLatin1String("in")) { - parseArg(attributes, argument); - inArguments << argument; - } else if (direction == QLatin1String("out")) { - parseArg(attributes, argument); - outArguments << argument; + if (!xml.readNextStartElement()) { + ifaceData->introspection += QLatin1String("/>\n"); + } else { + ifaceData->introspection += QLatin1String(">\n"); + + do { + if (xml.name() == QLatin1String("annotation")) { + parseAnnotation(xml, annotations, ifaceData); + } else if (xml.name() == QLatin1String("arg")) { + const QXmlStreamAttributes attributes = xml.attributes(); + const QString direction = attributes.value(QLatin1String("direction")).toString(); + QDBusIntrospection::Argument argument; + if (!attributes.hasAttribute(QLatin1String("direction")) + || direction == QLatin1String("in")) { + parseArg(attributes, argument, ifaceData); + inArguments << argument; + } else if (direction == QLatin1String("out")) { + parseArg(attributes, argument, ifaceData); + outArguments << argument; + } + } else if (xml.prefix().isEmpty()) { + qDBusParserError() << "Unknown element" << xml.name() << "while checking for method arguments"; } - } else if (xml.prefix().isEmpty()) { - qDBusParserError() << "Unknown element" << xml.name() << "while checking for method arguments"; - } - xml.skipCurrentElement(); + xml.skipCurrentElement(); + } while (xml.readNextStartElement()); + + ifaceData->introspection += QLatin1String(" </method>\n"); } methodData.inputArgs = inArguments; @@ -196,7 +231,7 @@ static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &metho static bool parseSignal(QXmlStreamReader &xml, QDBusIntrospection::Signal &signalData, - const QString &ifaceName) + QDBusIntrospection::Interface *ifaceData) { Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("signal")); @@ -205,31 +240,39 @@ static bool parseSignal(QXmlStreamReader &xml, QDBusIntrospection::Signal &signa if (!QDBusUtil::isValidMemberName(signalName)) { qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(signalName), qPrintable(ifaceName)); + qPrintable(signalName), qPrintable(ifaceData->name)); return false; } signalData.name = signalName; - + ifaceData->introspection += QLatin1String(" <signal name=\"") + signalName + QLatin1String("\""); QDBusIntrospection::Arguments arguments; QDBusIntrospection::Annotations annotations; - while (xml.readNextStartElement()) { - if (xml.name() == QLatin1String("annotation")) { - parseAnnotation(xml, annotations); - } else if (xml.name() == QLatin1String("arg")) { - const QXmlStreamAttributes attributes = xml.attributes(); - QDBusIntrospection::Argument argument; - if (!attributes.hasAttribute(QLatin1String("direction")) || - attributes.value(QLatin1String("direction")) == QLatin1String("out")) { - parseArg(attributes, argument); - arguments << argument; + if (!xml.readNextStartElement()) { + ifaceData->introspection += QLatin1String("/>\n"); + } else { + ifaceData->introspection += QLatin1String(">\n"); + + do { + if (xml.name() == QLatin1String("annotation")) { + parseAnnotation(xml, annotations, ifaceData); + } else if (xml.name() == QLatin1String("arg")) { + const QXmlStreamAttributes attributes = xml.attributes(); + QDBusIntrospection::Argument argument; + if (!attributes.hasAttribute(QLatin1String("direction")) || + attributes.value(QLatin1String("direction")) == QLatin1String("out")) { + parseArg(attributes, argument, ifaceData); + arguments << argument; + } + } else { + qDBusParserError() << "Unknown element" << xml.name() << "while checking for signal arguments"; } - } else { - qDBusParserError() << "Unknown element" << xml.name() << "while checking for signal arguments"; - } - xml.skipCurrentElement(); + xml.skipCurrentElement(); + } while (xml.readNextStartElement()); + + ifaceData->introspection += QLatin1String(" </signal>\n"); } signalData.outputArgs = arguments; @@ -252,22 +295,23 @@ static void readInterface(QXmlStreamReader &xml, QDBusIntrospection::Object *obj QDBusIntrospection::Interface *ifaceData = new QDBusIntrospection::Interface; ifaceData->name = ifaceName; + ifaceData->introspection += QLatin1String(" <interface name=\"") + ifaceName + QLatin1String("\">\n"); while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("method")) { QDBusIntrospection::Method methodData; - if (parseMethod(xml, methodData, ifaceName)) + if (parseMethod(xml, methodData, ifaceData)) ifaceData->methods.insert(methodData.name, methodData); } else if (xml.name() == QLatin1String("signal")) { QDBusIntrospection::Signal signalData; - if (parseSignal(xml, signalData, ifaceName)) + if (parseSignal(xml, signalData, ifaceData)) ifaceData->signals_.insert(signalData.name, signalData); } else if (xml.name() == QLatin1String("property")) { QDBusIntrospection::Property propertyData; - if (parseProperty(xml, propertyData, ifaceName)) + if (parseProperty(xml, propertyData, ifaceData)) ifaceData->properties.insert(propertyData.name, propertyData); } else if (xml.name() == QLatin1String("annotation")) { - parseAnnotation(xml, ifaceData->annotations); + parseAnnotation(xml, ifaceData->annotations, ifaceData, true); xml.skipCurrentElement(); // skip over annotation object } else { if (xml.prefix().isEmpty()) { @@ -277,6 +321,8 @@ static void readInterface(QXmlStreamReader &xml, QDBusIntrospection::Object *obj } } + ifaceData->introspection += QLatin1String(" </interface>"); + interfaces->insert(ifaceName, QSharedDataPointer<QDBusIntrospection::Interface>(ifaceData)); if (!xml.isEndElement() || xml.name() != QLatin1String("interface")) { diff --git a/tests/auto/dbus/qdbusxmlparser/qdbusxmlparser.pro b/tests/auto/dbus/qdbusxmlparser/qdbusxmlparser.pro index 4b3415612a..a7186c341b 100644 --- a/tests/auto/dbus/qdbusxmlparser/qdbusxmlparser.pro +++ b/tests/auto/dbus/qdbusxmlparser/qdbusxmlparser.pro @@ -1,5 +1,5 @@ CONFIG += testcase TARGET = tst_qdbusxmlparser -QT = core-private dbus-private testlib +QT = core-private dbus-private xml testlib SOURCES += tst_qdbusxmlparser.cpp DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp b/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp index 5f03600b89..35cf989753 100644 --- a/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp +++ b/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp @@ -44,6 +44,7 @@ #include <qmetatype.h> #include <QtTest/QtTest> #include <QtDBus/QtDBus> +#include <QtXml/QDomDocument> #define USE_PRIVATE_CODE #include "../qdbusmarshall/common.h" @@ -54,6 +55,7 @@ class tst_QDBusXmlParser: public QObject private: void parsing_common(const QString&); + QString clean_xml(const QString&); private slots: void parsing_data(); @@ -75,36 +77,58 @@ void tst_QDBusXmlParser::parsing_data() QTest::addColumn<int>("interfaceCount"); QTest::addColumn<int>("objectCount"); QTest::addColumn<int>("annotationCount"); + QTest::addColumn<QStringList>("introspection"); - QTest::newRow("null") << QString() << 0 << 0 << 0; - QTest::newRow("empty") << QString("") << 0 << 0 << 0; + QStringList introspection; + + QTest::newRow("null") << QString() << 0 << 0 << 0 << introspection; + QTest::newRow("empty") << QString("") << 0 << 0 << 0 << introspection; - QTest::newRow("junk") << "<junk/>" << 0 << 0 << 0; + QTest::newRow("junk") << "<junk/>" << 0 << 0 << 0 << introspection; QTest::newRow("interface-inside-junk") << "<junk><interface name=\"iface.iface1\" /></junk>" - << 0 << 0 << 0; + << 0 << 0 << 0 << introspection; QTest::newRow("object-inside-junk") << "<junk><node name=\"obj1\" /></junk>" - << 0 << 0 << 0; + << 0 << 0 << 0 << introspection; - QTest::newRow("zero-interfaces") << "<node/>" << 0 << 0 << 0; - QTest::newRow("one-interface") << "<node><interface name=\"iface.iface1\" /></node>" << 1 << 0 << 0; + QTest::newRow("zero-interfaces") << "<node/>" << 0 << 0 << 0 << introspection; - + introspection << "<interface name=\"iface.iface1\"/>"; + QTest::newRow("one-interface") << "<node><interface name=\"iface.iface1\" /></node>" + << 1 << 0 << 0 << introspection; + introspection.clear(); + + introspection << "<interface name=\"iface.iface1\"/>" + << "<interface name=\"iface.iface2\"/>"; QTest::newRow("two-interfaces") << "<node><interface name=\"iface.iface1\" />" "<interface name=\"iface.iface2\" /></node>" - << 2 << 0 << 0; + << 2 << 0 << 0 << introspection; + introspection.clear(); - QTest::newRow("one-object") << "<node><node name=\"obj1\"/></node>" << 0 << 1 << 0; - QTest::newRow("two-objects") << "<node><node name=\"obj1\"/><node name=\"obj2\"/></node>" << 0 << 2 << 0; + QTest::newRow("one-object") << "<node><node name=\"obj1\"/></node>" + << 0 << 1 << 0 << introspection; + QTest::newRow("two-objects") << "<node><node name=\"obj1\"/><node name=\"obj2\"/></node>" + << 0 << 2 << 0 << introspection; - QTest::newRow("i1o1") << "<node><interface name=\"iface.iface1\"/><node name=\"obj1\"/></node>" << 1 << 1 << 0; + introspection << "<interface name=\"iface.iface1\"/>"; + QTest::newRow("i1o1") << "<node><interface name=\"iface.iface1\"/><node name=\"obj1\"/></node>" + << 1 << 1 << 0 << introspection; + introspection.clear(); + introspection << "<interface name=\"iface.iface1\">" + " <annotation name=\"foo.testing\" value=\"nothing to see here\"/>" + "</interface>"; QTest::newRow("one-interface-annotated") << "<node><interface name=\"iface.iface1\">" "<annotation name=\"foo.testing\" value=\"nothing to see here\" />" - "</interface></node>" << 1 << 0 << 1; + "</interface></node>" << 1 << 0 << 1 << introspection; + introspection.clear(); + + + introspection << "<interface name=\"iface.iface1\"/>"; QTest::newRow("one-interface-docnamespace") << "<?xml version=\"1.0\" xmlns:doc=\"foo\" ?><node>" "<interface name=\"iface.iface1\"><doc:something />" - "</interface></node>" << 1 << 0 << 0; + "</interface></node>" << 1 << 0 << 0 << introspection; + introspection.clear(); } void tst_QDBusXmlParser::parsing_common(const QString &xmlData) @@ -114,20 +138,36 @@ void tst_QDBusXmlParser::parsing_common(const QString &xmlData) QFETCH(int, interfaceCount); QFETCH(int, objectCount); QFETCH(int, annotationCount); + QFETCH(QStringList, introspection); QCOMPARE(obj.interfaces.count(), interfaceCount); QCOMPARE(obj.childObjects.count(), objectCount); QCOMPARE(QDBusIntrospection::parseInterface(xmlData).annotations.count(), annotationCount); + QDBusIntrospection::Interfaces ifaces = QDBusIntrospection::parseInterfaces(xmlData); + // also verify the naming int i = 0; - foreach (QString name, obj.interfaces) - QCOMPARE(name, QString("iface.iface%1").arg(++i)); + foreach (QString name, obj.interfaces) { + const QString expectedName = QString("iface.iface%1").arg(i+1); + QCOMPARE(name, expectedName); + + const QString expectedIntrospection = clean_xml(introspection.at(i++)); + const QString resultIntrospection = clean_xml(ifaces.value(expectedName)->introspection); + QCOMPARE(resultIntrospection, expectedIntrospection); + } i = 0; foreach (QString name, obj.childObjects) QCOMPARE(name, QString("obj%1").arg(++i)); } +QString tst_QDBusXmlParser::clean_xml(const QString &xmlData) +{ + QDomDocument dom; + dom.setContent(xmlData); + return dom.toString(); +} + void tst_QDBusXmlParser::parsing() { QFETCH(QString, xmlData); @@ -304,10 +344,10 @@ void tst_QDBusXmlParser::methods_data() void tst_QDBusXmlParser::methods() { - QString xmlHeader = "<node>" - "<interface name=\"iface.iface1\">", - xmlFooter = "</interface>" - "</node>"; + QString intHeader = "<interface name=\"iface.iface1\">", + intFooter = "</interface>", + xmlHeader = "<node>" + intHeader, + xmlFooter = intFooter + "</node>"; QFETCH(QString, xmlDataFragment); @@ -315,6 +355,7 @@ void tst_QDBusXmlParser::methods() QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter); QCOMPARE(iface.name, QString("iface.iface1")); + QCOMPARE(clean_xml(iface.introspection), clean_xml(intHeader + xmlDataFragment + intFooter)); QFETCH(MethodMap, methodMap); MethodMap parsedMap = iface.methods; @@ -417,10 +458,10 @@ void tst_QDBusXmlParser::signals__data() void tst_QDBusXmlParser::signals_() { - QString xmlHeader = "<node>" - "<interface name=\"iface.iface1\">", - xmlFooter = "</interface>" - "</node>"; + QString intHeader = "<interface name=\"iface.iface1\">", + intFooter = "</interface>", + xmlHeader = "<node>" + intHeader, + xmlFooter = intFooter + "</node>"; QFETCH(QString, xmlDataFragment); @@ -428,6 +469,7 @@ void tst_QDBusXmlParser::signals_() QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter); QCOMPARE(iface.name, QString("iface.iface1")); + QCOMPARE(clean_xml(iface.introspection), clean_xml(intHeader + xmlDataFragment + intFooter)); QFETCH(SignalMap, signalMap); SignalMap parsedMap = iface.signals_; @@ -506,10 +548,10 @@ void tst_QDBusXmlParser::properties_data() void tst_QDBusXmlParser::properties() { - QString xmlHeader = "<node>" - "<interface name=\"iface.iface1\">", - xmlFooter = "</interface>" - "</node>"; + QString intHeader = "<interface name=\"iface.iface1\">", + intFooter = "</interface>", + xmlHeader = "<node>" + intHeader, + xmlFooter = intFooter + "</node>"; QFETCH(QString, xmlDataFragment); @@ -517,6 +559,7 @@ void tst_QDBusXmlParser::properties() QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter); QCOMPARE(iface.name, QString("iface.iface1")); + QCOMPARE(clean_xml(iface.introspection), clean_xml(intHeader + xmlDataFragment + intFooter)); QFETCH(PropertyMap, propertyMap); PropertyMap parsedMap = iface.properties; |