|
8 | 8 |
|
9 | 9 | #include "DAP.h" |
10 | 10 | #include "EventHelper.h" |
11 | | -#include "JSONUtils.h" |
| 11 | +#include "Protocol/ProtocolRequests.h" |
| 12 | +#include "Protocol/ProtocolTypes.h" |
12 | 13 | #include "RequestHandler.h" |
13 | 14 |
|
| 15 | +using namespace llvm; |
| 16 | +using namespace lldb; |
| 17 | +using namespace lldb_dap::protocol; |
| 18 | + |
14 | 19 | namespace lldb_dap { |
15 | 20 |
|
16 | | -// "StepInRequest": { |
17 | | -// "allOf": [ { "$ref": "#/definitions/Request" }, { |
18 | | -// "type": "object", |
19 | | -// "description": "StepIn request; value of command field is 'stepIn'. The |
20 | | -// request starts the debuggee to step into a function/method if possible. |
21 | | -// If it cannot step into a target, 'stepIn' behaves like 'next'. The debug |
22 | | -// adapter first sends the StepInResponse and then a StoppedEvent (event |
23 | | -// type 'step') after the step has completed. If there are multiple |
24 | | -// function/method calls (or other targets) on the source line, the optional |
25 | | -// argument 'targetId' can be used to control into which target the 'stepIn' |
26 | | -// should occur. The list of possible targets for a given source line can be |
27 | | -// retrieved via the 'stepInTargets' request.", "properties": { |
28 | | -// "command": { |
29 | | -// "type": "string", |
30 | | -// "enum": [ "stepIn" ] |
31 | | -// }, |
32 | | -// "arguments": { |
33 | | -// "$ref": "#/definitions/StepInArguments" |
34 | | -// } |
35 | | -// }, |
36 | | -// "required": [ "command", "arguments" ] |
37 | | -// }] |
38 | | -// }, |
39 | | -// "StepInArguments": { |
40 | | -// "type": "object", |
41 | | -// "description": "Arguments for 'stepIn' request.", |
42 | | -// "properties": { |
43 | | -// "threadId": { |
44 | | -// "type": "integer", |
45 | | -// "description": "Execute 'stepIn' for this thread." |
46 | | -// }, |
47 | | -// "targetId": { |
48 | | -// "type": "integer", |
49 | | -// "description": "Optional id of the target to step into." |
50 | | -// }, |
51 | | -// "granularity": { |
52 | | -// "$ref": "#/definitions/SteppingGranularity", |
53 | | -// "description": "Stepping granularity. If no granularity is specified, a |
54 | | -// granularity of `statement` is assumed." |
55 | | -// } |
56 | | -// }, |
57 | | -// "required": [ "threadId" ] |
58 | | -// }, |
59 | | -// "StepInResponse": { |
60 | | -// "allOf": [ { "$ref": "#/definitions/Response" }, { |
61 | | -// "type": "object", |
62 | | -// "description": "Response to 'stepIn' request. This is just an |
63 | | -// acknowledgement, so no body field is required." |
64 | | -// }] |
65 | | -// } |
66 | | -void StepInRequestHandler::operator()(const llvm::json::Object &request) const { |
67 | | - llvm::json::Object response; |
68 | | - FillResponse(request, response); |
69 | | - const auto *arguments = request.getObject("arguments"); |
| 21 | +// The request resumes the given thread to step into a function/method and |
| 22 | +// allows all other threads to run freely by resuming them. If the debug adapter |
| 23 | +// supports single thread execution (see capability |
| 24 | +// `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument |
| 25 | +// to true prevents other suspended threads from resuming. If the request cannot |
| 26 | +// step into a target, `stepIn` behaves like the `next` request. The debug |
| 27 | +// adapter first sends the response and then a `stopped` event (with reason |
| 28 | +// `step`) after the step has completed. If there are multiple function/method |
| 29 | +// calls (or other targets) on the source line, the argument `targetId` can be |
| 30 | +// used to control into which target the `stepIn` should occur. The list of |
| 31 | +// possible targets for a given source line can be retrieved via the |
| 32 | +// `stepInTargets` request. |
| 33 | +Error StepInRequestHandler::Run(const StepInArguments &args) const { |
| 34 | + SBThread thread = dap.GetLLDBThread(args.threadId); |
| 35 | + if (!thread.IsValid()) |
| 36 | + return make_error<DAPError>("invalid thread"); |
| 37 | + |
| 38 | + // Remember the thread ID that caused the resume so we can set the |
| 39 | + // "threadCausedFocus" boolean value in the "stopped" events. |
| 40 | + dap.focus_tid = thread.GetThreadID(); |
| 41 | + |
| 42 | + if (args.granularity == eSteppingGranularityInstruction) { |
| 43 | + thread.StepInstruction(/*step_over=*/false); |
| 44 | + return Error::success(); |
| 45 | + } |
70 | 46 |
|
71 | 47 | std::string step_in_target; |
72 | | - const auto target_id = |
73 | | - GetInteger<uint64_t>(arguments, "targetId").value_or(0); |
74 | | - auto it = dap.step_in_targets.find(target_id); |
| 48 | + auto it = dap.step_in_targets.find(args.targetId.value_or(0)); |
75 | 49 | if (it != dap.step_in_targets.end()) |
76 | 50 | step_in_target = it->second; |
77 | 51 |
|
78 | | - const bool single_thread = |
79 | | - GetBoolean(arguments, "singleThread").value_or(false); |
80 | | - lldb::RunMode run_mode = |
81 | | - single_thread ? lldb::eOnlyThisThread : lldb::eOnlyDuringStepping; |
82 | | - lldb::SBThread thread = dap.GetLLDBThread(*arguments); |
83 | | - if (thread.IsValid()) { |
84 | | - // Remember the thread ID that caused the resume so we can set the |
85 | | - // "threadCausedFocus" boolean value in the "stopped" events. |
86 | | - dap.focus_tid = thread.GetThreadID(); |
87 | | - if (HasInstructionGranularity(*arguments)) { |
88 | | - thread.StepInstruction(/*step_over=*/false); |
89 | | - } else { |
90 | | - thread.StepInto(step_in_target.c_str(), run_mode); |
91 | | - } |
92 | | - } else { |
93 | | - response["success"] = llvm::json::Value(false); |
94 | | - } |
95 | | - dap.SendJSON(llvm::json::Value(std::move(response))); |
| 52 | + RunMode run_mode = args.singleThread ? eOnlyThisThread : eOnlyDuringStepping; |
| 53 | + thread.StepInto(step_in_target.c_str(), run_mode); |
| 54 | + return Error::success(); |
96 | 55 | } |
97 | 56 |
|
98 | 57 | } // namespace lldb_dap |
0 commit comments