File indexing completed on 2024-04-28 05:48:32

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 <QObject>
0009 
0010 #include "backendinterface.h"
0011 #include "configview.h"
0012 #include "dap/client.h"
0013 #include "dap/entities.h"
0014 #include "dap/settings.h"
0015 #include <memory>
0016 #include <optional>
0017 
0018 class DapBackend : public BackendInterface
0019 {
0020     Q_OBJECT
0021 public:
0022     DapBackend(QObject *parent);
0023     ~DapBackend() override = default;
0024 
0025     void runDebugger(const DAPTargetConf &conf);
0026     bool debuggerRunning() const override;
0027     bool debuggerBusy() const override;
0028     bool hasBreakpoint(QUrl const &url, int line) const override;
0029 
0030     bool supportsMovePC() const override;
0031     bool supportsRunToCursor() const override;
0032     bool canSetBreakpoints() const override;
0033     bool canMove() const override;
0034     bool canContinue() const override;
0035 
0036     void toggleBreakpoint(QUrl const &url, int line) override;
0037     void movePC(QUrl const &url, int line) override;
0038     void runToCursor(QUrl const &url, int line) override;
0039 
0040     void issueCommand(QString const &cmd) override;
0041 
0042     QString targetName() const override;
0043     void setFileSearchPaths(const QStringList &paths) override;
0044 
0045 public Q_SLOTS:
0046     void slotInterrupt() override;
0047     void slotStepInto() override;
0048     void slotStepOver() override;
0049     void slotStepOut() override;
0050     void slotContinue() override;
0051     void slotKill() override;
0052     void slotReRun() override;
0053     QString slotPrintVariable(const QString &variable) override;
0054 
0055     void slotQueryLocals(bool display) override;
0056     void changeStackFrame(int index) override;
0057     void changeThread(int index) override;
0058     void changeScope(int scopeId) override;
0059 
0060 private:
0061     enum State { None, Initializing, Running, Stopped, Terminated, Disconnected, PostMortem };
0062     enum Task { Idle, Busy };
0063 
0064     void unsetClient();
0065 
0066     void onError(const QString &message);
0067     void onTerminated();
0068     void onStopped(const dap::StoppedEvent &info);
0069     void onThreads(const QList<dap::Thread> &threads);
0070     void onStackTrace(const int, const dap::StackTraceInfo &info);
0071     void onProgramEnded(int exitCode);
0072     void onRunning();
0073     void onContinuedEvent(const dap::ContinuedEvent &info);
0074     void onInitialized();
0075     void onErrorResponse(const QString &summary, const std::optional<dap::Message> &message);
0076     void onOutputProduced(const dap::Output &output);
0077     void onDebuggingProcess(const dap::ProcessInfo &info);
0078     void onThreadEvent(const dap::ThreadEvent &info);
0079     void onModuleEvent(const dap::ModuleEvent &info);
0080     void onScopes(const int frameId, const QList<dap::Scope> &scopes);
0081     void onVariables(const int variablesReference, const QList<dap::Variable> &variables);
0082     void onModules(const dap::ModulesInfo &modules);
0083     void onSourceBreakpoints(const QString &path, int reference, const std::optional<QList<dap::Breakpoint>> &breakpoints);
0084     void onBreakpointEvent(const dap::BreakpointEvent &info);
0085     void onExpressionEvaluated(const QString &expression, const std::optional<dap::EvaluateInfo> &info);
0086     void onGotoTargets(const dap::Source &, const int, const QList<dap::GotoTarget> &targets);
0087     void onCapabilitiesReceived(const dap::Capabilities &capabilities);
0088     void onServerDisconnected();
0089     void onServerFinished();
0090 
0091     bool tryTerminate();
0092     bool tryDisconnect();
0093     void cmdShutdown();
0094     void cmdHelp(const QString &cmd);
0095     void cmdEval(const QString &cmd);
0096     void cmdJump(const QString &cmd);
0097     void cmdRunToCursor(const QString &cmd);
0098     void cmdListModules(const QString &cmd);
0099     void cmdListBreakpoints(const QString &cmd);
0100     void cmdBreakpointOn(const QString &cmd);
0101     void cmdBreakpointOff(const QString &cmd);
0102     void cmdPause(const QString &cmd);
0103     void cmdContinue(const QString &cmd);
0104     void cmdNext(const QString &cmd);
0105     void cmdStepIn(const QString &cmd);
0106     void cmdStepOut(const QString &cmd);
0107     void cmdWhereami(const QString &cmd);
0108 
0109     void resetState(State state = State::Running);
0110     void setState(State state);
0111     void setTaskState(Task state);
0112 
0113     bool isConnectedState() const;
0114     bool isAttachedState() const;
0115     bool isRunningState() const;
0116 
0117     void pushRequest();
0118     void popRequest();
0119 
0120     QString resolveOrWarn(const QString &filename);
0121     std::optional<QString> resolveFilename(const QString &filename, bool fallback = true) const;
0122     dap::settings::ClientSettings &target2dap(const DAPTargetConf &target);
0123     std::optional<int> findBreakpoint(const QString &path, int line) const;
0124     std::optional<int> findBreakpointIntent(const QString &path, int line) const;
0125 
0126     void insertBreakpoint(const QString &path, int line);
0127     // return false if nothing found
0128     bool removeBreakpoint(const QString &path, int line);
0129     void informBreakpointAdded(const QString &path, const dap::Breakpoint &bpoint);
0130     void informBreakpointRemoved(const QString &path, int line);
0131     void clearBreakpoints();
0132     void informStackFrame();
0133 
0134     QString m_targetName;
0135 
0136     void start();
0137 
0138     dap::Client *m_client = nullptr;
0139     std::optional<dap::settings::ClientSettings> m_settings;
0140     State m_state;
0141     Task m_task;
0142 
0143     QString m_file;
0144     QString m_workDir;
0145     std::optional<int> m_currentThread;
0146     std::optional<int> m_watchedThread;
0147     std::optional<int> m_currentFrame;
0148     std::optional<int> m_currentScope;
0149     bool m_restart = false;
0150     bool m_queryLocals = false;
0151 
0152     enum KillMode { Polite, Force };
0153 
0154     struct {
0155         std::optional<State> target = std::nullopt;
0156         std::optional<KillMode> userAction = std::nullopt;
0157     } m_shutdown;
0158 
0159     void shutdownUntil(std::optional<State> state = std::nullopt);
0160     bool continueShutdown() const;
0161 
0162     struct Cursor {
0163         int line;
0164         QString path;
0165     };
0166     std::optional<Cursor> m_runToCursor;
0167 
0168     int m_requests;
0169 
0170     QStringList m_commandQueue;
0171 
0172     std::map<QString, QList<std::optional<dap::Breakpoint>>> m_breakpoints;
0173     std::map<QString, QList<dap::SourceBreakpoint>> m_wantedBreakpoints;
0174     QList<dap::StackFrame> m_frames;
0175 };