Просмотр исходного кода

Merge topic 'debug-adapter-value-formatting'

41621c3afb Debugger: Add Value Formatting support for StackTrace request

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !9940
Brad King 1 год назад
Родитель
Сommit
9fdf716ee8

+ 2 - 1
Source/cmDebuggerAdapter.cxx

@@ -148,6 +148,7 @@ cmDebuggerAdapter::cmDebuggerAdapter(
     SupportsVariableType = req.supportsVariableType.value(false);
     dap::CMakeInitializeResponse response;
     response.supportsConfigurationDoneRequest = true;
+    response.supportsValueFormattingOptions = true;
     response.cmakeVersion.major = CMake_VERSION_MAJOR;
     response.cmakeVersion.minor = CMake_VERSION_MINOR;
     response.cmakeVersion.patch = CMake_VERSION_PATCH;
@@ -186,7 +187,7 @@ cmDebuggerAdapter::cmDebuggerAdapter(
     std::unique_lock<std::mutex> lock(Mutex);
 
     cm::optional<dap::StackTraceResponse> response =
-      ThreadManager->GetThreadStackTraceResponse(request.threadId);
+      ThreadManager->GetThreadStackTraceResponse(request);
     if (response.has_value()) {
       return response.value();
     }

+ 6 - 0
Source/cmDebuggerStackFrame.cxx

@@ -25,4 +25,10 @@ int64_t cmDebuggerStackFrame::GetLine() const noexcept
   return this->Function.Line();
 }
 
+std::vector<cmListFileArgument> const& cmDebuggerStackFrame::GetArguments()
+  const noexcept
+{
+  return this->Function.Arguments();
+}
+
 } // namespace cmDebugger

+ 3 - 0
Source/cmDebuggerStackFrame.h

@@ -7,8 +7,10 @@
 #include <atomic>
 #include <cstdint>
 #include <string>
+#include <vector>
 
 class cmListFileFunction;
+struct cmListFileArgument;
 class cmMakefile;
 
 namespace cmDebugger {
@@ -32,6 +34,7 @@ public:
   {
     return this->Function;
   }
+  std::vector<cmListFileArgument> const& GetArguments() const noexcept;
 };
 
 } // namespace cmDebugger

+ 41 - 2
Source/cmDebuggerThread.cxx

@@ -14,6 +14,7 @@
 #include "cmDebuggerVariablesHelper.h"
 #include "cmDebuggerVariablesManager.h"
 #include "cmListFileCache.h"
+#include "cmStringAlgorithms.h"
 
 namespace cmDebugger {
 
@@ -117,8 +118,27 @@ dap::VariablesResponse cmDebuggerThread::GetVariablesResponse(
 }
 
 dap::StackTraceResponse GetStackTraceResponse(
-  std::shared_ptr<cmDebuggerThread> const& thread)
+  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) {
@@ -136,10 +156,29 @@ dap::StackTraceResponse GetStackTraceResponse(
 #endif
     stackFrame.line = thread->Frames[i]->GetLine();
     stackFrame.column = 1;
-    stackFrame.name = thread->Frames[i]->GetFunction().OriginalName();
     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);
   }
 

+ 7 - 1
Source/cmDebuggerThread.h

@@ -23,6 +23,11 @@ class cmDebuggerVariables;
 class cmDebuggerVariablesManager;
 }
 
+namespace dap {
+template <typename T>
+class optional;
+}
+
 namespace cmDebugger {
 
 class cmDebuggerThread
@@ -53,7 +58,8 @@ public:
   dap::VariablesResponse GetVariablesResponse(
     dap::VariablesRequest const& request);
   friend dap::StackTraceResponse GetStackTraceResponse(
-    std::shared_ptr<cmDebuggerThread> const& thread);
+    std::shared_ptr<cmDebuggerThread> const& thread,
+    dap::optional<dap::StackFrameFormat> format);
 };
 
 } // namespace cmDebugger

+ 5 - 3
Source/cmDebuggerThreadManager.cxx

@@ -6,6 +6,7 @@
 #include <algorithm>
 
 #include <cm3p/cppdap/protocol.h>
+#include <cm3p/cppdap/types.h>
 
 #include "cmDebuggerThread.h"
 
@@ -30,18 +31,19 @@ void cmDebuggerThreadManager::EndThread(
 }
 
 cm::optional<dap::StackTraceResponse>
