diff options
author | Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> | 2023-06-30 17:02:37 +0200 |
---|---|---|
committer | Ievgenii Meshcheriakov <ievgenii.meshcheriakov@qt.io> | 2023-07-06 21:51:15 +0200 |
commit | 2e8a48c1cdc8547ec47f097a41dd53c641715b77 (patch) | |
tree | a02f7aaaf06318600e5d96f7f52b2a5f948ef1e0 | |
parent | d625b9bc47c05a83e2fd52e70ba0ee26b20bdb26 (diff) |
QDBusIntrospection: Add Annotation struct
Add a structure for annotation data containing
name, value and location information. This is done
to be able to emit diagnostics related to annotations
that include source location.
Task-number: QTBUG-2597
Change-Id: Ie990bcd0a16752b5f44f4314f8d730dd1b1a30b4
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/dbus/qdbusintrospection_p.h | 15 | ||||
-rw-r--r-- | src/dbus/qdbusmetaobject.cpp | 8 | ||||
-rw-r--r-- | src/dbus/qdbusxmlparser.cpp | 16 | ||||
-rw-r--r-- | src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 47 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusmarshall/common.h | 6 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp | 20 |
6 files changed, 70 insertions, 42 deletions
diff --git a/src/dbus/qdbusintrospection_p.h b/src/dbus/qdbusintrospection_p.h index 209d1386ae..38a7d5cc66 100644 --- a/src/dbus/qdbusintrospection_p.h +++ b/src/dbus/qdbusintrospection_p.h @@ -38,9 +38,10 @@ public: struct Interface; struct Object; struct ObjectTree; + struct Annotation; // typedefs - typedef QMap<QString, QString> Annotations; + typedef QMap<QString, Annotation> Annotations; typedef QList<Argument> Arguments; typedef QMultiMap<QString, Method> Methods; typedef QMultiMap<QString, Signal> Signals; @@ -116,6 +117,18 @@ public: annotations == other.annotations && type == other.type; } }; + struct Annotation + { + SourceLocation location; + QString name; + QString value; + + inline bool operator==(const Annotation &other) const + { + return name == other.name && value == other.value; + } + }; + struct Interface: public QSharedData { SourceLocation location; diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 2e367e63ac..543b185df9 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -148,7 +148,8 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, .arg(id); // extract from annotations: - QByteArray typeName = annotations.value(annotationName).toLatin1(); + auto annotation = annotations.value(annotationName); + QByteArray typeName = annotation.value.toLatin1(); // verify that it's a valid one if (typeName.isEmpty()) { @@ -158,7 +159,8 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, annotationName += QString::fromLatin1(".%1%2") .arg(QLatin1StringView(direction)) .arg(id); - typeName = annotations.value(annotationName).toLatin1(); + annotation = annotations.value(annotationName); + typeName = annotation.value.toLatin1(); } if (!typeName.isEmpty()) { @@ -269,7 +271,7 @@ void QDBusMetaObjectGenerator::parseMethods() prototype.append(')'); // check the async tag - if (m.annotations.value(ANNOTATION_NO_WAIT ""_L1) == "true"_L1) + if (m.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1) mm.tag = "Q_NOREPLY"; // meta method flags diff --git a/src/dbus/qdbusxmlparser.cpp b/src/dbus/qdbusxmlparser.cpp index 8769e0ae5e..7636ba365a 100644 --- a/src/dbus/qdbusxmlparser.cpp +++ b/src/dbus/qdbusxmlparser.cpp @@ -68,19 +68,23 @@ bool QDBusXmlParser::parseAnnotation(QDBusIntrospection::Annotations &annotation Q_ASSERT(m_currentInterface); Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "annotation"_L1); + QDBusIntrospection::Annotation annotation; + annotation.location = m_currentLocation; + const QXmlStreamAttributes attributes = m_xml.attributes(); - const QString name = attributes.value("name"_L1).toString(); + annotation.name = attributes.value("name"_L1).toString(); - if (!QDBusUtil::isValidInterfaceName(name)) { + if (!QDBusUtil::isValidInterfaceName(annotation.name)) { qDBusParserError("Invalid D-Bus annotation '%s' found while parsing introspection", - qPrintable(name)); + qPrintable(annotation.name)); return false; } - const QString value = attributes.value("value"_L1).toString(); - annotations.insert(name, value); + annotation.value = attributes.value("value"_L1).toString(); + annotations.insert(annotation.name, annotation); if (!interfaceAnnotation) m_currentInterface->introspection += " "_L1; - m_currentInterface->introspection += " <annotation value=\""_L1 + value.toHtmlEscaped() + "\" name=\""_L1 + name + "\"/>\n"_L1; + m_currentInterface->introspection += " <annotation value=\""_L1 + + annotation.value.toHtmlEscaped() + "\" name=\""_L1 + annotation.name + "\"/>\n"_L1; return true; } diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index 2c4fe3652a..171491dfbd 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -235,14 +235,16 @@ static QByteArray qtTypeName(const QString &where, const QString &signature, QString annotationName = u"org.qtproject.QtDBus.QtTypeName"_s; if (paramId >= 0) annotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId); - QString qttype = annotations.value(annotationName); + auto annotation = annotations.value(annotationName); + QString qttype = annotation.value; if (!qttype.isEmpty()) return std::move(qttype).toLatin1(); QString oldAnnotationName = u"com.trolltech.QtDBus.QtTypeName"_s; if (paramId >= 0) oldAnnotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId); - qttype = annotations.value(oldAnnotationName); + annotation = annotations.value(oldAnnotationName); + qttype = annotation.value; if (qttype.isEmpty()) { fprintf(stderr, "%s: Got unknown type `%s' processing '%s'\n", @@ -372,47 +374,47 @@ static void writeSignalArgList(QTextStream &ts, const QStringList &argNames, static QString propertyGetter(const QDBusIntrospection::Property &property) { - QString getter = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1); - if (!getter.isEmpty()) - return getter; + auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1); + if (!annotation.value.isEmpty()) + return annotation.value; - getter = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1); - if (!getter.isEmpty()) { + annotation = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1); + if (!annotation.value.isEmpty()) { fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found" " while processing '%s';" " suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n", PROGRAMNAME, qPrintable(inputFile)); - return getter; + return annotation.value; } - getter = property.name; + QString getter = property.name; getter[0] = getter[0].toLower(); return getter; } static QString propertySetter(const QDBusIntrospection::Property &property) { - QString setter = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1); - if (!setter.isEmpty()) - return setter; + auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1); + if (!annotation.value.isEmpty()) + return annotation.value; - setter = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1); - if (!setter.isEmpty()) { + annotation = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1); + if (!annotation.value.isEmpty()) { fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found" " while processing '%s';" " suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n", PROGRAMNAME, qPrintable(inputFile)); - return setter; + return annotation.value; } - setter = "set"_L1 + property.name; + QString setter = "set"_L1 + property.name; setter[3] = setter[3].toUpper(); return setter; } static QString methodName(const QDBusIntrospection::Method &method) { - QString name = method.annotations.value(u"org.qtproject.QtDBus.MethodName"_s); + QString name = method.annotations.value(u"org.qtproject.QtDBus.MethodName"_s).value; if (!name.isEmpty()) return name; @@ -588,9 +590,9 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // methods: hs << "public Q_SLOTS: // METHODS\n"; for (const QDBusIntrospection::Method &method : interface->methods) { - bool isDeprecated = method.annotations.value("org.freedesktop.DBus.Deprecated"_L1) == "true"_L1; - bool isNoReply = - method.annotations.value(ANNOTATION_NO_WAIT ""_L1) == "true"_L1; + bool isDeprecated = method.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value + == "true"_L1; + bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1; if (isNoReply && !method.outputArgs.isEmpty()) { fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n", PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), @@ -687,7 +689,7 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf hs << "Q_SIGNALS: // SIGNALS\n"; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; - if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1) == "true"_L1) + if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value == "true"_L1) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; @@ -921,8 +923,7 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << "public Q_SLOTS: // METHODS\n"; for (const QDBusIntrospection::Method &method : interface->methods) { - bool isNoReply = - method.annotations.value(ANNOTATION_NO_WAIT ""_L1) == "true"_L1; + bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1; if (isNoReply && !method.outputArgs.isEmpty()) { fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n", PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), qPrintable(interface->name)); diff --git a/tests/auto/dbus/qdbusmarshall/common.h b/tests/auto/dbus/qdbusmarshall/common.h index 916370c377..e972ca21a1 100644 --- a/tests/auto/dbus/qdbusmarshall/common.h +++ b/tests/auto/dbus/qdbusmarshall/common.h @@ -214,7 +214,7 @@ QString printable(const QDBusIntrospection::Method& m) .arg(arg.type, arg.name); AnnotationsMap::const_iterator it = m.annotations.begin(); for ( ; it != m.annotations.end(); ++it) - result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value()); + result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value().value); result += ")"; return result; @@ -228,7 +228,7 @@ QString printable(const QDBusIntrospection::Signal& s) .arg(arg.type, arg.name); AnnotationsMap::const_iterator it = s.annotations.begin(); for ( ; it != s.annotations.end(); ++it) - result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value()); + result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value().value); result += ")"; return result; @@ -247,7 +247,7 @@ QString printable(const QDBusIntrospection::Property& p) AnnotationsMap::const_iterator it = p.annotations.begin(); for ( ; it != p.annotations.end(); ++it) - result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value()); + result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value().value); return result; } diff --git a/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp b/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp index 5e1ff9e5b7..01f174c3e8 100644 --- a/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp +++ b/tests/auto/dbus/qdbusxmlparser/tst_qdbusxmlparser.cpp @@ -32,6 +32,14 @@ private slots: void properties(); }; +static void addAnnotation(QDBusIntrospection::Annotations &annotations, const QString &name, + const QString &value) +{ + annotations.insert( + name, + QDBusIntrospection::Annotation{ QDBusIntrospection::SourceLocation{}, name, value }); +} + void tst_QDBusXmlParser::initTestCase() { // Always initialize the hash seed with a known value to get reliable test results @@ -191,7 +199,7 @@ void tst_QDBusXmlParser::methods_data() // add a third, with annotations method.name = "Baz"; - method.annotations.insert("foo.testing", "nothing to see here"); + addAnnotation(method.annotations, "foo.testing", "nothing to see here"); map << method; QTest::newRow("method-with-annotation") << "<method name=\"Foo\"/>" @@ -290,7 +298,7 @@ void tst_QDBusXmlParser::methods_data() method = QDBusIntrospection::Method(); method.inputArgs << arg("a{sv}", "variantMap") << arg("u", "index"); method.outputArgs << arg("s", "key") << arg("v", "value"); - method.annotations.insert("foo.equivalent", "QVariantMap"); + addAnnotation(method.annotations, "foo.equivalent", "QVariantMap"); method.name = "Method2"; map << method; @@ -359,7 +367,7 @@ void tst_QDBusXmlParser::signals__data() // add a third, with annotations signal.name = "Baz"; - signal.annotations.insert("foo.testing", "nothing to see here"); + addAnnotation(signal.annotations, "foo.testing", "nothing to see here"); map << signal; QTest::newRow("signal-with-annotation") << "<signal name=\"Foo\"/>" @@ -408,7 +416,7 @@ void tst_QDBusXmlParser::signals__data() // with annotation "foo.equivalent":"QVariantMap" signal = QDBusIntrospection::Signal(); signal.outputArgs << arg("s", "key") << arg("v", "value"); - signal.annotations.insert("foo.equivalent", "QVariantMap"); + addAnnotation(signal.annotations, "foo.equivalent", "QVariantMap"); signal.name = "Signal2"; map << signal; @@ -492,8 +500,8 @@ void tst_QDBusXmlParser::properties_data() prop.name = "baz"; prop.type = "as"; prop.access = QDBusIntrospection::Property::Write; - prop.annotations.insert("foo.annotation", "Hello, World"); - prop.annotations.insert("foo.annotation2", "Goodbye, World"); + addAnnotation(prop.annotations, "foo.annotation", "Hello, World"); + addAnnotation(prop.annotations, "foo.annotation2", "Goodbye, World"); map << prop; QTest::newRow("complex") << "<property access=\"read\" type=\"i\" name=\"bar\"/>" |