1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "debugmodel.h" |
6 | #include "debug.h" |
7 | #include "debuggerglobals.h" |
8 | |
9 | #include <QUuid> |
10 | #include <QString> |
11 | |
12 | #include "stdlib.h" |
13 | |
14 | namespace DEBUG_NAMESPACE { |
15 | DebugModel::DebugModel(dap::optional<dap::array<DebugSession *>> _sessions, QObject *parent) |
16 | : QObject(parent) |
17 | { |
18 | if (_sessions) { |
19 | auto sessionArray = _sessions.value(); |
20 | sessions.insert(sessions.end(), sessionArray.begin(), sessionArray.end()); |
21 | } |
22 | } |
23 | |
24 | dap::array<DebugSession *> DebugModel::getSessions(bool includeInactive) |
25 | { |
26 | dap::array<DebugSession *> ret; |
27 | |
28 | std::copy_if(sessions.begin(), sessions.end(), std::back_inserter(ret), [&](const DebugSession *item){ |
29 | return (includeInactive || item->state != State::kInactive); |
30 | }); |
31 | |
32 | return ret; |
33 | } |
34 | |
35 | dap::optional<DebugSession *> DebugModel::getSession(dap::optional<dap::string> sessionId, bool includeInactive) |
36 | { |
37 | if (sessionId) { |
38 | auto filteredSessions = getSessions(includeInactive); |
39 | for (auto s : filteredSessions) { |
40 | if (s->getId() == sessionId.value()) { |
41 | return s; |
42 | } |
43 | } |
44 | } |
45 | return undefined; |
46 | } |
47 | |
48 | void DebugModel::addSession(DebugSession *session) |
49 | { |
50 | Q_ASSERT(session); |
51 | dap::array<DebugSession *> filterdSessions; |
52 | for (auto s = sessions.begin(); s != sessions.end();) { |
53 | if ((*s)->getId() == session->getId()) { |
54 | s = sessions.erase(s); |
55 | return; |
56 | } |
57 | if ((*s)->state == State::kInactive && (*s)->configuration->name == session->configuration->name) { |
58 | s = sessions.erase(s); |
59 | return; |
60 | } |
61 | ++s; |
62 | } |
63 | int i = 1; |
64 | char szBuf[10] = { 0 }; |
65 | for (auto s = sessions.begin(); s != sessions.end(); ++s) { |
66 | while ((*s)->getLabel() == session->getLabel()) { |
67 | sprintf(szBuf, "%d" , i); |
68 | auto newName = session->configuration->name + szBuf; |
69 | session->setName(newName); |
70 | memset(szBuf, 0, sizeof(szBuf)); |
71 | } |
72 | } |
73 | |
74 | sessions.push_back(session); |
75 | } |
76 | |
77 | void DebugModel::clear() |
78 | { |
79 | sessions.clear(); |
80 | } |
81 | |
82 | void DebugModel::rawUpdate(IRawModelUpdate *data) |
83 | { |
84 | for (auto it : sessions) { |
85 | if (it->getId() == data->sessionId) { |
86 | it->rawUpdate(data); |
87 | // fire event. |
88 | } |
89 | } |
90 | } |
91 | |
92 | void DebugModel::fetchCallStack(Thread &thread) |
93 | { |
94 | // fetch whole threads. |
95 | thread.fetchCallStack(); |
96 | } |
97 | |
98 | IBreakpoint convertToIBreakpoint(Breakpoint &bp) |
99 | { |
100 | IBreakpoint ibp; |
101 | ibp.condition = bp.condition; |
102 | ibp.hitCondition = bp.hitCondition; |
103 | ibp.logMessage = bp.logMessage; |
104 | ibp.verified = bp.verified(); |
105 | ibp.support = bp.supported(); |
106 | ibp.message = bp.message(); |
107 | ibp.sessionsThatVerified = bp.sessionsThatVerified(); |
108 | |
109 | ibp.uri = bp.uri(); |
110 | ibp.lineNumber = bp.lineNumber(); |
111 | ibp.endLineNumber = bp.endLineNumber(); |
112 | ibp.column = bp.column(); |
113 | ibp.endColumn = bp.endColumn(); |
114 | ibp.adapterData = bp.adapterData(); |
115 | |
116 | return ibp; |
117 | } |
118 | |
119 | dap::array<IBreakpoint> DebugModel::getBreakpoints(dap::optional<QUrl> url, dap::optional<int> lineNumber, dap::optional<int> column, dap::optional<bool> enabledOnly) |
120 | { |
121 | dap::array<IBreakpoint> ret; |
122 | dap::string uriStr = url ? url->toString().toStdString() : "" ; |
123 | for (auto it : breakPoints) { |
124 | if ((url && it.uri().toString().toStdString() != uriStr) |
125 | || (lineNumber && lineNumber.value() != it.lineNumber()) |
126 | || (enabledOnly && (!breakpointsActivated || enabledOnly.value() != it.enabled))) { |
127 | continue; |
128 | } |
129 | auto ibp = convertToIBreakpoint(it); |
130 | ret.push_back(ibp); |
131 | } |
132 | return ret; |
133 | } |
134 | |
135 | QMap<QString, dap::array<IBreakpoint>> DebugModel::getAllBreakpoints() |
136 | { |
137 | QMap<QString, dap::array<IBreakpoint>> allBreakpoints; |
138 | for (auto it : breakPoints) { |
139 | auto ibp = convertToIBreakpoint(it); |
140 | QString path = ibp.uri.path(); |
141 | if (allBreakpoints.contains(path)) { |
142 | allBreakpoints[path].push_back(ibp); |
143 | } else { |
144 | allBreakpoints.insert(path, {ibp}); |
145 | } |
146 | } |
147 | return allBreakpoints; |
148 | } |
149 | |
150 | bool DebugModel::areBreakpointsActivated() |
151 | { |
152 | return breakpointsActivated; |
153 | } |
154 | |
155 | dap::array<IFunctionBreakpoint> DebugModel::getFunctionBreakpoints() |
156 | { |
157 | return functionBreakpoints; |
158 | } |
159 | |
160 | dap::array<IDataBreakpoint> DebugModel::getDataBreakpoints() |
161 | { |
162 | return dataBreakpoints; |
163 | } |
164 | |
165 | dap::array<IExceptionBreakpoint> DebugModel::getExceptionBreakpoints() |
166 | { |
167 | return exceptionBreakpoints; |
168 | } |
169 | |
170 | dap::array<IInstructionBreakpoint> DebugModel::getInstructionBreakpoints() |
171 | { |
172 | return instructionBreakpoints; |
173 | } |
174 | |
175 | dap::array<IBreakpoint> DebugModel::addBreakpoints( |
176 | QUrl &uri, dap::array<IBreakpointData> &rawData, bool fireEvent) |
177 | { |
178 | Q_UNUSED(uri) |
179 | Q_UNUSED(fireEvent) |
180 | |
181 | dap::array<IBreakpoint> retBreakpoints; |
182 | for (auto rawBp : rawData) { |
183 | Breakpoint bp(uri, rawBp.lineNumber.value(), rawBp.column, rawBp.enabled, |
184 | rawBp.condition, rawBp.hitCondition, rawBp.logMessage, undefined, rawBp.id.value()); |
185 | auto ibp = convertToIBreakpoint(bp); |
186 | retBreakpoints.push_back(ibp); |
187 | breakPoints.push_back(bp); |
188 | } |
189 | |
190 | return retBreakpoints; |
191 | } |
192 | |
193 | dap::array<IBreakpoint> DebugModel::removeBreakpoint(const QString &filePath, int lineNumber) |
194 | { |
195 | for (auto bp = breakPoints.begin(); bp != breakPoints.end(); ) { |
196 | if (bp->lineNumber() == lineNumber |
197 | && bp->uri().toString() == filePath) { |
198 | bp = breakPoints.erase(bp); |
199 | } else { |
200 | ++bp; |
201 | } |
202 | } |
203 | |
204 | dap::array<IBreakpoint> retBreakpoints; |
205 | for (auto bp : breakPoints) { |
206 | auto ibp = convertToIBreakpoint(bp); |
207 | retBreakpoints.push_back(ibp); |
208 | } |
209 | return retBreakpoints; |
210 | // fire event. |
211 | } |
212 | |
213 | void DebugModel::updateBreakpoints(std::map<dap::string, IBreakpointUpdateData> &data) |
214 | { |
215 | Q_UNUSED(data) |
216 | // dap::array<IBreakpoint> updated; |
217 | // for (auto bp : breakPoints) { |
218 | // auto bpData = data.find(bp.Enablement::getId()); |
219 | // if (bpData != data.end()) { |
220 | // bp.update(bpData->second); |
221 | // updated.push_back(bp); |
222 | // } |
223 | // } |
224 | } |
225 | |
226 | IBreakpointSessionData toBreakpointSessionData(dap::Breakpoint &data, dap::Capabilities &capabilities) |
227 | { |
228 | Q_UNUSED(data) |
229 | Q_UNUSED(capabilities) |
230 | return {}; |
231 | } |
232 | |
233 | void DebugModel::setBreakpointSessionData(dap::string &sessionId, const dap::Capabilities &capabilites, dap::optional<std::map<dap::string, dap::Breakpoint>> data) |
234 | { |
235 | for (auto bp : breakPoints) { |
236 | if (!data) { |
237 | bp.setSessionData(sessionId, undefined); |
238 | } else { |
239 | auto bpData = data.value().find(bp.getId()); |
240 | if (bpData != data->end()) { |
241 | // TODO(mozart):write session data. |
242 | bp.setSessionData(sessionId, undefined); |
243 | } |
244 | } |
245 | } |
246 | } |
247 | |
248 | dap::optional<dap::Breakpoint> DebugModel::getDebugProtocolBreakpoint( |
249 | dap::string &breakpointId, dap::string &sessionId) |
250 | { |
251 | for (auto bp : breakPoints) { |
252 | if (bp.getId() == breakpointId) { |
253 | return bp.getDebugProtocolBreakpoint(sessionId); |
254 | } |
255 | } |
256 | return undefined; |
257 | } |
258 | |
259 | void DebugModel::enableOrDisableAllBreakpoints(bool enable) |
260 | { |
261 | for (auto bp : breakPoints) { |
262 | bp.enabled = enable; |
263 | } |
264 | } |
265 | |
266 | void DebugModel::setBreakpointsActivated(bool activated) |
267 | { |
268 | breakpointsActivated = activated; |
269 | // fire event. |
270 | } |
271 | } // end namespace. |
272 | |