-cmDebuggerThreadManager::GetThreadStackTraceResponse(int64_t id)
+cmDebuggerThreadManager::GetThreadStackTraceResponse(
+  const dap::StackTraceRequest& request)
 {
   auto it = find_if(Threads.begin(), Threads.end(),
                     [&](const std::shared_ptr<cmDebuggerThread>& t) {
-                      return t->GetId() == id;
+                      return t->GetId() == request.threadId;
                     });
 
   if (it == Threads.end()) {
     return {};
   }
 
-  return GetStackTraceResponse(*it);
+  return GetStackTraceResponse(*it, request.format);
 }
 
 } // namespace cmDebugger

+ 2 - 1
Source/cmDebuggerThreadManager.h

@@ -17,6 +17,7 @@ class cmDebuggerThread;
 }
 
 namespace dap {
+struct StackTraceRequest;
 struct StackTraceResponse;
 }
 
@@ -32,7 +33,7 @@ public:
   std::shared_ptr<cmDebuggerThread> StartThread(std::string const& name);
   void EndThread(std::shared_ptr<cmDebuggerThread> const& thread);
   cm::optional<dap::StackTraceResponse> GetThreadStackTraceResponse(
-    std::int64_t id);
+    const dap::StackTraceRequest& request);
 };
 
 } // namespace cmDebugger

+ 1 - 0
Tests/CMakeLib/testDebuggerAdapter.cxx

@@ -132,6 +132,7 @@ bool runTest(std::function<bool(dap::Session&)> onThreadExitedEvent)
   ASSERT_TRUE(initializeResponse.response.supportsExceptionInfoRequest);
   ASSERT_TRUE(
     initializeResponse.response.exceptionBreakpointFilters.has_value());
+  ASSERT_TRUE(initializeResponse.response.supportsValueFormattingOptions);
 
   dap::LaunchRequest launchRequest;
   auto launchResponse = client->send(launchRequest).get();

+ 37 - 5
Tests/CMakeLib/testDebuggerThread.cxx

@@ -2,6 +2,7 @@
 #include <string>
 #include <vector>
 
+#include <cm3p/cppdap/optional.h>
 #include <cm3p/cppdap/protocol.h>
 #include <cm3p/cppdap/types.h>
 
@@ -10,21 +11,52 @@
 
 #include "testCommon.h"
 
-static bool testStackFrameFunctionName()
+static bool testStackFrameFunctionName(
+  dap::optional<dap::StackFrameFormat> format, const char* expectedName)
 {
   auto thread = std::make_shared<cmDebugger::cmDebuggerThread>(0, "name");
   const auto* functionName = "function_name";
-  auto arguments = std::vector<cmListFileArgument>{};
+  auto arguments = std::vector<cmListFileArgument>{ cmListFileArgument(
+    "arg", cmListFileArgument::Delimiter::Unquoted, 0) };
   cmListFileFunction func(functionName, 10, 20, arguments);
   thread->PushStackFrame(nullptr, "CMakeLists.txt", func);
 
-  auto stackTrace = GetStackTraceResponse(thread);
+  auto stackTrace = GetStackTraceResponse(thread, format);
 
-  ASSERT_TRUE(stackTrace.stackFrames[0].name == functionName);
+  ASSERT_TRUE(stackTrace.stackFrames[0].name == expectedName);
   return true;
 }
 
+bool testStackFrameNoFormatting()
+{
+  return testStackFrameFunctionName({}, "function_name");
+}
+
+bool testStackFrameFormatParameters()
+{
+  dap::StackFrameFormat format;
+  format.parameters = true;
+  return testStackFrameFunctionName(format, "function_name()");
+}
+
+bool testStackFrameFormatParameterValues()
+{
+  dap::StackFrameFormat format;
+  format.parameters = true;
+  format.parameterValues = true;
+  return testStackFrameFunctionName(format, "function_name(arg)");
+}
+
+bool testStackFrameFormatLine()
+{
+  dap::StackFrameFormat format;
+  format.line = true;
+  return testStackFrameFunctionName(format, "function_name Line: 10");
+}
+
 int testDebuggerThread(int, char*[])
 {
-  return runTests({ testStackFrameFunctionName });
+  return runTests({ testStackFrameNoFormatting, testStackFrameFormatParameters,
+                    testStackFrameFormatParameterValues,
+                    testStackFrameFormatLine });
 }