mirror of
https://github.com/Kitware/CMake.git
synced 2025-05-09 23:08:18 +08:00

Add support for the "format" property of the Debug Adapter Protocol StackTrace request to fulfill the host's request to format the resulting StackFrame name differently.
190 lines
5.1 KiB
C++
190 lines
5.1 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
|
|
#include "cmDebuggerThread.h"
|
|
|
|
#include <cstdint>
|
|
#include <utility>
|
|
|
|
#include <cm3p/cppdap/optional.h>
|
|
#include <cm3p/cppdap/types.h>
|
|
|
|
#include "cmDebuggerStackFrame.h"
|
|
#include "cmDebuggerVariables.h"
|
|
#include "cmDebuggerVariablesHelper.h"
|
|
#include "cmDebuggerVariablesManager.h"
|
|
#include "cmListFileCache.h"
|
|
#include "cmStringAlgorithms.h"
|
|
|
|
namespace cmDebugger {
|
|
|
|
cmDebuggerThread::cmDebuggerThread(int64_t id, std::string name)
|
|
: Id(id)
|
|
, Name(std::move(name))
|
|
, VariablesManager(std::make_shared<cmDebuggerVariablesManager>())
|
|
{
|
|
}
|
|
|
|
void cmDebuggerThread::PushStackFrame(cmMakefile* mf,
|
|
std::string const& sourcePath,
|
|
cmListFileFunction const& lff)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Mutex);
|
|
Frames.emplace_back(
|
|
std::make_shared<cmDebuggerStackFrame>(mf, sourcePath, lff));
|
|
FrameMap.insert({ Frames.back()->GetId(), Frames.back() });
|
|
}
|
|
|
|
void cmDebuggerThread::PopStackFrame()
|
|
{
|
|
std::unique_lock<std::mutex> lock(Mutex);
|
|
FrameMap.erase(Frames.back()->GetId());
|
|
FrameScopes.erase(Frames.back()->GetId());
|
|
FrameVariables.erase(Frames.back()->GetId());
|
|
Frames.pop_back();
|
|
}
|
|
|
|
std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetTopStackFrame()
|
|
{
|
|
std::unique_lock<std::mutex> lock(Mutex);
|
|
if (!Frames.empty()) {
|
|
return Frames.back();
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::shared_ptr<cmDebuggerStackFrame> cmDebuggerThread::GetStackFrame(
|
|
int64_t frameId)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Mutex);
|
|
auto it = FrameMap.find(frameId);
|
|
|
|
if (it == FrameMap.end()) {
|
|
return {};
|
|
}
|
|
|
|
return it->second;
|
|
}
|
|
|
|
dap::ScopesResponse cmDebuggerThread::GetScopesResponse(
|
|
int64_t frameId, bool supportsVariableType)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Mutex);
|
|
auto it = FrameScopes.find(frameId);
|
|
|
|
if (it != FrameScopes.end()) {
|
|
dap::ScopesResponse response;
|
|
response.scopes = it->second;
|
|
return response;
|
|
}
|
|
|
|
auto it2 = FrameMap.find(frameId);
|
|
if (it2 == FrameMap.end()) {
|
|
return dap::ScopesResponse();
|
|
}
|
|
|
|
std::shared_ptr<cmDebuggerStackFrame> frame = it2->second;
|
|
std::shared_ptr<cmDebuggerVariables> localVariables =
|
|
cmDebuggerVariablesHelper::Create(VariablesManager, "Locals",
|
|
supportsVariableType, frame);
|
|
|
|
FrameVariables[frameId].emplace_back(localVariables);
|
|
|
|
dap::Scope scope;
|
|
scope.name = localVariables->GetName();
|
|
scope.presentationHint = "locals";
|
|
scope.variablesReference = localVariables->GetId();
|
|
|
|
dap::Source source;
|
|
source.name = frame->GetFileName();
|
|
source.path = source.name;
|
|
scope.source = source;
|
|
|
|
FrameScopes[frameId].push_back(scope);
|
|
|
|
dap::ScopesResponse response;
|
|
response.scopes.push_back(scope);
|
|
return response;
|
|
}
|
|
|
|
dap::VariablesResponse cmDebuggerThread::GetVariablesResponse(
|
|
dap::VariablesRequest const& request)
|
|
{
|
|
std::unique_lock<std::mutex> lock(Mutex);
|
|
dap::VariablesResponse response;
|
|
response.variables = VariablesManager->HandleVariablesRequest(request);
|
|
return response;
|
|
}
|
|
|
|
dap::StackTraceResponse GetStackTraceResponse(
|
|
std::shared_ptr<cmDebuggerThread> const& thread,
|
|
dap::optional<dap::StackFrameFormat> format)
|
|
{
|
|
dap::boolean showParameters = false;
|
|
dap::boolean showParameterValues = false;
|
|
dap::boolean showLine = false;
|
|
if (format.has_value()) {
|
|
auto formatValue = format.value();
|
|
if (formatValue.parameters.has_value()) {
|
|
showParameters = formatValue.parameters.value();
|
|
}
|
|
|
|
if (formatValue.parameterValues.has_value()) {
|
|
showParameterValues = formatValue.parameterValues.value();
|
|
}
|
|
|
|
if (formatValue.line.has_value()) {
|
|
showLine = formatValue.line.value();
|
|
}
|
|
}
|
|
|
|
dap::StackTraceResponse response;
|
|
std::unique_lock<std::mutex> lock(thread->Mutex);
|
|
for (int i = static_cast<int>(thread->Frames.size()) - 1; i >= 0; --i) {
|
|
dap::Source source;
|
|
source.name = thread->Frames[i]->GetFileName();
|
|
source.path = source.name;
|
|
|
|
#ifdef __GNUC__
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Warray-bounds"
|
|
#endif
|
|
dap::StackFrame stackFrame;
|
|
#ifdef __GNUC__
|
|
# pragma GCC diagnostic pop
|
|
#endif
|
|
stackFrame.line = thread->Frames[i]->GetLine();
|
|
stackFrame.column = 1;
|
|
stackFrame.id = thread->Frames[i]->GetId();
|
|
stackFrame.source = source;
|
|
|
|
auto stackName = thread->Frames[i]->GetFunction().OriginalName();
|
|
if (showParameters) {
|
|
stackName.push_back('(');
|
|
if (showParameterValues && !thread->Frames[i]->GetArguments().empty()) {
|
|
for (auto const& arg : thread->Frames[i]->GetArguments()) {
|
|
stackName = cmStrCat(stackName, arg.Value, ", ");
|
|
}
|
|
|
|
stackName.erase(stackName.end() - 2, stackName.end());
|
|
}
|
|
|
|
stackName.push_back(')');
|
|
}
|
|
|
|
if (showLine) {
|
|
stackName =
|
|
cmStrCat(stackName, " Line: ", static_cast<int64_t>(stackFrame.line));
|
|
}
|
|
|
|
stackFrame.name = stackName;
|
|
response.stackFrames.push_back(stackFrame);
|
|
}
|
|
|
|
response.totalFrames = response.stackFrames.size();
|
|
return response;
|
|
}
|
|
|
|
} // namespace cmDebugger
|