| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmDebuggerExceptionManager.h" | |
| #include <utility> | |
| #include <vector> | |
| #include <cm3p/cppdap/optional.h> | |
| #include <cm3p/cppdap/session.h> | |
| #include <cm3p/cppdap/types.h> | |
| #include "cmDebuggerProtocol.h" | |
| #include "cmMessageType.h" | |
| namespace cmDebugger { | |
| cmDebuggerExceptionManager::cmDebuggerExceptionManager( | |
| dap::Session* dapSession) | |
| : DapSession(dapSession) | |
| { | |
| // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_SetExceptionBreakpoints | |
| DapSession->registerHandler( | |
| [&](dap::SetExceptionBreakpointsRequest const& request) { | |
| return HandleSetExceptionBreakpointsRequest(request); | |
| }); | |
| // https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo | |
| DapSession->registerHandler([&](dap::ExceptionInfoRequest /*unused*/) { | |
| return HandleExceptionInfoRequest(); | |
| }); | |
| ExceptionMap[MessageType::FATAL_ERROR] = | |
| cmDebuggerExceptionFilter{ "FATAL_ERROR", "Fatal error" }; | |
| ExceptionMap[MessageType::INTERNAL_ERROR] = | |
| cmDebuggerExceptionFilter{ "INTERNAL_ERROR", "Internal error" }; | |
| ExceptionMap[MessageType::MESSAGE] = | |
| cmDebuggerExceptionFilter{ "MESSAGE", "Other messages" }; | |
| ExceptionMap[MessageType::WARNING] = | |
| cmDebuggerExceptionFilter{ "WARNING", "Warning" }; | |
| ExceptionMap[MessageType::LOG] = | |
| cmDebuggerExceptionFilter{ "LOG", "Debug log" }; | |
| RaiseExceptions["FATAL_ERROR"] = true; | |
| RaiseExceptions["INTERNAL_ERROR"] = true; | |
| } | |
| dap::SetExceptionBreakpointsResponse | |
| cmDebuggerExceptionManager::HandleSetExceptionBreakpointsRequest( | |
| dap::SetExceptionBreakpointsRequest const& request) | |
| { | |
| std::unique_lock<std::mutex> lock(Mutex); | |
| dap::SetExceptionBreakpointsResponse response; | |
| RaiseExceptions.clear(); | |
| for (auto const& filter : request.filters) { | |
| RaiseExceptions[filter] = true; | |
| } | |
| return response; | |
| } | |
| dap::ExceptionInfoResponse | |
| cmDebuggerExceptionManager::HandleExceptionInfoRequest() | |
| { | |
| std::unique_lock<std::mutex> lock(Mutex); | |
| dap::ExceptionInfoResponse response; | |
| if (TheException.has_value()) { | |
| response.exceptionId = TheException->Id; | |
| response.breakMode = "always"; | |
| response.description = TheException->Description; | |
| TheException = cm::nullopt; | |
| } | |
| return response; | |
| } | |
| void cmDebuggerExceptionManager::HandleInitializeRequest( | |
| dap::CMakeInitializeResponse& response) | |
| { | |
| std::unique_lock<std::mutex> lock(Mutex); | |
| response.supportsExceptionInfoRequest = true; | |
| dap::array<dap::ExceptionBreakpointsFilter> exceptionBreakpointFilters; | |
| for (auto& pair : ExceptionMap) { | |
| dap::ExceptionBreakpointsFilter filter; | |
| filter.filter = pair.second.Filter; | |
| filter.label = pair.second.Label; | |
| filter.def = RaiseExceptions[filter.filter]; | |
| exceptionBreakpointFilters.emplace_back(filter); | |
| } | |
| response.exceptionBreakpointFilters = exceptionBreakpointFilters; | |
| } | |
| cm::optional<dap::StoppedEvent> | |
| cmDebuggerExceptionManager::RaiseExceptionIfAny(MessageType t, | |
| std::string const& text) | |
| { | |
| cm::optional<dap::StoppedEvent> maybeStoppedEvent; | |
| std::unique_lock<std::mutex> lock(Mutex); | |
| if (RaiseExceptions[ExceptionMap[t].Filter]) { | |
| dap::StoppedEvent stoppedEvent; | |
| stoppedEvent.allThreadsStopped = true; | |
| stoppedEvent.reason = "exception"; | |
| stoppedEvent.description = "Pause on exception"; | |
| stoppedEvent.text = text; | |
| TheException = cmDebuggerException{ ExceptionMap[t].Filter, text }; | |
| maybeStoppedEvent = std::move(stoppedEvent); | |
| } | |
| return maybeStoppedEvent; | |
| } | |
| void cmDebuggerExceptionManager::ClearAll() | |
| { | |
| std::unique_lock<std::mutex> lock(Mutex); | |
| RaiseExceptions.clear(); | |
| } | |
| } // namespace cmDebugger |