[Lldb-commits] [lldb] 19311f5 - [lldb] common completion for process pids and process names

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Mon Aug 24 08:31:01 PDT 2020


Author: Gongyu Deng
Date: 2020-08-24T17:30:43+02:00
New Revision: 19311f5c3e9ada9d445e49feb7a2ae00ddaee2fa

URL: https://github.com/llvm/llvm-project/commit/19311f5c3e9ada9d445e49feb7a2ae00ddaee2fa
DIFF: https://github.com/llvm/llvm-project/commit/19311f5c3e9ada9d445e49feb7a2ae00ddaee2fa.diff

LOG: [lldb] common completion for process pids and process names

1. Added two common completions: `ProcessIDs` and `ProcessNames`, which are
refactored from their original dedicated option completions;
2. Removed the dedicated option completion functions of `process attach` and
`platform process attach`, so that they can use arg-type-bound common
completions instead;
3. Bound `eArgTypePid` to the pid completion, `eArgTypeProcessName` to the
process name completion in `CommandObject.cpp`;
4. Added a related test case.

Reviewed By: teemperor

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

Added: 
    

Modified: 
    lldb/include/lldb/Interpreter/CommandCompletions.h
    lldb/source/Commands/CommandCompletions.cpp
    lldb/source/Commands/CommandObjectPlatform.cpp
    lldb/source/Commands/CommandObjectProcess.cpp
    lldb/source/Interpreter/CommandObject.cpp
    lldb/test/API/functionalities/completion/TestCompletion.py
    lldb/test/API/functionalities/completion/main.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Interpreter/CommandCompletions.h b/lldb/include/lldb/Interpreter/CommandCompletions.h
index 1d8972e0ca03..0392eaed62c5 100644
--- a/lldb/include/lldb/Interpreter/CommandCompletions.h
+++ b/lldb/include/lldb/Interpreter/CommandCompletions.h
@@ -45,10 +45,12 @@ class CommandCompletions {
     eThreadIndexCompletion = (1u << 17),
     eWatchPointIDCompletion = (1u << 18),
     eBreakpointNameCompletion = (1u << 19),
+    eProcessIDCompletion = (1u << 20),
+    eProcessNameCompletion = (1u << 21),
     // 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 << 20)
+    eCustomCompletion = (1u << 22)
   };
 
   static bool InvokeCommonCompletionCallbacks(
@@ -110,6 +112,12 @@ class CommandCompletions {
                                  CompletionRequest &request,
                                  SearchFilter *searcher);
 
+  static void ProcessIDs(CommandInterpreter &interpreter,
+                         CompletionRequest &request, SearchFilter *searcher);
+
+  static void ProcessNames(CommandInterpreter &interpreter,
+                           CompletionRequest &request, SearchFilter *searcher);
+
   static void DisassemblyFlavors(CommandInterpreter &interpreter,
                                  CompletionRequest &request,
                                  SearchFilter *searcher);

diff  --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index 109613e223c7..9e74d8ad26cd 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -71,6 +71,8 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
       {eThreadIndexCompletion, CommandCompletions::ThreadIndexes},
       {eWatchPointIDCompletion, CommandCompletions::WatchPointIDs},
       {eBreakpointNameCompletion, CommandCompletions::BreakpointNames},
+      {eProcessIDCompletion, CommandCompletions::ProcessIDs},
+      {eProcessNameCompletion, CommandCompletions::ProcessNames},
       {eNoCompletion, nullptr} // This one has to be last in the list.
   };
 
@@ -649,6 +651,33 @@ void CommandCompletions::DisassemblyFlavors(CommandInterpreter &interpreter,
   }
 }
 
