[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