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 }