Index: lldb/include/lldb/Interpreter/CommandCompletions.h =================================================================== --- lldb/include/lldb/Interpreter/CommandCompletions.h +++ lldb/include/lldb/Interpreter/CommandCompletions.h @@ -38,10 +38,11 @@ eBreakpointCompletion = (1u << 10), eBreakpointNameCompletion = (1u << 11), eProcessPluginCompletion = (1u << 12), + eProcessIDCompletion = (1u << 13), // 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 << 13) + eCustomCompletion = (1u << 14) }; static bool InvokeCommonCompletionCallbacks( @@ -99,6 +100,9 @@ static void ProcessPluginNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); + + static void ProcessIDs(CommandInterpreter &interpreter, + CompletionRequest &request, SearchFilter *searcher); }; } // namespace lldb_private Index: lldb/source/Commands/CommandCompletions.cpp =================================================================== --- lldb/source/Commands/CommandCompletions.cpp +++ lldb/source/Commands/CommandCompletions.cpp @@ -60,6 +60,7 @@ {eBreakpointCompletion, CommandCompletions::Breakpoints}, {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, + {eProcessIDCompletion, CommandCompletions::ProcessIDs}, {eNoCompletion, nullptr} // This one has to be last in the list. }; @@ -608,4 +609,25 @@ SearchFilter *searcher) { PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(), request); +} + +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); + const size_t num_matches = process_infos.size(); + if (num_matches == 0) + return; + for (const ProcessInstanceInfo &info : process_infos) { + const llvm::StringRef process_name = info.GetNameAsStringRef(); + if (process_name.empty()) + continue; + request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()), + process_name); + } } \ No newline at end of file Index: lldb/source/Commands/CommandObjectProcess.cpp =================================================================== --- lldb/source/Commands/CommandObjectProcess.cpp +++ lldb/source/Commands/CommandObjectProcess.cpp @@ -355,6 +355,12 @@ interpreter, CommandCompletions::eProcessPluginCompletion, request, nullptr); break; + + case 'p': + CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, CommandCompletions::eProcessIDCompletion, request, + nullptr); + break; } } Index: lldb/test/API/functionalities/completion/TestCompletion.py =================================================================== --- lldb/test/API/functionalities/completion/TestCompletion.py +++ lldb/test/API/functionalities/completion/TestCompletion.py @@ -3,8 +3,8 @@ """ - import os +from multiprocessing import Process import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -92,6 +92,19 @@ self.complete_from_to('process ' + subcommand + ' mac', 'process ' + subcommand + ' mach-o-core') + @skipIfRemote + def test_process_attach_dash_p(self): + # The LLDB process itself and the process already attached to are both + # ignored by the process discovery mechanism, thus we need to create a + # process known to us here. + def test(): + while True: + time.sleep(1) + + p = Process(target=test, daemon=True) + p.start() + self.complete_from_to('process attach -p ', [str(p.pid)]) + def test_process_signal(self): # The tab completion for "process signal" won't work without a running process. self.complete_from_to('process signal ',