/* 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 #include #include #include #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()) { } void cmDebuggerThread::PushStackFrame(cmMakefile* mf, std::string const& sourcePath, cmListFileFunction const& lff) { std::unique_lock lock(Mutex); Frames.emplace_back( std::make_shared(mf, sourcePath, lff)); FrameMap.insert({ Frames.back()->GetId(), Frames.back() }); } void cmDebuggerThread::PopStackFrame() { std::unique_lock lock(Mutex); FrameMap.erase(Frames.back()->GetId()); FrameScopes.erase(Frames.back()->GetId()); FrameVariables.erase(Frames.back()->GetId()); Frames.pop_back(); } std::shared_ptr cmDebuggerThread::GetTopStackFrame() { std::unique_lock lock(Mutex); if (!Frames.empty()) { return Frames.back(); } return {}; } std::shared_ptr cmDebuggerThread::GetStackFrame( int64_t frameId) { std::unique_lock 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 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 frame = it2->second; std::shared_ptr 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 lock(Mutex); dap::VariablesResponse response; response.variables = VariablesManager->HandleVariablesRequest(request); return response; } dap::StackTraceResponse GetStackTraceResponse( std::shared_ptr const& thread, dap::optional 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 lock(thread->Mutex); for (int i = static_cast(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(stackFrame.line)); } stackFrame.name = stackName; response.stackFrames.push_back(stackFrame); } response.totalFrames = response.stackFrames.size(); return response; } } // namespace cmDebugger