This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rG22e63cba17e5: [lldb] tab completion for breakpoint names 
(authored by MrHate, committed by teemperor).
Herald added a subscriber: lldb-commits.

Changed prior to commit:
  https://reviews.llvm.org/D80693?vs=276295&id=286870#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D80693

Files:
  lldb/include/lldb/Interpreter/CommandCompletions.h
  lldb/source/Commands/CommandCompletions.cpp
  lldb/source/Commands/CommandObjectBreakpoint.cpp
  lldb/source/Interpreter/CommandObject.cpp
  lldb/test/API/functionalities/completion/TestCompletion.py
  lldb/test/API/functionalities/completion/breakpoints.json
  lldb/test/API/functionalities/completion/breakpoints_invalid.json

Index: lldb/test/API/functionalities/completion/breakpoints_invalid.json
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/completion/breakpoints_invalid.json
@@ -0,0 +1,6 @@
+[
+    {
+        "Breakpoint": {
+        }
+    }
+]
Index: lldb/test/API/functionalities/completion/breakpoints.json
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/completion/breakpoints.json
@@ -0,0 +1,34 @@
+[
+    {
+        "Breakpoint": {
+            "BKPTOptions": {
+                "AutoContinue": false,
+                "ConditionText": "",
+                "EnabledState": true,
+                "IgnoreCount": 0,
+                "OneShotState": false
+            },
+            "BKPTResolver": {
+                "Options": {
+                    "NameMask": [
+                        56
+                    ],
+                    "Offset": 0,
+                    "SkipPrologue": true,
+                    "SymbolNames": [
+                        "main"
+                    ]
+                },
+                "Type": "SymbolName"
+            },
+            "Hardware": false,
+            "Names": [
+                "mm"
+            ],
+            "SearchFilter": {
+                "Options": {},
+                "Type": "Unconstrained"
+            }
+        }
+    }
+]
Index: lldb/test/API/functionalities/completion/TestCompletion.py
===================================================================
--- lldb/test/API/functionalities/completion/TestCompletion.py
+++ lldb/test/API/functionalities/completion/TestCompletion.py
@@ -644,3 +644,21 @@
                                   ['1',
                                    '2'])
 
+    def test_complete_breakpoint_with_names(self):
+        self.build()
+        target = self.dbg.CreateTarget(self.getBuildArtifact('a.out'))
+        self.assertTrue(target, VALID_TARGET)
+
+        # test breakpoint read dedicated
+        self.complete_from_to('breakpoint read -N ', 'breakpoint read -N ')
+        self.complete_from_to('breakpoint read -f breakpoints.json -N ', ['mm'])
+        self.complete_from_to('breakpoint read -f breakpoints.json -N n', 'breakpoint read -f breakpoints.json -N n')
+        self.complete_from_to('breakpoint read -f breakpoints_invalid.json -N ', 'breakpoint read -f breakpoints_invalid.json -N ')
+
+        # test common breapoint name completion
+        bp1 = target.BreakpointCreateByName('main', 'a.out')
+        self.assertTrue(bp1)
+        self.assertEqual(bp1.GetNumLocations(), 1)
+        self.complete_from_to('breakpoint set -N n', 'breakpoint set -N n')
+        self.assertTrue(bp1.AddNameWithErrorHandling("nn"))
+        self.complete_from_to('breakpoint set -N ', 'breakpoint set -N nn')
Index: lldb/source/Interpreter/CommandObject.cpp
===================================================================
--- lldb/source/Interpreter/CommandObject.cpp
+++ lldb/source/Interpreter/CommandObject.cpp
@@ -1041,7 +1041,7 @@
     { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" },
     { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr },
     { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr },
-    { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
+    { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eBreakpointNameCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
     { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." },
     { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." },
     { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." },
Index: lldb/source/Commands/CommandObjectBreakpoint.cpp
===================================================================
--- lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -2097,7 +2097,79 @@
       return llvm::makeArrayRef(g_breakpoint_read_options);
     }
 
-    // Instance variables to hold the values for command options.
+    void HandleOptionArgumentCompletion(
+        CompletionRequest &request, OptionElementVector &opt_element_vector,
+        int opt_element_index, CommandInterpreter &interpreter) override {
+      int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
+      int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
+
+      switch (GetDefinitions()[opt_defs_index].short_option) {
+      case 'f':
+        CommandCompletions::InvokeCommonCompletionCallbacks(
+            interpreter, CommandCompletions::eDiskFileCompletion, request,
+            nullptr);
+        break;
+
+      case 'N':
+        llvm::Optional<FileSpec> file_spec;
+        const llvm::StringRef dash_f("-f");
+        for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
+          if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
+            file_spec.emplace(
+                request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
+            break;
+          }
+        }
+        if (!file_spec)
+          return;
+
+        FileSystem::Instance().Resolve(*file_spec);
+        Status error;
+        StructuredData::ObjectSP input_data_sp =
+            StructuredData::ParseJSONFromFile(*file_spec, error);
+        if (!error.Success())
+          return;
+
+        StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
+        if (!bkpt_array)
+          return;
+
+        const size_t num_bkpts = bkpt_array->GetSize();
+        for (size_t i = 0; i < num_bkpts; i++) {
+          StructuredData::ObjectSP bkpt_object_sp =
+              bkpt_array->GetItemAtIndex(i);
+          if (!bkpt_object_sp)
+            return;
+
+          StructuredData::Dictionary *bkpt_dict =
+              bkpt_object_sp->GetAsDictionary();
+          if (!bkpt_dict)
+            return;
+
+          StructuredData::ObjectSP bkpt_data_sp =
+              bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
+          if (!bkpt_data_sp)
+            return;
+
+          bkpt_dict = bkpt_data_sp->GetAsDictionary();
+          if (!bkpt_dict)
+            return;
+
+          StructuredData::Array *names_array;
+
+          if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
+            return;
+
+          size_t num_names = names_array->GetSize();
+
+          for (size_t i = 0; i < num_names; i++) {
+            llvm::StringRef name;
+            if (names_array->GetItemAtIndexAsString(i, name))
+              request.TryCompleteCurrentArg(name);
+          }
+        }
+      }
+    }
 
     std::string m_filename;
     std::vector<std::string> m_names;
Index: lldb/source/Commands/CommandCompletions.cpp
===================================================================
--- lldb/source/Commands/CommandCompletions.cpp
+++ lldb/source/Commands/CommandCompletions.cpp
@@ -70,6 +70,7 @@
       {eStopHookIDCompletion, CommandCompletions::StopHookIDs},
       {eThreadIndexCompletion, CommandCompletions::ThreadIndexes},
       {eWatchPointIDCompletion, CommandCompletions::WatchPointIDs},
+      {eBreakpointNameCompletion, CommandCompletions::BreakpointNames},
       {eNoCompletion, nullptr} // This one has to be last in the list.
   };
 
@@ -617,13 +618,26 @@
   }
 }
 
+void CommandCompletions::BreakpointNames(CommandInterpreter &interpreter,
+                                         CompletionRequest &request,
+                                         SearchFilter *searcher) {
+  lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget();
+  if (!target)
+    return;
+
+  std::vector<std::string> name_list;
+  target->GetBreakpointNames(name_list);
+
+  for (const std::string &name : name_list)
+    request.TryCompleteCurrentArg(name);
+}
+
 void CommandCompletions::ProcessPluginNames(CommandInterpreter &interpreter,
                                             CompletionRequest &request,
                                             SearchFilter *searcher) {
   PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(),
                                          request);
 }
-
 void CommandCompletions::DisassemblyFlavors(CommandInterpreter &interpreter,
                                             CompletionRequest &request,
                                             SearchFilter *searcher) {
Index: lldb/include/lldb/Interpreter/CommandCompletions.h
===================================================================
--- lldb/include/lldb/Interpreter/CommandCompletions.h
+++ lldb/include/lldb/Interpreter/CommandCompletions.h
@@ -44,10 +44,11 @@
     eStopHookIDCompletion = (1u << 16),
     eThreadIndexCompletion = (1u << 17),
     eWatchPointIDCompletion = (1u << 18),
+    eBreakpointNameCompletion = (1u << 19),
     // This item serves two purposes.  It is the last element in the enum, so
     // you can add custom enums starting from here in your Option class. Also
     // if you & in this bit the base code will not process the option.
-    eCustomCompletion = (1u << 19)
+    eCustomCompletion = (1u << 20)
   };
 
   static bool InvokeCommonCompletionCallbacks(
@@ -101,6 +102,10 @@
   static void Breakpoints(CommandInterpreter &interpreter,
                           CompletionRequest &request, SearchFilter *searcher);
 
+  static void BreakpointNames(CommandInterpreter &interpreter,
+                              CompletionRequest &request,
+                              SearchFilter *searcher);
+
   static void ProcessPluginNames(CommandInterpreter &interpreter,
                                  CompletionRequest &request,
                                  SearchFilter *searcher);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to