forked from OSchip/llvm-project
Complete breakpoint enable/disable/delete/modify with a list of breakpoint IDs
Summary: 1. A new common completion `CommandCompletions::Breakpoints` to provide a list of the breakpoints of the current context; 2. Apply the completion above to the commands breakpoint enable/disable/delete/modify; 3. Unit test. Reviewers: teemperor, JDevlieghere Reviewed By: teemperor Tags: #lldb Differential Revision: https://reviews.llvm.org/D79666
This commit is contained in:
parent
c25b20c0f6
commit
0e50b9a43b
|
@ -35,10 +35,11 @@ public:
|
||||||
eArchitectureCompletion = (1u << 7),
|
eArchitectureCompletion = (1u << 7),
|
||||||
eVariablePathCompletion = (1u << 8),
|
eVariablePathCompletion = (1u << 8),
|
||||||
eRegisterCompletion = (1u << 9),
|
eRegisterCompletion = (1u << 9),
|
||||||
|
eBreakpointCompletion = (1u << 10),
|
||||||
// This item serves two purposes. It is the last element in the enum, so
|
// 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
|
// 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.
|
// if you & in this bit the base code will not process the option.
|
||||||
eCustomCompletion = (1u << 10)
|
eCustomCompletion = (1u << 11)
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool InvokeCommonCompletionCallbacks(
|
static bool InvokeCommonCompletionCallbacks(
|
||||||
|
@ -85,6 +86,9 @@ public:
|
||||||
|
|
||||||
static void Registers(CommandInterpreter &interpreter,
|
static void Registers(CommandInterpreter &interpreter,
|
||||||
CompletionRequest &request, SearchFilter *searcher);
|
CompletionRequest &request, SearchFilter *searcher);
|
||||||
|
|
||||||
|
static void Breakpoints(CommandInterpreter &interpreter,
|
||||||
|
CompletionRequest &request, SearchFilter *searcher);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lldb_private
|
} // namespace lldb_private
|
||||||
|
|
|
@ -57,6 +57,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||||
{eArchitectureCompletion, CommandCompletions::ArchitectureNames},
|
{eArchitectureCompletion, CommandCompletions::ArchitectureNames},
|
||||||
{eVariablePathCompletion, CommandCompletions::VariablePath},
|
{eVariablePathCompletion, CommandCompletions::VariablePath},
|
||||||
{eRegisterCompletion, CommandCompletions::Registers},
|
{eRegisterCompletion, CommandCompletions::Registers},
|
||||||
|
{eBreakpointCompletion, CommandCompletions::Breakpoints},
|
||||||
{eNoCompletion, nullptr} // This one has to be last in the list.
|
{eNoCompletion, nullptr} // This one has to be last in the list.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -550,3 +551,34 @@ void CommandCompletions::Registers(CommandInterpreter &interpreter,
|
||||||
reg_info->alt_name);
|
reg_info->alt_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandCompletions::Breakpoints(CommandInterpreter &interpreter,
|
||||||
|
CompletionRequest &request,
|
||||||
|
SearchFilter *searcher) {
|
||||||
|
lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget();
|
||||||
|
if (!target)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const BreakpointList &breakpoints = target->GetBreakpointList();
|
||||||
|
|
||||||
|
std::unique_lock<std::recursive_mutex> lock;
|
||||||
|
target->GetBreakpointList().GetListMutex(lock);
|
||||||
|
|
||||||
|
size_t num_breakpoints = breakpoints.GetSize();
|
||||||
|
if (num_breakpoints == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_breakpoints; ++i) {
|
||||||
|
lldb::BreakpointSP bp = breakpoints.GetBreakpointAtIndex(i);
|
||||||
|
|
||||||
|
StreamString s;
|
||||||
|
bp->GetDescription(&s, lldb::eDescriptionLevelBrief);
|
||||||
|
llvm::StringRef bp_info = s.GetString();
|
||||||
|
|
||||||
|
const size_t colon_pos = bp_info.find_first_of(':');
|
||||||
|
if (colon_pos != llvm::StringRef::npos)
|
||||||
|
bp_info = bp_info.drop_front(colon_pos + 2);
|
||||||
|
|
||||||
|
request.TryCompleteCurrentArg(std::to_string(bp->GetID()), bp_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -819,6 +819,14 @@ public:
|
||||||
|
|
||||||
~CommandObjectBreakpointModify() override = default;
|
~CommandObjectBreakpointModify() override = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
HandleArgumentCompletion(CompletionRequest &request,
|
||||||
|
OptionElementVector &opt_element_vector) override {
|
||||||
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||||
|
GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
|
||||||
|
request, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
Options *GetOptions() override { return &m_options; }
|
Options *GetOptions() override { return &m_options; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -885,6 +893,14 @@ public:
|
||||||
|
|
||||||
~CommandObjectBreakpointEnable() override = default;
|
~CommandObjectBreakpointEnable() override = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
HandleArgumentCompletion(CompletionRequest &request,
|
||||||
|
OptionElementVector &opt_element_vector) override {
|
||||||
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||||
|
GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
|
||||||
|
request, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||||||
Target &target = GetSelectedOrDummyTarget();
|
Target &target = GetSelectedOrDummyTarget();
|
||||||
|
@ -993,6 +1009,14 @@ the second re-enables the first location.");
|
||||||
|
|
||||||
~CommandObjectBreakpointDisable() override = default;
|
~CommandObjectBreakpointDisable() override = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
HandleArgumentCompletion(CompletionRequest &request,
|
||||||
|
OptionElementVector &opt_element_vector) override {
|
||||||
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||||
|
GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
|
||||||
|
request, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
||||||
Target &target = GetSelectedOrDummyTarget();
|
Target &target = GetSelectedOrDummyTarget();
|
||||||
|
@ -1371,6 +1395,14 @@ public:
|
||||||
|
|
||||||
~CommandObjectBreakpointDelete() override = default;
|
~CommandObjectBreakpointDelete() override = default;
|
||||||
|
|
||||||
|
void
|
||||||
|
HandleArgumentCompletion(CompletionRequest &request,
|
||||||
|
OptionElementVector &opt_element_vector) override {
|
||||||
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||||
|
GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
|
||||||
|
request, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
Options *GetOptions() override { return &m_options; }
|
Options *GetOptions() override { return &m_options; }
|
||||||
|
|
||||||
class CommandOptions : public Options {
|
class CommandOptions : public Options {
|
||||||
|
|
|
@ -477,3 +477,40 @@ class CommandLineCompletionTestCase(TestBase):
|
||||||
# register write can only take exact one register name as argument
|
# register write can only take exact one register name as argument
|
||||||
self.complete_from_to('register write rbx ',
|
self.complete_from_to('register write rbx ',
|
||||||
[])
|
[])
|
||||||
|
|
||||||
|
def test_breakpoint_enable_disable_delete_modify_with_ids(self):
|
||||||
|
"""These four breakpoint subcommands should be completed with a list of breakpoint ids"""
|
||||||
|
|
||||||
|
subcommands = ['enable', 'disable', 'delete', 'modify']
|
||||||
|
|
||||||
|
# The tab completion here is unavailable without a target
|
||||||
|
for subcommand in subcommands:
|
||||||
|
self.complete_from_to('breakpoint ' + subcommand + ' ',
|
||||||
|
'breakpoint ' + subcommand + ' ')
|
||||||
|
|
||||||
|
self.build()
|
||||||
|
target = self.dbg.CreateTarget(self.getBuildArtifact('a.out'))
|
||||||
|
self.assertTrue(target, VALID_TARGET)
|
||||||
|
|
||||||
|
bp = target.BreakpointCreateByName('main', 'a.out')
|
||||||
|
self.assertTrue(bp)
|
||||||
|
self.assertEqual(bp.GetNumLocations(), 1)
|
||||||
|
|
||||||
|
for subcommand in subcommands:
|
||||||
|
self.complete_from_to('breakpoint ' + subcommand + ' ',
|
||||||
|
['1'])
|
||||||
|
|
||||||
|
bp2 = target.BreakpointCreateByName('Bar', 'a.out')
|
||||||
|
self.assertTrue(bp2)
|
||||||
|
self.assertEqual(bp2.GetNumLocations(), 1)
|
||||||
|
|
||||||
|
for subcommand in subcommands:
|
||||||
|
self.complete_from_to('breakpoint ' + subcommand + ' ',
|
||||||
|
['1',
|
||||||
|
'2'])
|
||||||
|
|
||||||
|
for subcommand in subcommands:
|
||||||
|
self.complete_from_to('breakpoint ' + subcommand + ' 1 ',
|
||||||
|
['1',
|
||||||
|
'2'])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue