ivanhernandez13 created this revision.
ivanhernandez13 added a reviewer: clayborg.
ivanhernandez13 added a project: LLDB.
Herald added a subscriber: lldb-commits.

lldb-vscode can receive 'evaluate' requests in multiple modes, one of which is 
'repl' which indicates the expression to evaluate was typed into the Debug 
Console i.e. user input. This change makes 'request_evaluate' in lldb-vscode 
evaluate any user requested expression as an LLDB command if it cannot first 
find it as a local variable or a variable in the current frame. 


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D62547

Files:
  
lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py
  lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -926,6 +926,7 @@
   auto arguments = request.getObject("arguments");
   lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
   const auto expression = GetString(arguments, "expression");
+  const auto context = GetString(arguments, "context");
 
   if (!expression.empty() && expression[0] == '`') {
     auto result = RunLLDBCommands(llvm::StringRef(),
@@ -936,25 +937,38 @@
     // Always try to get the answer from the local variables if possible. If
     // this fails, then actually evaluate an expression using the expression
     // parser. "frame variable" is more reliable than the expression parser in
-    // many cases and it is faster.
+    // many cases and it is faster. Run the expression as an LLDB command as a
+    // last resort when in REPL context.
     lldb::SBValue value = frame.GetValueForVariablePath(
         expression.data(), lldb::eDynamicDontRunTarget);
     if (value.GetError().Fail())
       value = frame.EvaluateExpression(expression.data());
     if (value.GetError().Fail()) {
-      response["success"] = llvm::json::Value(false);
-      // This error object must live until we're done with the pointer returned
-      // by GetCString().
-      lldb::SBError error = value.GetError();
-      const char *error_cstr = error.GetCString();
-      if (error_cstr && error_cstr[0])
-        EmplaceSafeString(response, "message", std::string(error_cstr));
-      else
-        EmplaceSafeString(response, "message", "evaluate failed");
+      // Evaluate the expression as an LLDB command when the expression was
+      // received from the REPL console.
+      if (context == "repl") {
+        if (value.GetError().Fail()) {
+          auto result = RunLLDBCommands(llvm::StringRef(),
+                                        {expression});
+          EmplaceSafeString(body, "result", result);
+          body.try_emplace("variablesReference", (int64_t)0);
+        }
+      } else {
+        response["success"] = llvm::json::Value(false);
+        // This error object must live until we're done with the pointer
+        // returned by GetCString().
+        lldb::SBError error = value.GetError();
+        const char *error_cstr = error.GetCString();
+        if (error_cstr && error_cstr[0])
+          EmplaceSafeString(response, "message", std::string(error_cstr));
+        else
+          EmplaceSafeString(response, "message", "evaluate failed");
+      }
     } else {
       SetValueForKey(value, body, "result");
       auto value_typename = value.GetType().GetDisplayTypeName();
-      EmplaceSafeString(body, "type", value_typename ? value_typename : NO_TYPENAME);
+      EmplaceSafeString(
+                        body, "type", value_typename ? value_typename : NO_TYPENAME);
       if (value.MightHaveChildren()) {
         auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
         g_vsc.variables.Append(value);
Index: lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -519,7 +519,7 @@
         }
         return self.send_recv(command_dict)
 
-    def request_evaluate(self, expression, frameIndex=0, threadId=None):
+    def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None):
         stackFrame = self.get_stackFrame(frameIndex=frameIndex,
                                          threadId=threadId)
         if stackFrame is None:
@@ -528,6 +528,8 @@
             'expression': expression,
             'frameId': stackFrame['id'],
         }
+        if context is not None:
+          args_dict["context"] = context
         command_dict = {
             'command': 'evaluate',
             'type': 'request',
Index: lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py
@@ -195,6 +195,18 @@
         for expression in expressions:
             response = self.vscode.request_evaluate(expression)
             self.verify_values(expressions[expression], response['body'])
+            # Verify REPL context still returns variables when available.
+            response = self.vscode.request_evaluate(expression, context='repl')
+            self.verify_values(expressions[expression], response['body'])
+
+        # Test REPL commands with evaluate
+        replCommands = ['target list', 'image list', 'bt']
+        for command in replCommands:
+            response = self.vscode.request_evaluate(command, context='repl');
+            body = response['body']
+            self.assertTrue('result' in body,
+                            '"%s" doesn\'t return a result' % (command))
+            self.verify_commands('replCommands', body['result'], [command])
 
         # Test setting variables
         self.set_local('argc', 123)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to