QDBus: Add diagnostics reporting interface
Add an abstract class QDBusIntrospection::DiagnosticsReporter for reporting errors and warnings. Extend QDBusXmlParser to accept optional diagnostics reporter and use it when available. Report unexpected elements as warnings and the rest of problems as errors. This will allow tools like qdbusxml2cpp to show parsing diagnostics using a custom format. While at it, s/D-BUS/D-Bus/a Task-number: QTBUG-2597 Change-Id: Ibec3f5f282cf717d1127eb64c82b4fc695f14a74 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
1572c420f3
commit
248d2103b5
@ -58,6 +58,15 @@ public:
|
||||
qint64 columnNumber = 0;
|
||||
};
|
||||
|
||||
class DiagnosticsReporter
|
||||
{
|
||||
public:
|
||||
virtual void warning(const SourceLocation &location, const char *msg, ...)
|
||||
Q_ATTRIBUTE_FORMAT_PRINTF(3, 4) = 0;
|
||||
virtual void error(const SourceLocation &location, const char *msg, ...)
|
||||
Q_ATTRIBUTE_FORMAT_PRINTF(3, 4) = 0;
|
||||
};
|
||||
|
||||
struct Argument
|
||||
{
|
||||
SourceLocation location;
|
||||
|
@ -17,7 +17,21 @@ using namespace Qt::StringLiterals;
|
||||
|
||||
Q_LOGGING_CATEGORY(dbusParser, "dbus.parser", QtWarningMsg)
|
||||
|
||||
#define qDBusParserError(...) qCDebug(dbusParser, ##__VA_ARGS__)
|
||||
#define qDBusParserWarning(format, ...) \
|
||||
do { \
|
||||
if (m_reporter) \
|
||||
m_reporter->warning(m_currentLocation, format "\n", ##__VA_ARGS__); \
|
||||
else \
|
||||
qCDebug(dbusParser, "Warning: " format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define qDBusParserError(format, ...) \
|
||||
do { \
|
||||
if (m_reporter) \
|
||||
m_reporter->error(m_currentLocation, format "\n", ##__VA_ARGS__); \
|
||||
else \
|
||||
qCDebug(dbusParser, "Error: " format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
bool QDBusXmlParser::parseArg(const QXmlStreamAttributes &attributes,
|
||||
QDBusIntrospection::Argument &argData)
|
||||
@ -28,8 +42,8 @@ bool QDBusXmlParser::parseArg(const QXmlStreamAttributes &attributes,
|
||||
|
||||
bool ok = QDBusUtil::isValidSingleSignature(argType);
|
||||
if (!ok) {
|
||||
qDBusParserError("Invalid D-BUS type signature '%s' found while parsing introspection",
|
||||
qPrintable(argType));
|
||||
qDBusParserError("Invalid D-Bus type signature '%s' found while parsing introspection",
|
||||
qPrintable(argType));
|
||||
}
|
||||
|
||||
argData.name = attributes.value("name"_L1).toString();
|
||||
@ -58,8 +72,8 @@ bool QDBusXmlParser::parseAnnotation(QDBusIntrospection::Annotations &annotation
|
||||
const QString name = attributes.value("name"_L1).toString();
|
||||
|
||||
if (!QDBusUtil::isValidInterfaceName(name)) {
|
||||
qDBusParserError("Invalid D-BUS annotation '%s' found while parsing introspection",
|
||||
qPrintable(name));
|
||||
qDBusParserError("Invalid D-Bus annotation '%s' found while parsing introspection",
|
||||
qPrintable(name));
|
||||
return false;
|
||||
}
|
||||
const QString value = attributes.value("value"_L1).toString();
|
||||
@ -78,8 +92,9 @@ bool QDBusXmlParser::parseProperty(QDBusIntrospection::Property &propertyData)
|
||||
QXmlStreamAttributes attributes = m_xml.attributes();
|
||||
const QString propertyName = attributes.value("name"_L1).toString();
|
||||
if (!QDBusUtil::isValidMemberName(propertyName)) {
|
||||
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
|
||||
qPrintable(propertyName), qPrintable(m_currentInterface->name));
|
||||
qDBusParserError("Invalid D-Bus member name '%s' found in interface '%s' while parsing "
|
||||
"introspection",
|
||||
qPrintable(propertyName), qPrintable(m_currentInterface->name));
|
||||
m_xml.skipCurrentElement();
|
||||
return false;
|
||||
}
|
||||
@ -90,9 +105,10 @@ bool QDBusXmlParser::parseProperty(QDBusIntrospection::Property &propertyData)
|
||||
|
||||
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(m_currentInterface->name),
|
||||
qPrintable(propertyName));
|
||||
qDBusParserError("Invalid D-Bus type signature '%s' found in property '%s.%s' while "
|
||||
"parsing introspection",
|
||||
qPrintable(propertyData.type), qPrintable(m_currentInterface->name),
|
||||
qPrintable(propertyName));
|
||||
}
|
||||
|
||||
const QString access = attributes.value("access"_L1).toString();
|
||||
@ -103,9 +119,10 @@ bool QDBusXmlParser::parseProperty(QDBusIntrospection::Property &propertyData)
|
||||
else if (access == "readwrite"_L1)
|
||||
propertyData.access = QDBusIntrospection::Property::ReadWrite;
|
||||
else {
|
||||
qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection",
|
||||
qPrintable(access), qPrintable(m_currentInterface->name),
|
||||
qPrintable(propertyName));
|
||||
qDBusParserError("Invalid D-Bus property access '%s' found in property '%s.%s' while "
|
||||
"parsing introspection",
|
||||
qPrintable(access), qPrintable(m_currentInterface->name),
|
||||
qPrintable(propertyName));
|
||||
return false; // invalid one!
|
||||
}
|
||||
|
||||
@ -120,7 +137,8 @@ bool QDBusXmlParser::parseProperty(QDBusIntrospection::Property &propertyData)
|
||||
if (m_xml.name() == "annotation"_L1) {
|
||||
parseAnnotation(propertyData.annotations);
|
||||
} else if (m_xml.prefix().isEmpty()) {
|
||||
qDBusParserError() << "Unknown element" << m_xml.name() << "while checking for annotations";
|
||||
qDBusParserWarning("Unknown element '%s' while checking for annotations",
|
||||
qPrintable(m_xml.name().toString()));
|
||||
}
|
||||
m_xml.skipCurrentElement();
|
||||
} while (readNextStartElement());
|
||||
@ -129,7 +147,7 @@ bool QDBusXmlParser::parseProperty(QDBusIntrospection::Property &propertyData)
|
||||
}
|
||||
|
||||
if (!m_xml.isEndElement() || m_xml.name() != "property"_L1) {
|
||||
qDBusParserError() << "Invalid property specification" << m_xml.tokenString() << m_xml.name();
|
||||
qDBusParserError("Invalid property specification: '%s'", qPrintable(m_xml.tokenString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -144,8 +162,9 @@ bool QDBusXmlParser::parseMethod(QDBusIntrospection::Method &methodData)
|
||||
const QXmlStreamAttributes attributes = m_xml.attributes();
|
||||
const QString methodName = attributes.value("name"_L1).toString();
|
||||
if (!QDBusUtil::isValidMemberName(methodName)) {
|
||||
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
|
||||
qPrintable(methodName), qPrintable(m_currentInterface->name));
|
||||
qDBusParserError("Invalid D-Bus member name '%s' found in interface '%s' while parsing "
|
||||
"introspection",
|
||||
qPrintable(methodName), qPrintable(m_currentInterface->name));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -177,7 +196,8 @@ bool QDBusXmlParser::parseMethod(QDBusIntrospection::Method &methodData)
|
||||
outArguments << argument;
|
||||
}
|
||||
} else if (m_xml.prefix().isEmpty()) {
|
||||
qDBusParserError() << "Unknown element" << m_xml.name() << "while checking for method arguments";
|
||||
qDBusParserWarning("Unknown element '%s' while checking for method arguments",
|
||||
qPrintable(m_xml.name().toString()));
|
||||
}
|
||||
m_xml.skipCurrentElement();
|
||||
} while (readNextStartElement());
|
||||
@ -201,8 +221,9 @@ bool QDBusXmlParser::parseSignal(QDBusIntrospection::Signal &signalData)
|
||||
const QString signalName = attributes.value("name"_L1).toString();
|
||||
|
||||
if (!QDBusUtil::isValidMemberName(signalName)) {
|
||||
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
|
||||
qPrintable(signalName), qPrintable(m_currentInterface->name));
|
||||
qDBusParserError("Invalid D-Bus member name '%s' found in interface '%s' while parsing "
|
||||
"introspection",
|
||||
qPrintable(signalName), qPrintable(m_currentInterface->name));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -230,7 +251,8 @@ bool QDBusXmlParser::parseSignal(QDBusIntrospection::Signal &signalData)
|
||||
arguments << argument;
|
||||
}
|
||||
} else {
|
||||
qDBusParserError() << "Unknown element" << m_xml.name() << "while checking for signal arguments";
|
||||
qDBusParserWarning("Unknown element '%s' while checking for signal arguments",
|
||||
qPrintable(m_xml.name().toString()));
|
||||
}
|
||||
m_xml.skipCurrentElement();
|
||||
} while (readNextStartElement());
|
||||
@ -250,8 +272,8 @@ void QDBusXmlParser::readInterface()
|
||||
|
||||
const QString ifaceName = m_xml.attributes().value("name"_L1).toString();
|
||||
if (!QDBusUtil::isValidInterfaceName(ifaceName)) {
|
||||
qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection",
|
||||
qPrintable(ifaceName));
|
||||
qDBusParserError("Invalid D-Bus interface name '%s' found while parsing introspection",
|
||||
qPrintable(ifaceName));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -283,7 +305,8 @@ void QDBusXmlParser::readInterface()
|
||||
m_xml.skipCurrentElement(); // skip over annotation object
|
||||
} else {
|
||||
if (m_xml.prefix().isEmpty()) {
|
||||
qDBusParserError() << "Unknown element while parsing interface" << m_xml.name();
|
||||
qDBusParserWarning("Unknown element '%s' while parsing interface",
|
||||
qPrintable(m_xml.name().toString()));
|
||||
}
|
||||
m_xml.skipCurrentElement();
|
||||
}
|
||||
@ -296,7 +319,7 @@ void QDBusXmlParser::readInterface()
|
||||
QSharedDataPointer<QDBusIntrospection::Interface>(m_currentInterface.release()));
|
||||
|
||||
if (!m_xml.isEndElement() || m_xml.name() != "interface"_L1) {
|
||||
qDBusParserError() << "Invalid Interface specification";
|
||||
qDBusParserError("Invalid Interface specification");
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,8 +330,8 @@ void QDBusXmlParser::readNode(int nodeLevel)
|
||||
? (m_object->path + objName)
|
||||
: QString(m_object->path + u'/' + objName);
|
||||
if (!QDBusUtil::isValidObjectPath(fullName)) {
|
||||
qDBusParserError("Invalid D-BUS object path '%s' found while parsing introspection",
|
||||
qPrintable(fullName));
|
||||
qDBusParserError("Invalid D-Bus object path '%s' found while parsing introspection",
|
||||
qPrintable(fullName));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -340,8 +363,13 @@ bool QDBusXmlParser::readNextStartElement()
|
||||
return false;
|
||||
}
|
||||
|
||||
QDBusXmlParser::QDBusXmlParser(const QString &service, const QString &path, const QString &xmlData)
|
||||
: m_service(service), m_path(path), m_object(new QDBusIntrospection::Object), m_xml(xmlData)
|
||||
QDBusXmlParser::QDBusXmlParser(const QString &service, const QString &path, const QString &xmlData,
|
||||
QDBusIntrospection::DiagnosticsReporter *reporter)
|
||||
: m_service(service),
|
||||
m_path(path),
|
||||
m_object(new QDBusIntrospection::Object),
|
||||
m_xml(xmlData),
|
||||
m_reporter(reporter)
|
||||
{
|
||||
m_object->service = m_service;
|
||||
m_object->path = m_path;
|
||||
@ -360,7 +388,8 @@ QDBusXmlParser::QDBusXmlParser(const QString &service, const QString &path, cons
|
||||
readInterface();
|
||||
} else {
|
||||
if (m_xml.prefix().isEmpty()) {
|
||||
qDBusParserError() << "skipping unknown element" << m_xml.name();
|
||||
qDBusParserWarning("Skipping unknown element '%s'",
|
||||
qPrintable(m_xml.name().toString()));
|
||||
}
|
||||
m_xml.skipCurrentElement();
|
||||
}
|
||||
@ -369,7 +398,8 @@ QDBusXmlParser::QDBusXmlParser(const QString &service, const QString &path, cons
|
||||
if (m_xml.name() == "node"_L1) {
|
||||
--nodeLevel;
|
||||
} else {
|
||||
qDBusParserError() << "Invalid Node declaration" << m_xml.name();
|
||||
qDBusParserError("Invalid node declaration '%s'",
|
||||
qPrintable(m_xml.name().toString()));
|
||||
}
|
||||
break;
|
||||
case QXmlStreamReader::StartDocument:
|
||||
@ -386,14 +416,13 @@ QDBusXmlParser::QDBusXmlParser(const QString &service, const QString &path, cons
|
||||
break;
|
||||
Q_FALLTHROUGH();
|
||||
default:
|
||||
qDBusParserError() << "unknown token" << m_xml.name() << m_xml.tokenString();
|
||||
qDBusParserError("Unknown token: '%s'", qPrintable(m_xml.tokenString()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_xml.hasError()) {
|
||||
qDBusParserError() << "xml error" << m_xml.errorString() << "doc" << xmlData;
|
||||
}
|
||||
if (m_xml.hasError())
|
||||
qDBusParserError("XML error: %s", qPrintable(m_xml.errorString()));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -39,10 +39,11 @@ class QDBusXmlParser
|
||||
QDBusIntrospection::Interfaces m_interfaces;
|
||||
QXmlStreamReader m_xml;
|
||||
QDBusIntrospection::SourceLocation m_currentLocation;
|
||||
QDBusIntrospection::DiagnosticsReporter *m_reporter;
|
||||
|
||||
public:
|
||||
QDBusXmlParser(const QString& service, const QString& path,
|
||||
const QString& xmlData);
|
||||
QDBusXmlParser(const QString &service, const QString &path, const QString &xmlData,
|
||||
QDBusIntrospection::DiagnosticsReporter *reporter = nullptr);
|
||||
|
||||
inline QDBusIntrospection::Interfaces interfaces() const { return m_interfaces; }
|
||||
inline QSharedDataPointer<QDBusIntrospection::Object> object() const { return m_object; }
|
||||
|
Loading…
Reference in New Issue
Block a user