blob: 470e44c9dc3335cefd138f453de8a76cbffa4a46 [file] [log] [blame]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt 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(
[&](const dap::SetExceptionBreakpointsRequest& request) {
return HandleSetExceptionBreakpointsRequest(request);
});
// https://microsoft.github.io/debug-adapter-protocol/specification#Requests_ExceptionInfo
DapSession->registerHandler([&](const dap::ExceptionInfoRequest& request) {
(void)request;
return HandleExceptionInfoRequest();
});
ExceptionMap[MessageType::AUTHOR_WARNING] =
cmDebuggerExceptionFilter{ "AUTHOR_WARNING", "Warning (dev)" };
ExceptionMap[MessageType::AUTHOR_ERROR] =
cmDebuggerExceptionFilter{ "AUTHOR_ERROR", "Error (dev)" };
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" };
ExceptionMap[MessageType::DEPRECATION_ERROR] =
cmDebuggerExceptionFilter{ "DEPRECATION_ERROR", "Deprecation error" };
ExceptionMap[MessageType::DEPRECATION_WARNING] =
cmDebuggerExceptionFilter{ "DEPRECATION_WARNING", "Deprecation warning" };
RaiseExceptions["AUTHOR_ERROR"] = true;
RaiseExceptions["FATAL_ERROR"] = true;
RaiseExceptions["INTERNAL_ERROR"] = true;
RaiseExceptions["DEPRECATION_ERROR"] = true;
}
dap::SetExceptionBreakpointsResponse
cmDebuggerExceptionManager::HandleSetExceptionBreakpointsRequest(
dap::SetExceptionBreakpointsRequest const& request)
{
std::unique_lock<std::mutex> lock(Mutex);
dap::SetExceptionBreakpointsResponse response;
RaiseExceptions.clear();
for (const auto& 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