File indexing completed on 2024-05-12 05:51:06
0001 /* 0002 SPDX-FileCopyrightText: 2022 Héctor Mesa Jiménez <wmj.py@gmx.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 #pragma once 0007 0008 #include <QByteArray> 0009 #include <QHash> 0010 #include <QJsonObject> 0011 #include <QObject> 0012 #include <functional> 0013 #include <memory> 0014 #include <optional> 0015 #include <utility> 0016 0017 #include "bus.h" 0018 #include "entities.h" 0019 #include "settings.h" 0020 0021 class QJsonObject; 0022 0023 namespace dap 0024 { 0025 class Client : public QObject 0026 { 0027 Q_OBJECT 0028 public: 0029 enum class State { None, Initializing, Initialized, Running, Terminated, Failed }; 0030 Q_ENUM(State) 0031 0032 Client(const settings::ProtocolSettings &protocolSettings, Bus *bus, QObject *parent = nullptr); 0033 0034 Client(const settings::ClientSettings &clientSettings, QObject *parent = nullptr); 0035 0036 ~Client() override; 0037 0038 Bus *bus() const 0039 { 0040 return m_bus; 0041 } 0042 0043 void start(); 0044 State state() const 0045 { 0046 return m_state; 0047 } 0048 settings::ProtocolSettings protocol() const 0049 { 0050 return m_protocol; 0051 } 0052 Capabilities adapterCapabilities() const 0053 { 0054 return m_adapterCapabilities; 0055 } 0056 bool isServerConnected() const; 0057 0058 bool supportsTerminate() const; 0059 0060 /* 0061 * requests 0062 */ 0063 void requestConfigurationDone(); 0064 void requestThreads(); 0065 void requestStackTrace(int threadId, int startFrame = 0, int levels = 0); 0066 void requestScopes(int frameId); 0067 void requestVariables(int variablesReference, Variable::Type filter = Variable::Type::Both, int start = 0, int count = 0); 0068 void requestModules(int start = 0, int count = 0); 0069 void requestNext(int threadId, bool singleThread = false); 0070 void requestStepIn(int threadId, bool singleThread = false); 0071 void requestStepOut(int threadId, bool singleThread = false); 0072 void requestGoto(int threadId, int targetId); 0073 void requestContinue(int threadId, bool singleThread = false); 0074 void requestPause(int threadId); 0075 void requestTerminate(bool restart = false); 0076 void requestDisconnect(bool restart = false); 0077 void requestSource(const Source &source); 0078 void requestSetBreakpoints(const QString &path, const QList<dap::SourceBreakpoint> breakpoints, bool sourceModified = false); 0079 void requestSetBreakpoints(const dap::Source &source, const QList<dap::SourceBreakpoint> breakpoints, bool sourceModified = false); 0080 void requestEvaluate(const QString &expression, const QString &context, std::optional<int> frameId = std::nullopt); 0081 void requestWatch(const QString &expression, std::optional<int> frameId = std::nullopt); 0082 void requestGotoTargets(const QString &path, const int line, const std::optional<int> column = std::nullopt); 0083 void requestGotoTargets(const dap::Source &source, const int line, const std::optional<int> column = std::nullopt); 0084 0085 void detach(); 0086 0087 static QString extractCommand(const QJsonObject &launchRequest); 0088 0089 typedef std::function<void(const Response &, const QJsonValue &)> ResponseHandler; 0090 0091 Q_SIGNALS: 0092 void finished(); 0093 void stateChanged(State state); 0094 void initialized(); 0095 void launched(); 0096 void configured(); 0097 void failed(); 0098 0099 void capabilitiesReceived(const Capabilities &capabilities); 0100 void debuggeeRunning(); 0101 void debuggeeTerminated(); 0102 void debuggeeExited(int exitCode); 0103 void debuggeeStopped(const StoppedEvent &); 0104 void debuggeeContinued(const ContinuedEvent &); 0105 void outputProduced(const Output &); 0106 void debuggingProcess(const ProcessInfo &); 0107 void errorResponse(const QString &summary, const std::optional<Message> &message); 0108 void threadChanged(const ThreadEvent &); 0109 void moduleChanged(const ModuleEvent &); 0110 void threads(const QList<Thread> &); 0111 void stackTrace(const int threadId, const StackTraceInfo &); 0112 void scopes(const int frameId, const QList<Scope> &); 0113 void variables(const int variablesReference, const QList<Variable> &); 0114 void modules(const ModulesInfo &); 0115 void serverDisconnected(); 0116 void sourceContent(const QString &path, int reference, const SourceContent &content); 0117 void sourceBreakpoints(const QString &path, int reference, const std::optional<QList<Breakpoint>> &breakpoints); 0118 void breakpointChanged(const BreakpointEvent &); 0119 void expressionEvaluated(const QString &expression, const std::optional<EvaluateInfo> &); 0120 void gotoTargets(const Source &source, const int line, const QList<GotoTarget> &targets); 0121 0122 private: 0123 void setState(const State &state); 0124 void bind(); 0125 void read(); 0126 0127 struct HeaderInfo { 0128 int payloadStart; 0129 int payloadLength; 0130 }; 0131 /** 0132 * @brief readHeader 0133 * @param headerEnd position of the header's end 0134 * @return info extracted from header or nullopt if incomplete 0135 */ 0136 std::optional<HeaderInfo> readHeader(); 0137 0138 void processProtocolMessage(const QJsonObject &msg); 0139 0140 /* 0141 * responses 0142 */ 0143 void processResponse(const QJsonObject &msg); 0144 void processResponseInitialize(const Response &response, const QJsonValue &); 0145 void processResponseConfigurationDone(const Response &response, const QJsonValue &); 0146 void processResponseLaunch(const Response &response, const QJsonValue &); 0147 void processResponseThreads(const Response &response, const QJsonValue &); 0148 void processResponseStackTrace(const Response &response, const QJsonValue &request); 0149 void processResponseScopes(const Response &response, const QJsonValue &request); 0150 void processResponseVariables(const Response &response, const QJsonValue &request); 0151 void processResponseModules(const Response &response, const QJsonValue &); 0152 void processResponseNext(const Response &response, const QJsonValue &); 0153 void processResponseContinue(const Response &response, const QJsonValue &); 0154 void processResponseTerminate(const Response &response, const QJsonValue &); 0155 void processResponseDisconnect(const Response &response, const QJsonValue &); 0156 void processResponseSource(const Response &response, const QJsonValue &); 0157 void processResponseSetBreakpoints(const Response &response, const QJsonValue &); 0158 void processResponseEvaluate(const Response &response, const QJsonValue &); 0159 void processResponseGotoTargets(const Response &response, const QJsonValue &); 0160 void processResponsePause(const Response &response, const QJsonValue &); 0161 0162 /* 0163 * events 0164 */ 0165 void processEvent(const QJsonObject &msg); 0166 void processEventInitialized(); 0167 void processEventTerminated(); 0168 void processEventExited(const QJsonObject &body); 0169 void processEventOutput(const QJsonObject &body); 0170 void processEventProcess(const QJsonObject &body); 0171 void processEventThread(const QJsonObject &body); 0172 void processEventStopped(const QJsonObject &body); 0173 void processEventModule(const QJsonObject &body); 0174 void processEventContinued(const QJsonObject &body); 0175 void processEventBreakpoint(const QJsonObject &body); 0176 0177 int sequenceNumber(); 0178 0179 void write(const QJsonObject &msg); 0180 0181 /* 0182 * requests 0183 */ 0184 QJsonObject makeRequest(const QString &command, const QJsonValue &arguments, const ResponseHandler &handler); 0185 void requestInitialize(); 0186 void requestLaunchCommand(); 0187 0188 void checkRunning(); 0189 void onServerOutput(const QString &message); 0190 void onProcessOutput(const QString &message); 0191 0192 /* 0193 * server capabilities 0194 */ 0195 Capabilities m_adapterCapabilities; 0196 0197 Bus *m_bus = nullptr; 0198 bool m_managedBus; 0199 QByteArray m_buffer; 0200 int m_seq = 0; 0201 QHash<int, std::tuple<QString, QJsonValue, ResponseHandler>> m_requests; 0202 0203 State m_state = State::None; 0204 bool m_launched = false; 0205 bool m_configured = false; 0206 0207 settings::ProtocolSettings m_protocol; 0208 QString m_launchCommand; 0209 }; 0210 0211 }