Index: lldb/include/lldb/Interpreter/CommandCompletions.h =================================================================== --- lldb/include/lldb/Interpreter/CommandCompletions.h +++ lldb/include/lldb/Interpreter/CommandCompletions.h @@ -39,10 +39,11 @@ eBreakpointNameCompletion = (1u << 11), eProcessPluginCompletion = (1u << 12), eProcessIDCompletion = (1u << 13), + eFrameIndexCompletion = (1u << 14), // 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 << 14) + eCustomCompletion = (1u << 15) }; static bool InvokeCommonCompletionCallbacks( @@ -103,6 +104,9 @@ static void ProcessIDs(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); + + static void FrameIndexes(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 @@ -19,6 +19,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/TildeExpressionResolver.h" @@ -61,6 +62,7 @@ {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, {eProcessIDCompletion, CommandCompletions::ProcessIDs}, + {eFrameIndexCompletion, CommandCompletions::FrameIndexes}, {eNoCompletion, nullptr} // This one has to be last in the list. }; @@ -630,4 +632,21 @@ request.TryCompleteCurrentArg(std::to_string(info.GetProcessID()), process_name); } -} \ No newline at end of file +} + +void CommandCompletions::FrameIndexes(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + const ExecutionContext &exe_ctx = interpreter.GetExecutionContext(); + if (!exe_ctx.HasProcessScope()) + return; + + lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); + const uint32_t frame_num = thread_sp->GetStackFrameCount(); + for (uint32_t i = 0; i < frame_num; ++i) { + lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i); + StreamString strm; + frame_sp->Dump(&strm, false, true); + request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); + } +} Index: lldb/source/Commands/CommandObjectFrame.cpp =================================================================== --- lldb/source/Commands/CommandObjectFrame.cpp +++ lldb/source/Commands/CommandObjectFrame.cpp @@ -291,17 +291,12 @@ void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) + if (request.GetCursorIndex()) return; - lldb::ThreadSP thread_sp = m_exe_ctx.GetThreadSP(); - const uint32_t frame_num = thread_sp->GetStackFrameCount(); - for (uint32_t i = 0; i < frame_num; ++i) { - lldb::StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(i); - StreamString strm; - frame_sp->Dump(&strm, false, true); - request.TryCompleteCurrentArg(std::to_string(i), strm.GetString()); - } + CommandCompletions::InvokeCommonCompletionCallbacks( + GetCommandInterpreter(), CommandCompletions::eFrameIndexCompletion, + request, nullptr); } Options *GetOptions() override { return &m_options; } Index: lldb/source/Interpreter/CommandObject.cpp =================================================================== --- lldb/source/Interpreter/CommandObject.cpp +++ lldb/source/Interpreter/CommandObject.cpp @@ -1055,7 +1055,7 @@ { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "The name of a file (can include path)." }, { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, nullptr }, - { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into a thread's list of frames." }, + { eArgTypeFrameIndex, "frame-index", CommandCompletions::eFrameIndexCompletion, { nullptr, false }, "Index into a thread's list of frames." }, { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." }, { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." }, Index: lldb/test/API/functionalities/completion/TestCompletion.py =================================================================== --- lldb/test/API/functionalities/completion/TestCompletion.py +++ lldb/test/API/functionalities/completion/TestCompletion.py @@ -428,12 +428,12 @@ self.check_completion_with_desc("breakpoint set --Z", [ ]) - def test_frame_select(self): + def test_common_completion_frame_index(self): self.build() - self.main_source_spec = lldb.SBFileSpec("main.cpp") - lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec) + lldbutil.run_to_source_breakpoint(self, '// Break here', lldb.SBFileSpec("main.cpp")) self.complete_from_to('frame select ', ['0']) + self.complete_from_to('thread backtrace -s ', ['0']) def test_frame_recognizer_delete(self): self.runCmd("frame recognizer add -l py_class -s module_name -n recognizer_name")