+void CommandCompletions::ProcessIDs(CommandInterpreter &interpreter,
+                                    CompletionRequest &request,
+                                    SearchFilter *searcher) {
+  lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
+  if (!platform_sp)
+    return;
+  ProcessInstanceInfoList process_infos;
+  ProcessInstanceInfoMatch match_info;
+  platform_sp->FindProcesses(match_info, process_infos);
+  for (const ProcessInstanceInfo &info : process_infos)
+    request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()),
+                                  info.GetNameAsStringRef());
+}
+
+void CommandCompletions::ProcessNames(CommandInterpreter &interpreter,
+                                      CompletionRequest &request,
+                                      SearchFilter *searcher) {
+  lldb::PlatformSP platform_sp(interpreter.GetPlatform(true));
+  if (!platform_sp)
+    return;
+  ProcessInstanceInfoList process_infos;
+  ProcessInstanceInfoMatch match_info;
+  platform_sp->FindProcesses(match_info, process_infos);
+  for (const ProcessInstanceInfo &info : process_infos)
+    request.TryCompleteCurrentArg(info.GetNameAsStringRef());
+}
+
 void CommandCompletions::TypeLanguages(CommandInterpreter &interpreter,
                                        CompletionRequest &request,
                                        SearchFilter *searcher) {

diff  --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index 4c235cb866a6..da113e5cb342 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -1331,6 +1331,14 @@ class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
 
   ~CommandObjectPlatformProcessInfo() override = default;
 
+  void
+  HandleArgumentCompletion(CompletionRequest &request,
+                           OptionElementVector &opt_element_vector) override {
+    CommandCompletions::InvokeCommonCompletionCallbacks(
+        GetCommandInterpreter(), CommandCompletions::eProcessIDCompletion,
+        request, nullptr);
+  }
+
 protected:
   bool DoExecute(Args &args, CommandReturnObject &result) override {
     Target *target = GetDebugger().GetSelectedTarget().get();
@@ -1447,46 +1455,6 @@ class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
       return llvm::makeArrayRef(g_platform_process_attach_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;
-
-      // We are only completing the name option for now...
-
-      // Are we in the name?
-      if (GetDefinitions()[opt_defs_index].short_option != 'n')
-        return;
-
-      // Look to see if there is a -P argument provided, and if so use that
-      // plugin, otherwise use the default plugin.
-
-      const char *partial_name = nullptr;
-      partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
-
-      PlatformSP platform_sp(interpreter.GetPlatform(true));
-      if (!platform_sp)
-        return;
-
-      ProcessInstanceInfoList process_infos;
-      ProcessInstanceInfoMatch match_info;
-      if (partial_name) {
-        match_info.GetProcessInfo().GetExecutableFile().SetFile(
-            partial_name, FileSpec::Style::native);
-        match_info.SetNameMatchType(NameMatch::StartsWith);
-      }
-      platform_sp->FindProcesses(match_info, process_infos);
-      const uint32_t num_matches = process_infos.size();
-      if (num_matches == 0)
-        return;
-
-      for (uint32_t i = 0; i < num_matches; ++i) {
-        request.AddCompletion(process_infos[i].GetNameAsStringRef());
-      }
-      return;
-    }
-
     // Options table: Required for subclasses of Options.
 
     static OptionDefinition g_option_table[];

diff  --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 25fe2e4b8b1a..5ef0b87c6435 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -320,49 +320,6 @@ class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
       return llvm::makeArrayRef(g_process_attach_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 'n': {
-        // Look to see if there is a -P argument provided, and if so use that
-        // plugin, otherwise use the default plugin.
-
-        const char *partial_name = nullptr;
-        partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
-
-        PlatformSP platform_sp(interpreter.GetPlatform(true));
-        if (!platform_sp)
-          return;
-        ProcessInstanceInfoList process_infos;
-        ProcessInstanceInfoMatch match_info;
-        if (partial_name) {
-          match_info.GetProcessInfo().GetExecutableFile().SetFile(
-              partial_name, FileSpec::Style::native);
-          match_info.SetNameMatchType(NameMatch::StartsWith);
-        }
-        platform_sp->FindProcesses(match_info, process_infos);
-        const size_t num_matches = process_infos.size();
-        if (num_matches == 0)
-          return;
-        for (size_t i = 0; i < num_matches; ++i) {
-          request.AddCompletion(process_infos[i].GetNameAsStringRef());
-        }
-      } break;
-
-      case 'P':
-        CommandCompletions::InvokeCommonCompletionCallbacks(
-            interpreter, CommandCompletions::eProcessPluginCompletion, request,
-            nullptr);
-        break;
-      }
-    }
-
-    // Instance variables to hold the values for command options.
-
     ProcessAttachInfo attach_info;
   };
 

