- Migrate set breakpoint requests to use typed RequestHandler - `SetBreakpointsRequestHandler` - `SetDataBreakpointsRequestHandler` - `SetFunctionBreakpointsRequestHandler` - `SetInstructionBreakpointsRequestHandler` - `DataBreakpointInfoRequestHandler` - Decouple JSON from lldb-dap `Breakpoint` classes
80 lines
3.0 KiB
C++
80 lines
3.0 KiB
C++
//===-- SetBreakpointsRequestHandler.cpp ----------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "DAP.h"
|
|
#include "EventHelper.h"
|
|
#include "JSONUtils.h"
|
|
#include "Protocol/ProtocolRequests.h"
|
|
#include "RequestHandler.h"
|
|
#include <vector>
|
|
|
|
namespace lldb_dap {
|
|
|
|
/// Sets multiple breakpoints for a single source and clears all previous
|
|
/// breakpoints in that source. To clear all breakpoint for a source, specify an
|
|
/// empty array. When a breakpoint is hit, a `stopped` event (with reason
|
|
/// `breakpoint`) is generated.
|
|
llvm::Expected<protocol::SetBreakpointsResponseBody>
|
|
SetBreakpointsRequestHandler::Run(
|
|
const protocol::SetBreakpointsArguments &args) const {
|
|
const auto &source = args.source;
|
|
const auto path = source.path.value_or("");
|
|
std::vector<protocol::Breakpoint> response_breakpoints;
|
|
|
|
// Decode the source breakpoint infos for this "setBreakpoints" request
|
|
SourceBreakpointMap request_bps;
|
|
// "breakpoints" may be unset, in which case we treat it the same as being set
|
|
// to an empty array.
|
|
if (args.breakpoints) {
|
|
for (const auto &bp : *args.breakpoints) {
|
|
SourceBreakpoint src_bp(dap, bp);
|
|
std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(),
|
|
src_bp.GetColumn());
|
|
request_bps.try_emplace(bp_pos, src_bp);
|
|
const auto [iv, inserted] =
|
|
dap.source_breakpoints[path].try_emplace(bp_pos, src_bp);
|
|
// We check if this breakpoint already exists to update it
|
|
if (inserted)
|
|
iv->getSecond().SetBreakpoint(path.data());
|
|
else
|
|
iv->getSecond().UpdateBreakpoint(src_bp);
|
|
|
|
protocol::Breakpoint response_bp = iv->getSecond().ToProtocolBreakpoint();
|
|
|
|
// Use the path from the request if it is set
|
|
if (!path.empty())
|
|
response_bp.source = CreateSource(path);
|
|
|
|
if (!response_bp.line)
|
|
response_bp.line = src_bp.GetLine();
|
|
if (!response_bp.column)
|
|
response_bp.column = src_bp.GetColumn();
|
|
response_breakpoints.push_back(response_bp);
|
|
}
|
|
}
|
|
|
|
// Delete any breakpoints in this source file that aren't in the
|
|
// request_bps set. There is no call to remove breakpoints other than
|
|
// calling this function with a smaller or empty "breakpoints" list.
|
|
auto old_src_bp_pos = dap.source_breakpoints.find(path);
|
|
if (old_src_bp_pos != dap.source_breakpoints.end()) {
|
|
for (auto &old_bp : old_src_bp_pos->second) {
|
|
auto request_pos = request_bps.find(old_bp.first);
|
|
if (request_pos == request_bps.end()) {
|
|
// This breakpoint no longer exists in this source file, delete it
|
|
dap.target.BreakpointDelete(old_bp.second.GetID());
|
|
old_src_bp_pos->second.erase(old_bp.first);
|
|
}
|
|
}
|
|
}
|
|
|
|
return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
|
|
}
|
|
|
|
} // namespace lldb_dap
|