diff --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp --- a/lldb/tools/lldb-vscode/JSONUtils.cpp +++ b/lldb/tools/lldb-vscode/JSONUtils.cpp @@ -901,6 +901,8 @@ uint64_t bp_loc_id = thread.GetStopReasonDataAtIndex(1); snprintf(desc_str, sizeof(desc_str), "breakpoint %" PRIu64 ".%" PRIu64, bp_id, bp_loc_id); + body.try_emplace("hitBreakpointIds", + llvm::json::Array{llvm::json::Value(bp_id)}); EmplaceSafeString(body, "description", desc_str); } } break; @@ -945,9 +947,6 @@ EmplaceSafeString(body, "description", std::string(description)); } } - if (tid == g_vsc.focus_tid) { - body.try_emplace("threadCausedFocus", true); - } body.try_emplace("preserveFocusHint", tid != g_vsc.focus_tid); body.try_emplace("allThreadsStopped", true); event.try_emplace("body", std::move(body)); diff --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h --- a/lldb/tools/lldb-vscode/VSCode.h +++ b/lldb/tools/lldb-vscode/VSCode.h @@ -264,7 +264,10 @@ void RegisterRequestCallback(std::string request, RequestCallback callback); /// Debuggee will continue from stopped state. - void WillContinue() { variables.Clear(); } + void WillContinue() { + variables.Clear(); + focus_tid = LLDB_INVALID_THREAD_ID; + } /// Poll the process to wait for it to reach the eStateStopped state. /// diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -191,6 +191,27 @@ g_vsc.SendJSON(llvm::json::Value(std::move(event))); } +// Send a "continued" event to indicate the process is in the running state. +void SendContinuedEvent() { + lldb::SBProcess process = g_vsc.target.GetProcess(); + if (!process.IsValid()) { + return; + } + + // If the focus thread is not set then we haven't reported any thread status + // to the client, so nothing to report. + if (g_vsc.focus_tid == LLDB_INVALID_THREAD_ID) { + return; + } + + llvm::json::Object event(CreateEventObject("continued")); + llvm::json::Object body; + body.try_emplace("threadId", (int64_t)g_vsc.focus_tid); + body.try_emplace("allThreadsContinued", true); + event.try_emplace("body", std::move(body)); + g_vsc.SendJSON(llvm::json::Value(std::move(event))); +} + // Send a "terminated" event to indicate the process is done being // debugged. void SendTerminatedEvent() { @@ -252,7 +273,7 @@ } } - // We will have cleared g_vsc.focus_tid if he focus thread doesn't have + // We will have cleared g_vsc.focus_tid if the focus thread doesn't have // a stop reason, so if it was cleared, or wasn't set, or doesn't exist, // then set the focus thread to the first thread with a stop reason. if (!focus_thread_exists || g_vsc.focus_tid == LLDB_INVALID_THREAD_ID) @@ -468,6 +489,7 @@ break; case lldb::eStateRunning: g_vsc.WillContinue(); + SendContinuedEvent(); break; case lldb::eStateExited: // When restarting, we can get an "exited" event for the process we @@ -766,10 +788,6 @@ llvm::json::Object response; FillResponse(request, response); lldb::SBProcess process = g_vsc.target.GetProcess(); - auto arguments = request.getObject("arguments"); - // Remember the thread ID that caused the resume so we can set the - // "threadCausedFocus" boolean value in the "stopped" events. - g_vsc.focus_tid = GetUnsigned(arguments, "threadId", LLDB_INVALID_THREAD_ID); lldb::SBError error = process.Continue(); llvm::json::Object body; body.try_emplace("allThreadsContinued", true);