From 9a66022b8a23afb399a7d313314aeb51e7d99fd4 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sat, 9 Mar 2024 20:19:38 +0800 Subject: [PATCH] Initial implementation for #254 --- RedPandaIDE/debugger/dapprotocol.cpp | 138 ++++++++++++++++++++++----- RedPandaIDE/debugger/dapprotocol.h | 27 +++++- 2 files changed, 137 insertions(+), 28 deletions(-) diff --git a/RedPandaIDE/debugger/dapprotocol.cpp b/RedPandaIDE/debugger/dapprotocol.cpp index 626ed48c..e18a20cc 100644 --- a/RedPandaIDE/debugger/dapprotocol.cpp +++ b/RedPandaIDE/debugger/dapprotocol.cpp @@ -2,46 +2,136 @@ #include #include -QString createDAPRequestMessage(qint64 seq, const QString &command, const QVariantMap &arguments) + +DAPMessageError::DAPMessageError(const QString &reason) : BaseError{reason} { + +} + +static QJsonObject createDAPMessageObj(qint64 seq, const QString& type) { QJsonObject obj; obj["seq"]=seq; - obj["type"]="request"; - obj["command"]=command; - if (!arguments.isEmpty()) { - obj["arguments"]= QJsonObject::fromVariantMap(arguments); - } + obj["type"]=type; + return obj; +} + +static QString jsonToDAPMessageString(const QJsonObject &jsonObj) +{ QJsonDocument doc; - doc.setObject(obj); + doc.setObject(jsonObj); QString contentPart = doc.toJson(QJsonDocument::JsonFormat::Indented); QString message = QString("Content-Length: %1\r\n").arg(contentPart.length())+contentPart; return message; } -DAPRequest parseDAPRequestMessage(const QByteArray &contentPart) -{ +static QJsonObject contentPartToDAPMessageObj(const QByteArray &contentPart) { QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(contentPart, &error); if (error.error != QJsonParseError::NoError) { throw DAPMessageError(QObject::tr("Failed to parse json content: %1").arg(QString::fromUtf8(contentPart))); } QJsonObject obj = doc.object(); - DAPRequest req; - if (!obj.contains("seq")) { - throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg("seq")); - } - req.seq = obj["seq"].toDouble(); - req.type = "request"; - if (!obj.contains("command")) { - throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg("command")); - } - req.command = obj["command"].toString(); - if (obj.contains("arguments")) - req.arguments = obj["arguments"].toObject().toVariantMap(); - return req; + return obj; } -DAPMessageError::DAPMessageError(const QString &reason) : BaseError{reason} +static bool parseJsonObjBoolProperty(const QJsonObject& obj, const QString propName) { + if (!obj.contains(propName)) { + throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg(propName)); + } + return obj[propName].toBool(); +} + +static int parseJsonObjIntProperty(const QJsonObject& obj, const QString propName) { + if (!obj.contains(propName)) { + throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg(propName)); + } + return obj[propName].toInt(); +} + +static double parseJsonObjNumberProperty(const QJsonObject& obj, const QString propName) { + if (!obj.contains(propName)) { + throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg(propName)); + } + return obj[propName].toDouble(); +} + +static QString parseJsonObjStringProperty(const QJsonObject& obj, const QString propName) { + if (!obj.contains(propName)) { + throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg(propName)); + } + return obj[propName].toString(); +} + +static QJsonObject parseJsonObjObjectProperty(const QJsonObject& obj, const QString propName) { + if (!obj.contains(propName)) { + throw DAPMessageError(QObject::tr("The request message don't have '%1' field!").arg(propName)); + } + return obj[propName].toObject(); +} + + +QString createDAPRequestMessage(qint64 seq, const QString &command, const QJsonObject &arguments) { - + QJsonObject obj = createDAPMessageObj(seq, "request"); + obj["command"]=command; + if (!arguments.isEmpty()) { + obj["arguments"] = arguments; + } + return jsonToDAPMessageString(obj); +} + +QString createDAPResponseMessage(qint64 seq, qint64 request_seq, bool success, const QString &command, const QString &message, const QJsonObject &body) +{ + QJsonObject obj = createDAPMessageObj(seq, "response"); + obj["request_seq"]=request_seq; + obj["success"]=success; + obj["command"]=command; + if (!message.isEmpty()) + obj["message"]=message; + if (!body.isEmpty()) + obj["body"]=body; + return jsonToDAPMessageString(obj); +} + +QString createDAPEventMessage(qint64 seq, const QString &event, const QJsonObject &body) +{ + QJsonObject obj = createDAPMessageObj(seq, "event"); + obj["event"] = event; + if (!body.isEmpty()) + obj["body"] = body; + return jsonToDAPMessageString(obj); +} + +std::shared_ptr parseDAPMessage(const QByteArray &contentPart) +{ + QJsonObject obj = contentPartToDAPMessageObj(contentPart); + DAPRequest req; + qint64 seq = parseJsonObjNumberProperty(obj, "seq"); + QString type = parseJsonObjStringProperty(obj, "type"); + if (type == "request") { + std::shared_ptr req = std::make_shared(); + req->seq = seq; + req->type = "request"; + req->command = parseJsonObjStringProperty(obj, "command"); + req->arguments = obj["arguments"].toObject(); + return req; + } else if (type == "event") { + std::shared_ptr event = std::make_shared(); + event->seq = seq; + event->type = "event"; + event->event = parseJsonObjStringProperty(obj, "event"); + event->body = obj["body"].toObject(); + return event; + } else if (type == "response") { + std::shared_ptr response = std::make_shared(); + response->seq = seq; + response->type = "response"; + response->request_seq = parseJsonObjNumberProperty(obj, "request_seq"); + response->success = parseJsonObjBoolProperty(obj, "success"); + response->command = parseJsonObjStringProperty(obj, "command"); + response->message = obj["message"].toString(); + response->body = obj["body"].toObject(); + return response; + } + return std::shared_ptr(); } diff --git a/RedPandaIDE/debugger/dapprotocol.h b/RedPandaIDE/debugger/dapprotocol.h index 811d5d2b..ead48aca 100644 --- a/RedPandaIDE/debugger/dapprotocol.h +++ b/RedPandaIDE/debugger/dapprotocol.h @@ -19,11 +19,12 @@ #include #include #include +#include #include class DAPMessageError : public BaseError { public: - explicit FileError(const QString& reason); + explicit DAPMessageError(const QString& reason); }; struct DAPProtocolMessage{ @@ -33,11 +34,29 @@ struct DAPProtocolMessage{ struct DAPRequest: public DAPProtocolMessage { QString command; - QVariantMap arguments; + QJsonObject arguments; +}; + +struct DAPEvent: public DAPProtocolMessage { + QString event; + QJsonObject body; +}; + +struct DAPResponse: public DAPProtocolMessage { + qint64 request_seq; + bool success; + QString command; + QString message; + QJsonObject body; }; QString createDAPRequestMessage( - qint64 seq, const QString &command, const QVariantMap& arguments); + qint64 seq, const QString &command, const QJsonObject& arguments); + +QString createDAPResponseMessage( + qint64 seq, qint64 request_seq, bool success, + const QString& command, const QString& message, const QJsonObject& body); + +std::shared_ptr parseDAPMessage(const QByteArray& contentPart); -DAPRequest parseDAPRequestMessage(const QByteArray& contentPart); #endif