[Lldb-commits] [lldb] 22e63cb - [lldb] tab completion for breakpoint names

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Thu Aug 20 11:56:56 PDT 2020


Author: Gongyu Deng
Date: 2020-08-20T20:56:34+02:00
New Revision: 22e63cba17e5e6266b9251e3fb7032b793143d09

URL: https://github.com/llvm/llvm-project/commit/22e63cba17e5e6266b9251e3fb7032b793143d09
DIFF: https://github.com/llvm/llvm-project/commit/22e63cba17e5e6266b9251e3fb7032b793143d09.diff

LOG: [lldb] tab completion for breakpoint names

1. created a common completion for breakpoint names;
2. bound the breakpoint name common completion with eArgTypeBreakpointName;
3. implemented the dedicated completion for breakpoint read -N.

Reviewed By: JDevlieghere

Differential Revision: https://reviews.llvm.org/D80693

Added: 
    lldb/test/API/functionalities/completion/breakpoints.json
    lldb/test/API/functionalities/completion/breakpoints_invalid.json

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Interpreter/CommandCompletions.h b/lldb/include/lldb/Interpreter/CommandCompletions.h
index a744b3fd849d..1d8972e0ca03 100644
--- a/lldb/include/lldb/Interpreter/CommandCompletions.h
+++ b/lldb/include/lldb/Interpreter/CommandCompletions.h
@@ -44,10 +44,11 @@ class CommandCompletions {
     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 @@ class CommandCompletions {
   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);

diff  --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index 4ed11e14b84f..109613e223c7 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -70,6 +70,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
       {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::Breakpoints(CommandInterpreter &interpreter,
   }
 }
 
+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) {

diff  --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index b62fe6c93cd8..023ba208176a 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -2097,7 +2097,79 @@ class CommandObjectBreakpointRead : public CommandObjectParsed {
       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;

diff  --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index 6f356e448523..944cf5e58b40 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -1041,7 +1041,7 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
     { 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." },

diff  --git a/lldb/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py
index 987ae65474ed..4922cca7b722 100644
--- a/lldb/test/API/functionalities/completion/TestCompletion.py
+++ b/lldb/test/API/functionalities/completion/TestCompletion.py
@@ -644,3 +644,21 @@ def test_complete_breakpoint_with_ids(self):
                                   ['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')

diff  --git a/lldb/test/API/functionalities/completion/breakpoints.json b/lldb/test/API/functionalities/completion/breakpoints.json
new file mode 100644
index 000000000000..c9b4db3c6175
--- /dev/null
+++ b/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"
+            }
+        }
+    }
+]

diff  --git a/lldb/test/API/functionalities/completion/breakpoints_invalid.json b/lldb/test/API/functionalities/completion/breakpoints_invalid.json
new file mode 100644
index 000000000000..86a6b63dfcab
--- /dev/null
+++ b/lldb/test/API/functionalities/completion/breakpoints_invalid.json
@@ -0,0 +1,6 @@
+[
+    {
+        "Breakpoint": {
+        }
+    }
+]


        


More information about the lldb-commits mailing list