1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "debugmanager.h"
6#include "dap/dapdebugger.h"
7#include "debuggersignals.h"
8#include "debuggerglobals.h"
9#include "interface/menumanager.h"
10
11#include "services/debugger/debuggerservice.h"
12#include "services/language/languageservice.h"
13#include "common/util/custompaths.h"
14#include "services/project/projectinfo.h"
15
16using namespace DEBUG_NAMESPACE;
17using namespace dpfservice;
18DebugManager::DebugManager(QObject *parent)
19 : QObject(parent)
20{
21 connect(debuggerSignals, &DebuggerSignals::receivedEvent, this, &DebugManager::handleEvents);
22}
23
24bool DebugManager::initialize(dpfservice::WindowService *windowService,
25 dpfservice::DebuggerService *debuggerService)
26{
27 currentDebugger = new DAPDebugger(this);
28 debuggers.insert("dap", currentDebugger);
29 runner = new Runner(this);
30
31 menuManager.reset(new MenuManager());
32 menuManager->initialize(windowService);
33
34 connect(currentDebugger, &AbstractDebugger::runStateChanged, this, &DebugManager::handleRunStateChanged);
35
36 // bind debug services
37 using namespace std::placeholders;
38 if (!debuggerService->runCoredump) {
39 debuggerService->runCoredump = std::bind(&DebugManager::runCoredump, this, _1, _2, _3);
40 }
41
42 if (!debuggerService->registerDebugger) {
43 debuggerService->registerDebugger = std::bind(&DebugManager::registerDebugger, this, _1, _2);
44 }
45
46 return true;
47}
48
49QWidget *DebugManager::getStackPane() const
50{
51 return currentDebugger->getStackPane();
52}
53
54QWidget *DebugManager::getLocalsPane() const
55{
56 return currentDebugger->getLocalsPane();
57}
58
59QWidget *DebugManager::getBreakpointPane() const
60{
61 return currentDebugger->getBreakpointPane();
62}
63
64void DebugManager::registerDebugger(const QString &kit, AbstractDebugger *debugger)
65{
66 auto iterator = debuggers.find(kit);
67 if (iterator == debuggers.end()) {
68 debuggers.insert(kit, debugger);
69 }
70}
71
72void DebugManager::run()
73{
74 AbstractDebugger::RunState state = currentDebugger->getRunState();
75 switch (state) {
76 case AbstractDebugger::RunState::kNoRun:
77 case AbstractDebugger::RunState::kPreparing:
78 {
79 LanguageService *service = dpfGetService(LanguageService);
80 if (service) {
81 auto generator = service->create<LanguageGenerator>(activeProjectKitName);
82 if (generator) {
83 QString debugger = generator->debugger();
84 if (debuggers.contains(debugger) && currentDebugger != debuggers[debugger]) {
85 disconnect(currentDebugger, &AbstractDebugger::runStateChanged, this, &DebugManager::handleRunStateChanged);
86 currentDebugger = debuggers[debugger];
87 connect(currentDebugger, &AbstractDebugger::runStateChanged, this, &DebugManager::handleRunStateChanged);
88 }
89 }
90 }
91 AsynInvoke(currentDebugger->startDebug());
92 break;
93 }
94 case AbstractDebugger::RunState::kRunning:
95 // TODO(mozart):stop debug
96 break;
97 case AbstractDebugger::RunState::kStopped:
98 continueDebug();
99 break;
100 default:
101 ;// do nothing.
102 }
103}
104
105void DebugManager::detachDebug()
106{
107 AsynInvoke(currentDebugger->detachDebug());
108}
109
110void DebugManager::interruptDebug()
111{
112 AsynInvoke(currentDebugger->interruptDebug());
113}
114
115void DebugManager::continueDebug()
116{
117 AsynInvoke(currentDebugger->continueDebug());
118}
119
120void DebugManager::abortDebug()
121{
122 AsynInvoke(currentDebugger->abortDebug());
123}
124
125void DebugManager::restartDebug()
126{
127 AsynInvoke(currentDebugger->restartDebug());
128}
129
130void DebugManager::stepOver()
131{
132 AsynInvoke(currentDebugger->stepOver());
133}
134
135void DebugManager::stepIn()
136{
137 AsynInvoke(currentDebugger->stepIn());
138}
139
140void DebugManager::stepOut()
141{
142 AsynInvoke(currentDebugger->stepOut());
143}
144
145void DebugManager::handleRunStateChanged(AbstractDebugger::RunState state)
146{
147 menuManager->handleRunStateChanged(state);
148
149 if(state == AbstractDebugger::kStart || state == AbstractDebugger::kRunning) {
150 emit debugStarted();
151 }
152}
153
154void DebugManager::handleEvents(const dpf::Event &event)
155{
156 QString topic = event.topic();
157 QString data = event.data().toString();
158 if (event.data() == debugger.prepareDebugProgress.name) {
159 // TODO(logan)
160 } else if (event.data() == project.activedProject.name) {
161 auto projectInfo = qvariant_cast<ProjectInfo>(event.property(project.activedProject.pKeys[0]));
162 activeProjectKitName = projectInfo.kitName();
163 } else if (event.data() == project.createdProject.name) {
164 auto projectInfo = qvariant_cast<ProjectInfo>(event.property(project.createdProject.pKeys[0]));
165 activeProjectKitName = projectInfo.kitName();
166 } else if (event.data() == project.deletedProject.name) {
167 activeProjectKitName.clear();
168 } else if (event.data() == editor.switchedFile.name) {
169 // TODO(logan)
170 } else if (event.data() == editor.openedFile.name) {
171 // TODO(logan)
172 } else if (event.data() == editor.closedFile.name) {
173 // TODO(logan)
174 }
175}
176
177bool DebugManager::runCoredump(const QString &target, const QString &core, const QString &kit)
178{
179 return QtConcurrent::run(currentDebugger, &AbstractDebugger::runCoredump, target, core, kit);
180}
181