Skip to content

Commit

Permalink
Complete breakpoint enable/disable/delete/modify with a list of break…
Browse files Browse the repository at this point in the history
…point 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
  • Loading branch information
MrHate authored and Teemperor committed May 11, 2020
1 parent c25b20c commit 0e50b9a
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 2 deletions.
6 changes: 5 additions & 1 deletion lldb/include/lldb/Interpreter/CommandCompletions.h
Expand Up @@ -35,10 +35,11 @@ class CommandCompletions {
eArchitectureCompletion = (1u << 7),
eVariablePathCompletion = (1u << 8),
eRegisterCompletion = (1u << 9),
eBreakpointCompletion = (1u << 10),
// 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 << 10)
eCustomCompletion = (1u << 11)
};

static bool InvokeCommonCompletionCallbacks(
Expand Down Expand Up @@ -85,6 +86,9 @@ class CommandCompletions {

static void Registers(CommandInterpreter &interpreter,
CompletionRequest &request, SearchFilter *searcher);

static void Breakpoints(CommandInterpreter &interpreter,
CompletionRequest &request, SearchFilter *searcher);
};

} // namespace lldb_private
Expand Down
34 changes: 33 additions & 1 deletion lldb/source/Commands/CommandCompletions.cpp
Expand Up @@ -57,6 +57,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
{eArchitectureCompletion, CommandCompletions::ArchitectureNames},
{eVariablePathCompletion, CommandCompletions::VariablePath},
{eRegisterCompletion, CommandCompletions::Registers},
{eBreakpointCompletion, CommandCompletions::Breakpoints},
{eNoCompletion, nullptr} // This one has to be last in the list.
};

Expand Down Expand Up @@ -549,4 +550,35 @@ void CommandCompletions::Registers(CommandInterpreter &interpreter,
request.TryCompleteCurrentArg(reg_prefix + reg_info->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);
}
}
32 changes: 32 additions & 0 deletions lldb/source/Commands/CommandObjectBreakpoint.cpp
Expand Up @@ -819,6 +819,14 @@ class CommandObjectBreakpointModify : public CommandObjectParsed {

~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; }

protected:
Expand Down Expand Up @@ -885,6 +893,14 @@ class CommandObjectBreakpointEnable : public CommandObjectParsed {

~CommandObjectBreakpointEnable() override = default;

void
HandleArgumentCompletion(CompletionRequest &request,
OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
request, nullptr);
}

protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target &target = GetSelectedOrDummyTarget();
Expand Down Expand Up @@ -993,6 +1009,14 @@ the second re-enables the first location.");

~CommandObjectBreakpointDisable() override = default;

void
HandleArgumentCompletion(CompletionRequest &request,
OptionElementVector &opt_element_vector) override {
CommandCompletions::InvokeCommonCompletionCallbacks(
GetCommandInterpreter(), CommandCompletions::eBreakpointCompletion,
request, nullptr);
}

protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
Target &target = GetSelectedOrDummyTarget();
Expand Down Expand Up @@ -1371,6 +1395,14 @@ class CommandObjectBreakpointDelete : public CommandObjectParsed {

~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; }

class CommandOptions : public Options {
Expand Down
37 changes: 37 additions & 0 deletions lldb/test/API/functionalities/completion/TestCompletion.py
Expand Up @@ -477,3 +477,40 @@ def test_register_read_and_write_on_x86(self):
# register write can only take exact one register name as argument
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'])

0 comments on commit 0e50b9a

Please sign in to comment.