diff  --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index 944cf5e58b40..b57323c32790 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -1078,9 +1078,9 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
     { eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "Path." },
     { eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." },
     { eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." },
-    { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { nullptr, false }, "The process ID number." },
+    { eArgTypePid, "pid", CommandCompletions::eProcessIDCompletion, { nullptr, false }, "The process ID number." },
     { eArgTypePlugin, "plugin", CommandCompletions::eProcessPluginCompletion, { nullptr, false }, "Help text goes here." },
-    { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the process." },
+    { eArgTypeProcessName, "process-name", CommandCompletions::eProcessNameCompletion, { nullptr, false }, "The name of the process." },
     { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python class." },
     { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python function." },
     { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." },

diff  --git a/lldb/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py
index 4c81288b3836..2423aecc2075 100644
--- a/lldb/test/API/functionalities/completion/TestCompletion.py
+++ b/lldb/test/API/functionalities/completion/TestCompletion.py
@@ -5,6 +5,8 @@
 
 
 import os
+from multiprocessing import Process
+import psutil
 import lldb
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
@@ -117,6 +119,27 @@ def test_process_plugin_completion(self):
             self.complete_from_to('process ' + subcommand + ' mac',
                                   'process ' + subcommand + ' mach-o-core')
 
+    @skipIfRemote
+    def test_common_completion_process_pid_and_name(self):
+        # The LLDB process itself and the process already attached to are both
+        # ignored by the process discovery mechanism, thus we need a process known 
+        # to us here.
+        self.build()
+        server = self.spawnSubprocess(
+            self.getBuildArtifact("a.out"),
+            ["-x"], # Arg "-x" makes the subprocess wait for input thus it won't be terminated too early
+            install_remote=False)
+        self.assertIsNotNone(server)
+        pid = server.pid
+
+        self.complete_from_to('process attach -p ', [str(pid)])
+        self.complete_from_to('platform process attach -p ', [str(pid)])
+        self.complete_from_to('platform process info ', [str(pid)])
+
+        pname = psutil.Process(pid).name()  # FIXME: psutil doesn't work for remote
+        self.complete_from_to('process attach -n ', [str(pname)])
+        self.complete_from_to('platform process attach -n ', [str(pname)])
+
     def test_process_signal(self):
         # The tab completion for "process signal"  won't work without a running process.
         self.complete_from_to('process signal ',

diff  --git a/lldb/test/API/functionalities/completion/main.cpp b/lldb/test/API/functionalities/completion/main.cpp
index eba81dc4c54c..06ff5773e8a9 100644
--- a/lldb/test/API/functionalities/completion/main.cpp
+++ b/lldb/test/API/functionalities/completion/main.cpp
@@ -1,3 +1,5 @@
+#include <iostream>
+
 class Foo
 {
 public:
@@ -11,14 +13,16 @@ namespace { int Quux (void) { return 0; } }
 
 struct Container { int MemberVar; };
 
-int main()
-{
-    Foo fooo;
-    Foo *ptr_fooo = &fooo;
-    fooo.Bar(1, 2);
+int main(int argc, char *argv[]) {
+  if (argc > 1 && std::string(argv[1]) == "-x")
+    std::cin.get();
+
+  Foo fooo;
+  Foo *ptr_fooo = &fooo;
+  fooo.Bar(1, 2);
 
-    Container container;
-    Container *ptr_container = &container;
-    int q = Quux();
-    return container.MemberVar = 3; // Break here
+  Container container;
+  Container *ptr_container = &container;
+  int q = Quux();
+  return container.MemberVar = 3; // Break here
 }


        


More information about the lldb-commits mailing list