| //===-- SetFunctionBreakpointsRequestHandler.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 "RequestHandler.h" |
| |
| namespace lldb_dap { |
| |
| // "SetFunctionBreakpointsRequest": { |
| // "allOf": [ { "$ref": "#/definitions/Request" }, { |
| // "type": "object", |
| // "description": "SetFunctionBreakpoints request; value of command field is |
| // 'setFunctionBreakpoints'. Sets multiple function breakpoints and clears |
| // all previous function breakpoints. To clear all function breakpoint, |
| // specify an empty array. When a function breakpoint is hit, a StoppedEvent |
| // (event type 'function breakpoint') is generated.", "properties": { |
| // "command": { |
| // "type": "string", |
| // "enum": [ "setFunctionBreakpoints" ] |
| // }, |
| // "arguments": { |
| // "$ref": "#/definitions/SetFunctionBreakpointsArguments" |
| // } |
| // }, |
| // "required": [ "command", "arguments" ] |
| // }] |
| // }, |
| // "SetFunctionBreakpointsArguments": { |
| // "type": "object", |
| // "description": "Arguments for 'setFunctionBreakpoints' request.", |
| // "properties": { |
| // "breakpoints": { |
| // "type": "array", |
| // "items": { |
| // "$ref": "#/definitions/FunctionBreakpoint" |
| // }, |
| // "description": "The function names of the breakpoints." |
| // } |
| // }, |
| // "required": [ "breakpoints" ] |
| // }, |
| // "FunctionBreakpoint": { |
| // "type": "object", |
| // "description": "Properties of a breakpoint passed to the |
| // setFunctionBreakpoints request.", "properties": { |
| // "name": { |
| // "type": "string", |
| // "description": "The name of the function." |
| // }, |
| // "condition": { |
| // "type": "string", |
| // "description": "An optional expression for conditional breakpoints." |
| // }, |
| // "hitCondition": { |
| // "type": "string", |
| // "description": "An optional expression that controls how many hits of |
| // the breakpoint are ignored. The backend is expected to interpret the |
| // expression as needed." |
| // } |
| // }, |
| // "required": [ "name" ] |
| // }, |
| // "SetFunctionBreakpointsResponse": { |
| // "allOf": [ { "$ref": "#/definitions/Response" }, { |
| // "type": "object", |
| // "description": "Response to 'setFunctionBreakpoints' request. Returned is |
| // information about each breakpoint created by this request.", |
| // "properties": { |
| // "body": { |
| // "type": "object", |
| // "properties": { |
| // "breakpoints": { |
| // "type": "array", |
| // "items": { |
| // "$ref": "#/definitions/Breakpoint" |
| // }, |
| // "description": "Information about the breakpoints. The array |
| // elements correspond to the elements of the 'breakpoints' array." |
| // } |
| // }, |
| // "required": [ "breakpoints" ] |
| // } |
| // }, |
| // "required": [ "body" ] |
| // }] |
| // } |
| void SetFunctionBreakpointsRequestHandler::operator()( |
| const llvm::json::Object &request) const { |
| llvm::json::Object response; |
| lldb::SBError error; |
| FillResponse(request, response); |
| const auto *arguments = request.getObject("arguments"); |
| const auto *breakpoints = arguments->getArray("breakpoints"); |
| llvm::json::Array response_breakpoints; |
| |
| // Disable any function breakpoints that aren't in this request. |
| // There is no call to remove function breakpoints other than calling this |
| // function with a smaller or empty "breakpoints" list. |
| const auto name_iter = dap.function_breakpoints.keys(); |
| llvm::DenseSet<llvm::StringRef> seen(name_iter.begin(), name_iter.end()); |
| for (const auto &value : *breakpoints) { |
| const auto *bp_obj = value.getAsObject(); |
| if (!bp_obj) |
| continue; |
| FunctionBreakpoint fn_bp(dap, *bp_obj); |
| const auto [it, inserted] = dap.function_breakpoints.try_emplace( |
| fn_bp.GetFunctionName(), dap, *bp_obj); |
| if (inserted) |
| it->second.SetBreakpoint(); |
| else |
| it->second.UpdateBreakpoint(fn_bp); |
| |
| AppendBreakpoint(&it->second, response_breakpoints); |
| seen.erase(fn_bp.GetFunctionName()); |
| } |
| |
| // Remove any breakpoints that are no longer in our list |
| for (const auto &name : seen) { |
| auto fn_bp = dap.function_breakpoints.find(name); |
| if (fn_bp == dap.function_breakpoints.end()) |
| continue; |
| dap.target.BreakpointDelete(fn_bp->second.GetID()); |
| dap.function_breakpoints.erase(name); |
| } |
| |
| llvm::json::Object body; |
| body.try_emplace("breakpoints", std::move(response_breakpoints)); |
| response.try_emplace("body", std::move(body)); |
| dap.SendJSON(llvm::json::Value(std::move(response))); |
| } |
| |
| } // namespace lldb_dap |