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>bb10
parent
d625b9bc47
commit
2e8a48c1cd
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -68,19 +68,23 @@ bool QDBusXmlParser::parseAnnotation(QDBusIntrospection::Annotations &annotation
|
|||
Q_ASSERT(m_currentInterface);
|
||||
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "annotation"_L1);
|
||||
|
||||
const QXmlStreamAttributes attributes = m_xml.attributes();
|
||||
const QString name = attributes.value("name"_L1).toString();
|
||||
QDBusIntrospection::Annotation annotation;
|
||||
annotation.location = m_currentLocation;
|
||||
|
||||
if (!QDBusUtil::isValidInterfaceName(name)) {
|
||||
const QXmlStreamAttributes attributes = m_xml.attributes();
|
||||
annotation.name = attributes.value("name"_L1).toString();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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\"/>"
|
||||
|
|
|
|||
Loading…
Reference in New Issue