clayborg updated this revision to Diff 428789.
clayborg added a comment.

Remove logging change from VSCode.cpp that was accidentally left in.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125347/new/

https://reviews.llvm.org/D125347

Files:
  lldb/test/API/tools/lldb-vscode/variables/TestVSCode_variables.py
  lldb/test/API/tools/lldb-vscode/variables/main.cpp
  lldb/tools/lldb-vscode/JSONUtils.cpp

Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===================================================================
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <iomanip>
 #include <sstream>
+#include <string.h>
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/FormatAdapters.h"
@@ -1024,7 +1025,37 @@
   if (format_hex)
     v.SetFormat(lldb::eFormatHex);
   SetValueForKey(v, object, "value");
-  auto type_cstr = v.GetType().GetDisplayTypeName();
+  auto type_obj = v.GetType();
+  auto type_cstr = type_obj.GetDisplayTypeName();
+  // If we have a type with many many children, we would like to be able to
+  // give a hint to the IDE that the type has indexed children so that the
+  // request can be broken up in grabbing only a few children at a time. We want
+  // to be careful and only call "v.GetNumChildren()" if we have an array type
+  // or if we have a synthetic child provider. We don't want to call
+  // "v.GetNumChildren()" on all objects as class, struct and union types don't
+  // need to be completed if they are never expanded. So we want to avoid
+  // calling this to only cases where we it makes sense to keep performance high
+  // during normal debugging.
+
+  // If we have an array type, say that it is indexed and provide the number of
+  // children in case we have a huge array. If we don't do this, then we might
+  // take a while to produce all children at onces which can delay your debug
+  // session.
+  const bool is_array = type_obj.IsArrayType();
+  const bool is_synthetic = v.IsSynthetic();
+  if (is_array || is_synthetic) {
+    const auto num_children = v.GetNumChildren();
+    if (is_array) {
+      object.try_emplace("indexedVariables", num_children);
+    } else {
+      // If a type has a synthetic child provider, then the SBType of "v" won't
+      // tell us anything about what might be displayed. So we can check if the
+      // first child's name is "[0]" and then we can say it is indexed.
+      const char *first_child_name = v.GetChildAtIndex(0).GetName();
+      if (first_child_name && strcmp(first_child_name, "[0]") == 0)
+        object.try_emplace("indexedVariables", num_children);
+    }
+  }
   EmplaceSafeString(object, "type", type_cstr ? type_cstr : NO_TYPENAME);
   if (varID != INT64_MAX)
     object.try_emplace("id", varID);
Index: lldb/test/API/tools/lldb-vscode/variables/main.cpp
===================================================================
--- lldb/test/API/tools/lldb-vscode/variables/main.cpp
+++ lldb/test/API/tools/lldb-vscode/variables/main.cpp
@@ -5,10 +5,10 @@
   int y;
   int buffer[BUFFER_SIZE];
 };
-
+#include <vector>
 int g_global = 123;
 static int s_global = 234;
-
+int test_indexedVariables();
 int main(int argc, char const *argv[]) {
   static float s_local = 2.25;
   PointType pt = { 11,22, {0}};
@@ -22,5 +22,15 @@
       s_global = x; // breakpoint 2
     }
   }
-  return 0; // breakpoint 3
+  return test_indexedVariables(); // breakpoint 3
+}
+
+int test_indexedVariables() {
+  int small_array[5] = {1, 2, 3, 4, 5};
+  int large_array[200];
+  std::vector<int> small_vector;
+  std::vector<int> large_vector;
+  small_vector.assign(5, 0);
+  large_vector.assign(200, 0);
+  return 0; // breakpoint 4
 }
Index: lldb/test/API/tools/lldb-vscode/variables/TestVSCode_variables.py
===================================================================
--- lldb/test/API/tools/lldb-vscode/variables/TestVSCode_variables.py
+++ lldb/test/API/tools/lldb-vscode/variables/TestVSCode_variables.py
@@ -30,8 +30,8 @@
                 verify_value = verify[key]
                 actual_value = actual[key]
                 self.assertEqual(verify_value, actual_value,
-                                '"%s" keys don\'t match (%s != %s)' % (
-                                    key, actual_value, verify_value))
+                                '"%s" keys don\'t match (%s != %s) from:\n%s' % (
+                                    key, actual_value, verify_value, actual))
         if 'startswith' in verify_dict:
             verify = verify_dict['startswith']
             for key in verify:
@@ -43,6 +43,11 @@
                                  ' "%s")') % (
                                     key, actual_value,
                                     verify_value))
+        if 'missing' in verify_dict:
+            missing = verify_dict['missing']
+            for key in missing:
+                self.assertTrue(key not in actual,
+                                'key "%s" is not expected in %s' % (key, actual))
         hasVariablesReference = 'variablesReference' in actual
         varRef = None
         if hasVariablesReference:
@@ -310,22 +315,39 @@
         locals = self.vscode.get_local_variables()
         buffer_children = make_buffer_verify_dict(0, 32)
         verify_locals = {
-            "argc": {"equals": {"type": "int", "value": "1"}},
+            "argc": {
+                "equals": {"type": "int", "value": "1"},
+                "missing": ["indexedVariables"],
+            },
             "argv": {
                 "equals": {"type": "const char **"},
                 "startswith": {"value": "0x"},
                 "hasVariablesReference": True,
+                "missing": ["indexedVariables"],
             },
             "pt": {
                 "equals": {"type": "PointType"},
                 "hasVariablesReference": True,
+                "missing": ["indexedVariables"],
                 "children": {
-                    "x": {"equals": {"type": "int", "value": "11"}},
-                    "y": {"equals": {"type": "int", "value": "22"}},
-                    "buffer": {"children": buffer_children},
+                    "x": {
+                        "equals": {"type": "int", "value": "11"},
+                        "missing": ["indexedVariables"],
+                    },
+                    "y": {
+                        "equals": {"type": "int", "value": "22"},
+                        "missing": ["indexedVariables"],
+                    },
+                    "buffer": {
+                        "children": buffer_children,
+                        "equals": {"indexedVariables": 32}
+                    },
                 },
             },
-            "x": {"equals": {"type": "int"}},
+            "x": {
+                "equals": {"type": "int"},
+                "missing": ["indexedVariables"],
+            },
         }
         self.verify_variables(verify_locals, locals)
 
@@ -336,6 +358,7 @@
             "response": {
                 "equals": {"type": "PointType"},
                 "startswith": {"result": "PointType @ 0x"},
+                "missing": ["indexedVariables"],
                 "hasVariablesReference": True,
             },
             "children": {
@@ -408,3 +431,36 @@
                 self.assertEquals(scope.get("presentationHint"), "locals")
             if scope["name"] == "Registers":
                 self.assertEquals(scope.get("presentationHint"), "registers")
+
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_indexedVariables(self):
+        """
+        Tests that arrays and lldb.SBValue objects that have synthetic child
+        providers have "indexedVariables" key/value pairs. This helps the IDE
+        not to fetch too many children all at once.
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        source = "main.cpp"
+        breakpoint1_line = line_number(source, "// breakpoint 4")
+        lines = [breakpoint1_line]
+        # Set breakpoint in the thread function so we can step the threads
+        breakpoint_ids = self.set_source_breakpoints(source, lines)
+        self.assertEqual(
+            len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
+        )
+        self.continue_to_breakpoints(breakpoint_ids)
+
+        # Verify locals
+        locals = self.vscode.get_local_variables()
+        buffer_children = make_buffer_verify_dict(0, 32)
+        verify_locals = {
+            "small_array": {"equals": {"indexedVariables": 5}},
+            "large_array": {"equals": {"indexedVariables": 200}},
+            "small_vector": {"equals": {"indexedVariables": 5}},
+            "large_vector": {"equals": {"indexedVariables": 200}},
+            "pt": {"missing": ["indexedVariables"]},
+        }
+        self.verify_variables(verify_locals, locals)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to