[Lldb-commits] [lldb] 78af051 - Revert "[lldb-vscode] Creating a new flag for adjusting the behavior of evaluation repl expressions to allow users to more easily invoke lldb commands."

Shubham Sandeep Rastogi via lldb-commits lldb-commits at lists.llvm.org
Tue Jul 11 15:16:17 PDT 2023


Author: Shubham Sandeep Rastogi
Date: 2023-07-11T15:16:03-07:00
New Revision: 78af051ff0e16db73201b1370e34206a6a4c1b93

URL: https://github.com/llvm/llvm-project/commit/78af051ff0e16db73201b1370e34206a6a4c1b93
DIFF: https://github.com/llvm/llvm-project/commit/78af051ff0e16db73201b1370e34206a6a4c1b93.diff

LOG: Revert "[lldb-vscode] Creating a new flag for adjusting the behavior of evaluation repl expressions to allow users to more easily invoke lldb commands."

This reverts commit 16317f1ced77e1d8711188f2fcc6c86a783d9c56.

Reverting because of test failures:

******************** TEST 'lldb-api :: tools/lldb-vscode/console/TestVSCode_console.py' FAILED ********************
Script:
--
/usr/local/Frameworks/Python.framework/Versions/3.10/bin/python3.10 /Users/buildslave/jenkins/workspace/lldb-cmake/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --codesign-identity lldb_codesign --env LLVM_LIBS_DIR=/Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./lib --env LLVM_INCLUDE_DIR=/Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/include --env LLVM_TOOLS_DIR=/Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./bin --libcxx-include-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/include/c++/v1 --libcxx-library-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/lib --arch x86_64 --build-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/lldb-test-build.noindex --lldb-module-cache-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./bin/lldb --compiler /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./bin/clang --dsymutil /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./bin/dsymutil --llvm-tools-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./bin --lldb-libs-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/./lib --build-dir /Users/buildslave/jenkins/workspace/lldb-cmake/lldb-build/lldb-test-build.noindex -t --env TERM=vt100 /Users/buildslave/jenkins/workspace/lldb-cmake/llvm-project/lldb/test/API/tools/lldb-vscode/console -p TestVSCode_console.py

https://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/57586/

Added: 
    

Modified: 
    lldb/tools/lldb-vscode/Options.td
    lldb/tools/lldb-vscode/README.md
    lldb/tools/lldb-vscode/VSCode.cpp
    lldb/tools/lldb-vscode/VSCode.h
    lldb/tools/lldb-vscode/lldb-vscode.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/tools/lldb-vscode/Options.td b/lldb/tools/lldb-vscode/Options.td
index 8c51a994ebc270..a73671ad749c47 100644
--- a/lldb/tools/lldb-vscode/Options.td
+++ b/lldb/tools/lldb-vscode/Options.td
@@ -39,7 +39,3 @@ def debugger_pid: Separate<["--", "-"], "debugger-pid">,
   MetaVarName<"<pid>">,
   HelpText<"The PID of the lldb-vscode instance that sent the launchInTerminal "
     "request when using --launch-target.">;
-
-def repl_mode: S<"repl-mode">,
-  MetaVarName<"<mode>">,
-  HelpText<"The mode for handling repl evaluation requests, supported modes: variable, command, auto.">;

diff  --git a/lldb/tools/lldb-vscode/README.md b/lldb/tools/lldb-vscode/README.md
index 154ccefc5f5979..cd249ed2fac7c6 100644
--- a/lldb/tools/lldb-vscode/README.md
+++ b/lldb/tools/lldb-vscode/README.md
@@ -236,22 +236,3 @@ This will launch a server and then request a child debug session for a client.
   ]
 }
 ```
-
-## repl-mode
-
-Inspect or adjust the behavior of lldb-vscode repl evaluation requests. The
-supported modes are `variable`, `command` and `auto`.
-
-*  `variable` - Variable mode expressions are evaluated in the context of the
-   current frame. Use a `\`` prefix on the command to run an lldb command.
-*  `command` - Command mode expressions are evaluated as lldb commands, as a
-   result, values printed by lldb are always stringified representations of the
-   expression output.
-*  `auto` - Auto mode will attempt to infer if the expression represents an lldb
-   command or a variable expression. A heuristic is used to infer if the input
-   represents a variable or a command. Use a `\`` prefix to ensure an expression
-   is evaluated as a command.
-
-The initial repl-mode can be configured with the cli flag `--repl-mode=<mode>`
-and may also be adjusted at runtime using the lldb command
-`lldb-vscode repl-mode <mode>`.

