diff --git a/lldb/include/lldb/Interpreter/CommandCompletions.h b/lldb/include/lldb/Interpreter/CommandCompletions.h index deaf39ed32a77..306c6c121f5fa 100644 --- a/lldb/include/lldb/Interpreter/CommandCompletions.h +++ b/lldb/include/lldb/Interpreter/CommandCompletions.h @@ -39,10 +39,11 @@ class CommandCompletions { eProcessPluginCompletion = (1u << 11), eDisassemblyFlavorCompletion = (1u << 12), eTypeLanguageCompletion = (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 @@ class CommandCompletions { static void TypeLanguages(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); + + static void FrameIndexes(CommandInterpreter &interpreter, + CompletionRequest &request, SearchFilter *searcher); }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index 795aabda787fe..25f684a282688 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -20,6 +20,7 @@ #include "lldb/Symbol/Variable.h" #include "lldb/Target/Language.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" @@ -62,6 +63,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, {eDisassemblyFlavorCompletion, CommandCompletions::DisassemblyFlavors}, {eTypeLanguageCompletion, CommandCompletions::TypeLanguages}, + {eFrameIndexCompletion, CommandCompletions::FrameIndexes}, {eNoCompletion, nullptr} // This one has to be last in the list. }; @@ -618,3 +620,20 @@ void CommandCompletions::TypeLanguages(CommandInterpreter &interpreter, Language::GetNameForLanguageType(static_cast(bit))); } } + +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()); + } +} diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index c7b67b59d288c..a656a99a1c712 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -291,17 +291,12 @@ class CommandObjectFrameSelect : public CommandObjectParsed { void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override { - if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0) + if (request.GetCursorIndex() != 0) 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; } diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 40b6749f6a565..fc3127611ae5b 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -1055,7 +1055,7 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { { 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." }, diff --git a/lldb/test/API/functionalities/completion/TestCompletion.py b/lldb/test/API/functionalities/completion/TestCompletion.py index 436a464aa645d..691a6e89eec53 100644 --- a/lldb/test/API/functionalities/completion/TestCompletion.py +++ b/lldb/test/API/functionalities/completion/TestCompletion.py @@ -460,12 +460,12 @@ def test_completion_description_command_options(self): 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")