/src/CMake/Source/cmDebuggerExceptionManager.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmDebuggerExceptionManager.h" |
4 | | |
5 | | #include <utility> |
6 | | #include <vector> |
7 | | |
8 | | #include <cm3p/cppdap/optional.h> |
9 | | #include <cm3p/cppdap/session.h> |
10 | | #include <cm3p/cppdap/types.h> |
11 | | |
12 | | #include "cmDebuggerProtocol.h" |
13 | | #include "cmMessageType.h" |
14 | | |
15 | | namespace cmDebugger { |
16 | | |
17 | | cmDebuggerExceptionManager::cmDebuggerExceptionManager( |
18 | | dap::Session* dapSession) |
19 | 0 | : DapSession(dapSession) |
20 | 0 | { |
21 | | // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetExceptionBreakpoints |
22 | 0 | DapSession->registerHandler( |
23 | 0 | [&](dap::SetExceptionBreakpointsRequest const& request) { |
24 | 0 | return HandleSetExceptionBreakpointsRequest(request); |
25 | 0 | }); |
26 | | |
27 | | // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo |
28 | 0 | DapSession->registerHandler([&](dap::ExceptionInfoRequest /*unused*/) { |
29 | 0 | return HandleExceptionInfoRequest(); |
30 | 0 | }); |
31 | |
|
32 | 0 | ExceptionMap[MessageType::FATAL_ERROR] = |
33 | 0 | cmDebuggerExceptionFilter{ "FATAL_ERROR", "Fatal error" }; |
34 | 0 | ExceptionMap[MessageType::INTERNAL_ERROR] = |
35 | 0 | cmDebuggerExceptionFilter{ "INTERNAL_ERROR", "Internal error" }; |
36 | 0 | ExceptionMap[MessageType::MESSAGE] = |
37 | 0 | cmDebuggerExceptionFilter{ "MESSAGE", "Other messages" }; |
38 | 0 | ExceptionMap[MessageType::WARNING] = |
39 | 0 | cmDebuggerExceptionFilter{ "WARNING", "Warning" }; |
40 | 0 | ExceptionMap[MessageType::LOG] = |
41 | 0 | cmDebuggerExceptionFilter{ "LOG", "Debug log" }; |
42 | 0 | RaiseExceptions["FATAL_ERROR"] = true; |
43 | 0 | RaiseExceptions["INTERNAL_ERROR"] = true; |
44 | 0 | } |
45 | | |
46 | | dap::SetExceptionBreakpointsResponse |
47 | | cmDebuggerExceptionManager::HandleSetExceptionBreakpointsRequest( |
48 | | dap::SetExceptionBreakpointsRequest const& request) |
49 | 0 | { |
50 | 0 | std::unique_lock<std::mutex> lock(Mutex); |
51 | 0 | dap::SetExceptionBreakpointsResponse response; |
52 | 0 | RaiseExceptions.clear(); |
53 | 0 | for (auto const& filter : request.filters) { |
54 | 0 | RaiseExceptions[filter] = true; |
55 | 0 | } |
56 | |
|
57 | 0 | return response; |
58 | 0 | } |
59 | | |
60 | | dap::ExceptionInfoResponse |
61 | | cmDebuggerExceptionManager::HandleExceptionInfoRequest() |
62 | 0 | { |
63 | 0 | std::unique_lock<std::mutex> lock(Mutex); |
64 | |
|
65 | 0 | dap::ExceptionInfoResponse response; |
66 | 0 | if (TheException.has_value()) { |
67 | 0 | response.exceptionId = TheException->Id; |
68 | 0 | response.breakMode = "always"; |
69 | 0 | response.description = TheException->Description; |
70 | 0 | TheException = cm::nullopt; |
71 | 0 | } |
72 | 0 | return response; |
73 | 0 | } |
74 | | |
75 | | void cmDebuggerExceptionManager::HandleInitializeRequest( |
76 | | dap::CMakeInitializeResponse& response) |
77 | 0 | { |
78 | 0 | std::unique_lock<std::mutex> lock(Mutex); |
79 | 0 | response.supportsExceptionInfoRequest = true; |
80 | |
|
81 | 0 | dap::array<dap::ExceptionBreakpointsFilter> exceptionBreakpointFilters; |
82 | 0 | for (auto& pair : ExceptionMap) { |
83 | 0 | dap::ExceptionBreakpointsFilter filter; |
84 | 0 | filter.filter = pair.second.Filter; |
85 | 0 | filter.label = pair.second.Label; |
86 | 0 | filter.def = RaiseExceptions[filter.filter]; |
87 | 0 | exceptionBreakpointFilters.emplace_back(filter); |
88 | 0 | } |
89 | |
|
90 | 0 | response.exceptionBreakpointFilters = exceptionBreakpointFilters; |
91 | 0 | } |
92 | | |
93 | | cm::optional<dap::StoppedEvent> |
94 | | cmDebuggerExceptionManager::RaiseExceptionIfAny(MessageType t, |
95 | | std::string const& text) |
96 | 0 | { |
97 | 0 | cm::optional<dap::StoppedEvent> maybeStoppedEvent; |
98 | 0 | std::unique_lock<std::mutex> lock(Mutex); |
99 | 0 | if (RaiseExceptions[ExceptionMap[t].Filter]) { |
100 | 0 | dap::StoppedEvent stoppedEvent; |
101 | 0 | stoppedEvent.allThreadsStopped = true; |
102 | 0 | stoppedEvent.reason = "exception"; |
103 | 0 | stoppedEvent.description = "Pause on exception"; |
104 | 0 | stoppedEvent.text = text; |
105 | 0 | TheException = cmDebuggerException{ ExceptionMap[t].Filter, text }; |
106 | 0 | maybeStoppedEvent = std::move(stoppedEvent); |
107 | 0 | } |
108 | |
|
109 | 0 | return maybeStoppedEvent; |
110 | 0 | } |
111 | | |
112 | | void cmDebuggerExceptionManager::ClearAll() |
113 | 0 | { |
114 | 0 | std::unique_lock<std::mutex> lock(Mutex); |
115 | 0 | RaiseExceptions.clear(); |
116 | 0 | } |
117 | | |
118 | | } // namespace cmDebugger |