diff  --git a/lldb/tools/lldb-vscode/VSCode.cpp b/lldb/tools/lldb-vscode/VSCode.cpp
index f007e09eee1e1d..b1c6817c2128b9 100644
--- a/lldb/tools/lldb-vscode/VSCode.cpp
+++ b/lldb/tools/lldb-vscode/VSCode.cpp
@@ -44,8 +44,7 @@ VSCode::VSCode()
       configuration_done_sent(false), waiting_for_run_in_terminal(false),
       progress_event_reporter(
           [&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }),
-      reverse_request_seq(0), repl_mode(ReplMode::Auto),
-      auto_repl_mode_collision_warning(false) {
+      reverse_request_seq(0) {
   const char *log_file_path = getenv("LLDBVSCODE_LOG");
 #if defined(_WIN32)
   // Windows opens stdout and stdin in text mode which converts \n to 13,10
@@ -393,50 +392,6 @@ llvm::json::Value VSCode::CreateTopLevelScopes() {
   return llvm::json::Value(std::move(scopes));
 }
 
-ExpressionContext VSCode::DetectExpressionContext(lldb::SBFrame &frame,
-                                                  std::string &text) {
-  // Include ` as an escape hatch.
-  if (!text.empty() && text[0] == '`') {
-    text = text.substr(1);
-    return ExpressionContext::Command;
-  }
-
-  switch (repl_mode) {
-  case ReplMode::Variable:
-    return ExpressionContext::Variable;
-  case ReplMode::Command:
-    return ExpressionContext::Command;
-  case ReplMode::Auto:
-    if (!frame.IsValid()) {
-      return ExpressionContext::Command;
-    }
-
-    lldb::SBValue value =
-        frame.GetValueForVariablePath(text.data(), lldb::eDynamicDontRunTarget);
-
-    lldb::SBCommandReturnObject result;
-    debugger.GetCommandInterpreter().ResolveCommand(text.data(), result);
-
-    if (value.GetError().Success()) {
-      // Check if the expression is both a local variable and an lldb command.
-      if (result.Succeeded() && !auto_repl_mode_collision_warning) {
-        llvm::errs() << "Variable expression '" << text
-                     << "' is hiding an lldb command, prefix an expression "
-                        "with ` to ensure it runs as a lldb command.\n";
-        auto_repl_mode_collision_warning = true;
-      }
-
-      return ExpressionContext::Variable;
-    }
-
-    if (result.Succeeded()) {
-      return ExpressionContext::Command;
-    }
-
-    return ExpressionContext::Variable;
-  }
-}
-
 void VSCode::RunLLDBCommands(llvm::StringRef prefix,
                              const std::vector<std::string> &commands) {
   SendOutput(OutputType::Console,
@@ -546,8 +501,7 @@ bool VSCode::HandleObject(const llvm::json::Object &object) {
       return true; // Success
     } else {
       if (log)
-        *log << "error: unhandled command \"" << command.data() << "\""
-             << std::endl;
+        *log << "error: unhandled command \"" << command.data() << std::endl;
       return false; // Fail
     }
   }
@@ -682,7 +636,7 @@ void Variables::Clear() {
   expandable_variables.clear();
 }
 
-int64_t Variables::GetNewVariableReference(bool is_permanent) {
+int64_t Variables::GetNewVariableRefence(bool is_permanent) {
   if (is_permanent)
     return next_permanent_var_ref++;
   return next_temporary_var_ref++;
@@ -707,7 +661,7 @@ lldb::SBValue Variables::GetVariable(int64_t var_ref) const {
 
 int64_t Variables::InsertExpandableVariable(lldb::SBValue variable,
                                             bool is_permanent) {
-  int64_t var_ref = GetNewVariableReference(is_permanent);
+  int64_t var_ref = GetNewVariableRefence(is_permanent);
   if (is_permanent)
     expandable_permanent_variables.insert(std::make_pair(var_ref, variable));
   else
@@ -774,51 +728,4 @@ bool StartDebuggingRequestHandler::DoExecute(
   return true;
 }
 
-bool ReplModeRequestHandler::DoExecute(lldb::SBDebugger debugger,
-                                       char **command,
-                                       lldb::SBCommandReturnObject &result) {
-  // Command format like: `repl-mode <variable|command|auto>?`
-  // If a new mode is not specified report the current mode.
-  if (!command || llvm::StringRef(command[0]).empty()) {
-    std::string mode;
-    switch (g_vsc.repl_mode) {
-    case ReplMode::Variable:
-      mode = "variable";
-      break;
-    case ReplMode::Command:
-      mode = "command";
-      break;
-    case ReplMode::Auto:
-      mode = "auto";
-      break;
-    }
-
-    result.Printf("lldb-vscode repl-mode %s.\n", mode.c_str());
-    result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
-
-    return true;
-  }
-
-  llvm::StringRef new_mode{command[0]};
-
-  if (new_mode == "variable") {
-    g_vsc.repl_mode = ReplMode::Variable;
-  } else if (new_mode == "command") {
-    g_vsc.repl_mode = ReplMode::Command;
-  } else if (new_mode == "auto") {
-    g_vsc.repl_mode = ReplMode::Auto;
-  } else {
-    lldb::SBStream error_message;
-    error_message.Printf("Invalid repl-mode '%s'. Expected one of 'variable', "
-                         "'command' or 'auto'.\n",
-                         new_mode.data());
-    result.SetError(error_message.GetData());
-    return false;
-  }
-
-  result.Printf("lldb-vscode repl-mode %s set.\n", new_mode.data());
-  result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
-  return true;
-}
-
 } // namespace lldb_vscode

diff  --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h
index 4a2779fa4972a8..2d67da2bbc092e 100644
--- a/lldb/tools/lldb-vscode/VSCode.h
+++ b/lldb/tools/lldb-vscode/VSCode.h
@@ -84,14 +84,6 @@ enum class PacketStatus {
   JSONNotObject
 };
 
-enum class ReplMode { Variable = 0, Command, Auto };
-
-/// The detected context of an expression based off the current repl mode.
-enum class ExpressionContext {
-  Variable = 0,
-  Command,
-};
-
 struct Variables {
   /// Variable_reference start index of permanent expandable variable.
   static constexpr int64_t PermanentVariableStartIndex = (1ll << 32);
@@ -117,7 +109,7 @@ struct Variables {
   /// \return a new variableReference.
   /// Specify is_permanent as true for variable that should persist entire
   /// debug session.
-  int64_t GetNewVariableReference(bool is_permanent);
+  int64_t GetNewVariableRefence(bool is_permanent);
 
   /// \return the expandable variable corresponding with variableReference
   /// value of \p value.
@@ -137,11 +129,6 @@ struct StartDebuggingRequestHandler : public lldb::SBCommandPluginInterface {
                  lldb::SBCommandReturnObject &result) override;
 };
 
-struct ReplModeRequestHandler : public lldb::SBCommandPluginInterface {
-  bool DoExecute(lldb::SBDebugger debugger, char **command,
-                 lldb::SBCommandReturnObject &result) override;
-};
-
 struct VSCode {
   std::string debug_adaptor_path;
   InputStream input;
@@ -186,9 +173,6 @@ struct VSCode {
   std::map<int /* request_seq */, ResponseCallback /* reply handler */>
       inflight_reverse_requests;
   StartDebuggingRequestHandler start_debugging_request_handler;
-  ReplModeRequestHandler repl_mode_request_handler;
-  ReplMode repl_mode;
-  bool auto_repl_mode_collision_warning;
 
   VSCode();
   ~VSCode();
@@ -222,9 +206,6 @@ struct VSCode {
 
   llvm::json::Value CreateTopLevelScopes();
 
-  ExpressionContext DetectExpressionContext(lldb::SBFrame &frame,
-                                            std::string &text);
-
   void RunLLDBCommands(llvm::StringRef prefix,
                        const std::vector<std::string> &commands);
 

diff  --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 8f82ab8e2e3e16..5815b0d22506b3 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -1065,63 +1065,50 @@ void request_completions(const llvm::json::Object &request) {
   FillResponse(request, response);
   llvm::json::Object body;
   auto arguments = request.getObject("arguments");
-
-  // If we have a frame, try to set the context for variable completions.
-  lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
-  if (frame.IsValid()) {
-    frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
-    frame.GetThread().SetSelectedFrame(frame.GetFrameID());
-  }
-
   std::string text = std::string(GetString(arguments, "text"));
   auto original_column = GetSigned(arguments, "column", text.size());
-  auto original_line = GetSigned(arguments, "line", 1);
-  auto offset = original_column - 1;
-  if (original_line > 1) {
-    llvm::StringRef text_ref{text};
-    ::llvm::SmallVector<::llvm::StringRef, 2> lines;
-    text_ref.split(lines, '\n');
-    for (int i = 0; i < original_line - 1; i++) {
-      offset += lines[i].size();
-    }
-  }
+  auto actual_column = original_column - 1;
   llvm::json::Array targets;
-
-  if (g_vsc.DetectExpressionContext(frame, text) ==
-      ExpressionContext::Variable) {
-    char command[] = "frame variable ";
+  // NOTE: the 'line' argument is not needed, as multiline expressions
+  // work well already
+  // TODO: support frameID. Currently
+  // g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions
+  // is frame-unaware.
+
+  if (!text.empty() && text[0] == '`') {
+    text = text.substr(1);
+    actual_column--;
+  } else {
+    char command[] = "expression -- ";
     text = command + text;
-    offset += strlen(command);
+    actual_column += strlen(command);
   }
   lldb::SBStringList matches;
   lldb::SBStringList descriptions;
-
-  if (g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
-          text.c_str(), offset, 0, 100, matches, descriptions)) {
-    // The first element is the common substring after the cursor position for
-    // all the matches. The rest of the elements are the matches.
-    targets.reserve(matches.GetSize() - 1);
-    std::string common_pattern = matches.GetStringAtIndex(0);
-    for (size_t i = 1; i < matches.GetSize(); i++) {
-      std::string match = matches.GetStringAtIndex(i);
-      std::string description = descriptions.GetStringAtIndex(i);
-
-      llvm::json::Object item;
-      llvm::StringRef match_ref = match;
-      for (llvm::StringRef commit_point : {".", "->"}) {
-        if (match_ref.contains(commit_point)) {
-          match_ref = match_ref.rsplit(commit_point).second;
-        }
+  g_vsc.debugger.GetCommandInterpreter().HandleCompletionWithDescriptions(
+      text.c_str(), actual_column, 0, -1, matches, descriptions);
+  size_t count = std::min((uint32_t)100, matches.GetSize());
+  targets.reserve(count);
+  for (size_t i = 0; i < count; i++) {
+    std::string match = matches.GetStringAtIndex(i);
+    std::string description = descriptions.GetStringAtIndex(i);
+
+    llvm::json::Object item;
+
+    llvm::StringRef match_ref = match;
+    for (llvm::StringRef commit_point : {".", "->"}) {
+      if (match_ref.contains(commit_point)) {
+        match_ref = match_ref.rsplit(commit_point).second;
       }
-      EmplaceSafeString(item, "text", match_ref);
+    }
+    EmplaceSafeString(item, "text", match_ref);
 
-      if (description.empty())
-        EmplaceSafeString(item, "label", match);
-      else
-        EmplaceSafeString(item, "label", match + " -- " + description);
+    if (description.empty())
+      EmplaceSafeString(item, "label", match);
+    else
+      EmplaceSafeString(item, "label", match + " -- " + description);
 
-      targets.emplace_back(std::move(item));
-    }
+    targets.emplace_back(std::move(item));
   }
 
   body.try_emplace("targets", std::move(targets));
@@ -1236,17 +1223,12 @@ void request_evaluate(const llvm::json::Object &request) {
   llvm::json::Object body;
   auto arguments = request.getObject("arguments");
   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
-  std::string expression = GetString(arguments, "expression").str();
+  const auto expression = GetString(arguments, "expression");
   llvm::StringRef context = GetString(arguments, "context");
 
-  if (context == "repl" && g_vsc.DetectExpressionContext(frame, expression) ==
-                               ExpressionContext::Command) {
-    // If we're evaluating a command relative to the current frame, set the
-    // focus_tid to the current frame for any thread related events.
-    if (frame.IsValid()) {
-      g_vsc.focus_tid = frame.GetThread().GetThreadID();
-    }
-    auto result = RunLLDBCommands(llvm::StringRef(), {std::string(expression)});
+  if (!expression.empty() && expression[0] == '`') {
+    auto result =
+        RunLLDBCommands(llvm::StringRef(), {std::string(expression.substr(1))});
     EmplaceSafeString(body, "result", result);
     body.try_emplace("variablesReference", (int64_t)0);
   } else {
@@ -1490,17 +1472,11 @@ void request_initialize(const llvm::json::Object &request) {
   g_vsc.debugger =
       lldb::SBDebugger::Create(source_init_file, log_cb, nullptr);
   auto cmd = g_vsc.debugger.GetCommandInterpreter().AddMultiwordCommand(
-      "lldb-vscode", "Commands for managing lldb-vscode.");
-  if (GetBoolean(arguments, "supportsStartDebuggingRequest", false)) {
-    cmd.AddCommand(
-        "startDebugging", &g_vsc.start_debugging_request_handler,
-        "Sends a startDebugging request from the debug adapter to the client "
-        "to "
-        "start a child debug session of the same type as the caller.");
-  }
+      "lldb-vscode", nullptr);
   cmd.AddCommand(
-      "repl-mode", &g_vsc.repl_mode_request_handler,
-      "Get or set the repl behavior of vscode-lldb evaluation requests.");
+      "startDebugging", &g_vsc.start_debugging_request_handler,
+      "Sends a startDebugging request from the debug adapter to the client to "
+      "start a child debug session of the same type as the caller.");
 
   g_vsc.progress_event_thread = std::thread(ProgressEventThreadFunction);
 
@@ -1543,16 +1519,22 @@ void request_initialize(const llvm::json::Object &request) {
   body.try_emplace("supportsGotoTargetsRequest", false);
   // The debug adapter supports the stepInTargetsRequest.
   body.try_emplace("supportsStepInTargetsRequest", false);
-  // The debug adapter supports the completions request.
-  body.try_emplace("supportsCompletionsRequest", true);
-
-  llvm::json::Array completion_characters;
-  completion_characters.emplace_back(".");
-  completion_characters.emplace_back(" ");
-  completion_characters.emplace_back("\t");
-  body.try_emplace("completionTriggerCharacters",
-                   std::move(completion_characters));
-
+  // We need to improve the current implementation of completions in order to
+  // enable it again. For some context, this is how VSCode works:
+  // - VSCode sends a completion request whenever chars are added, the user
+  //   triggers completion manually via CTRL-space or similar mechanisms, but
+  //   not when there's a deletion. Besides, VSCode doesn't let us know which
+  //   of these events we are handling. What is more, the use can paste or cut
+  //   sections of the text arbitrarily.
+  //   https://github.com/microsoft/vscode/issues/89531 tracks part of the
+  //   issue just mentioned.
+  // This behavior causes many problems with the current way completion is
+  // implemented in lldb-vscode, as these requests could be really expensive,
+  // blocking the debugger, and there could be many concurrent requests unless
+  // the user types very slowly... We need to address this specific issue, or
+  // at least trigger completion only when the user explicitly wants it, which
+  // is the behavior of LLDB CLI, that expects a TAB.
+  body.try_emplace("supportsCompletionsRequest", false);
   // The debug adapter supports the modules request.
   body.try_emplace("supportsModulesRequest", true);
   // The set of additional module information exposed by the debug adapter.
@@ -2111,7 +2093,6 @@ void request_scopes(const llvm::json::Object &request) {
     frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread());
     frame.GetThread().SetSelectedFrame(frame.GetFrameID());
   }
-
   g_vsc.variables.locals = frame.GetVariables(/*arguments=*/true,
                                               /*locals=*/true,
                                               /*statics=*/false,
@@ -3425,23 +3406,6 @@ int main(int argc, char *argv[]) {
     return EXIT_SUCCESS;
   }
 
-  if (input_args.hasArg(OPT_repl_mode)) {
-    llvm::opt::Arg *repl_mode = input_args.getLastArg(OPT_repl_mode);
-    llvm::StringRef repl_mode_value = repl_mode->getValue();
-    if (repl_mode_value == "auto") {
-      g_vsc.repl_mode = ReplMode::Auto;
-    } else if (repl_mode_value == "variable") {
-      g_vsc.repl_mode = ReplMode::Variable;
-    } else if (repl_mode_value == "command") {
-      g_vsc.repl_mode = ReplMode::Command;
-    } else {
-      llvm::errs()
-          << "'" << repl_mode_value
-          << "' is not a valid option, use 'variable', 'command' or 'auto'.\n";
-      return EXIT_FAILURE;
-    }
-  }
-
   if (llvm::opt::Arg *target_arg = input_args.getLastArg(OPT_launch_target)) {
     if (llvm::opt::Arg *comm_file = input_args.getLastArg(OPT_comm_file)) {
       lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;


        


More information about the lldb-commits mailing list