Skip to content

Commit 22e63cb

Browse files
MrHateTeemperor
authored andcommitted
[lldb] tab completion for breakpoint names
1. created a common completion for breakpoint names; 2. bound the breakpoint name common completion with eArgTypeBreakpointName; 3. implemented the dedicated completion for breakpoint read -N. Reviewed By: JDevlieghere Differential Revision: https://reviews.llvm.org/D80693
1 parent ac63959 commit 22e63cb

File tree

7 files changed

+153
-4
lines changed

7 files changed

+153
-4
lines changed

lldb/include/lldb/Interpreter/CommandCompletions.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ class CommandCompletions {
4444
eStopHookIDCompletion = (1u << 16),
4545
eThreadIndexCompletion = (1u << 17),
4646
eWatchPointIDCompletion = (1u << 18),
47+
eBreakpointNameCompletion = (1u << 19),
4748
// This item serves two purposes. It is the last element in the enum, so
4849
// you can add custom enums starting from here in your Option class. Also
4950
// if you & in this bit the base code will not process the option.
50-
eCustomCompletion = (1u << 19)
51+
eCustomCompletion = (1u << 20)
5152
};
5253

5354
static bool InvokeCommonCompletionCallbacks(
@@ -101,6 +102,10 @@ class CommandCompletions {
101102
static void Breakpoints(CommandInterpreter &interpreter,
102103
CompletionRequest &request, SearchFilter *searcher);
103104

105+
static void BreakpointNames(CommandInterpreter &interpreter,
106+
CompletionRequest &request,
107+
SearchFilter *searcher);
108+
104109
static void ProcessPluginNames(CommandInterpreter &interpreter,
105110
CompletionRequest &request,
106111
SearchFilter *searcher);

lldb/source/Commands/CommandCompletions.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks(
7070
{eStopHookIDCompletion, CommandCompletions::StopHookIDs},
7171
{eThreadIndexCompletion, CommandCompletions::ThreadIndexes},
7272
{eWatchPointIDCompletion, CommandCompletions::WatchPointIDs},
73+
{eBreakpointNameCompletion, CommandCompletions::BreakpointNames},
7374
{eNoCompletion, nullptr} // This one has to be last in the list.
7475
};
7576

@@ -617,13 +618,26 @@ void CommandCompletions::Breakpoints(CommandInterpreter &interpreter,
617618
}
618619
}
619620

621+
void CommandCompletions::BreakpointNames(CommandInterpreter &interpreter,
622+
CompletionRequest &request,
623+
SearchFilter *searcher) {
624+
lldb::TargetSP target = interpreter.GetDebugger().GetSelectedTarget();
625+
if (!target)
626+
return;
627+
628+
std::vector<std::string> name_list;
629+
target->GetBreakpointNames(name_list);
630+
631+
for (const std::string &name : name_list)
632+
request.TryCompleteCurrentArg(name);
633+
}
634+
620635
void CommandCompletions::ProcessPluginNames(CommandInterpreter &interpreter,
621636
CompletionRequest &request,
622637
SearchFilter *searcher) {
623638
PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(),
624639
request);
625640
}
626-
627641
void CommandCompletions::DisassemblyFlavors(CommandInterpreter &interpreter,
628642
CompletionRequest &request,
629643
SearchFilter *searcher) {

lldb/source/Commands/CommandObjectBreakpoint.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2097,7 +2097,79 @@ class CommandObjectBreakpointRead : public CommandObjectParsed {
20972097
return llvm::makeArrayRef(g_breakpoint_read_options);
20982098
}
20992099

2100-
// Instance variables to hold the values for command options.
2100+
void HandleOptionArgumentCompletion(
2101+
CompletionRequest &request, OptionElementVector &opt_element_vector,
2102+
int opt_element_index, CommandInterpreter &interpreter) override {
2103+
int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2104+
int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2105+
2106+
switch (GetDefinitions()[opt_defs_index].short_option) {
2107+
case 'f':
2108+
CommandCompletions::InvokeCommonCompletionCallbacks(
2109+
interpreter, CommandCompletions::eDiskFileCompletion, request,
2110+
nullptr);
2111+
break;
2112+
2113+
case 'N':
2114+
llvm::Optional<FileSpec> file_spec;
2115+
const llvm::StringRef dash_f("-f");
2116+
for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2117+
if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2118+
file_spec.emplace(
2119+
request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2120+
break;
2121+
}
2122+
}
2123+
if (!file_spec)
2124+
return;
2125+
2126+
FileSystem::Instance().Resolve(*file_spec);
2127+
Status error;
2128+
StructuredData::ObjectSP input_data_sp =
2129+
StructuredData::ParseJSONFromFile(*file_spec, error);
2130+
if (!error.Success())
2131+
return;
2132+
2133+
StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2134+
if (!bkpt_array)
2135+
return;
2136+
2137+
const size_t num_bkpts = bkpt_array->GetSize();
2138+
for (size_t i = 0; i < num_bkpts; i++) {
2139+
StructuredData::ObjectSP bkpt_object_sp =
2140+
bkpt_array->GetItemAtIndex(i);
2141+
if (!bkpt_object_sp)
2142+
return;
2143+
2144+
StructuredData::Dictionary *bkpt_dict =
2145+
bkpt_object_sp->GetAsDictionary();
2146+
if (!bkpt_dict)
2147+
return;
2148+
2149+
StructuredData::ObjectSP bkpt_data_sp =
2150+
bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2151+
if (!bkpt_data_sp)
2152+
return;
2153+
2154+
bkpt_dict = bkpt_data_sp->GetAsDictionary();
2155+
if (!bkpt_dict)
2156+
return;
2157+
2158+
StructuredData::Array *names_array;
2159+
2160+
if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2161+
return;
2162+
2163+
size_t num_names = names_array->GetSize();
2164+
2165+
for (size_t i = 0; i < num_names; i++) {
2166+
llvm::StringRef name;
2167+
if (names_array->GetItemAtIndexAsString(i, name))
2168+
request.TryCompleteCurrentArg(name);
2169+
}
2170+
}
2171+
}
2172+
}
21012173

21022174
std::string m_filename;
21032175
std::vector<std::string> m_names;

lldb/source/Interpreter/CommandObject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = {
10411041
{ eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" },
10421042
{ eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr },
10431043
{ eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr },
1044-
{ eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
1044+
{ eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eBreakpointNameCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
10451045
{ eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." },
10461046
{ eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." },
10471047
{ eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." },

lldb/test/API/functionalities/completion/TestCompletion.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,3 +644,21 @@ def test_complete_breakpoint_with_ids(self):
644644
['1',
645645
'2'])
646646

647+
def test_complete_breakpoint_with_names(self):
648+
self.build()
649+
target = self.dbg.CreateTarget(self.getBuildArtifact('a.out'))
650+
self.assertTrue(target, VALID_TARGET)
651+
652+
# test breakpoint read dedicated
653+
self.complete_from_to('breakpoint read -N ', 'breakpoint read -N ')
654+
self.complete_from_to('breakpoint read -f breakpoints.json -N ', ['mm'])
655+
self.complete_from_to('breakpoint read -f breakpoints.json -N n', 'breakpoint read -f breakpoints.json -N n')
656+
self.complete_from_to('breakpoint read -f breakpoints_invalid.json -N ', 'breakpoint read -f breakpoints_invalid.json -N ')
657+
658+
# test common breapoint name completion
659+
bp1 = target.BreakpointCreateByName('main', 'a.out')
660+
self.assertTrue(bp1)
661+
self.assertEqual(bp1.GetNumLocations(), 1)
662+
self.complete_from_to('breakpoint set -N n', 'breakpoint set -N n')
663+
self.assertTrue(bp1.AddNameWithErrorHandling("nn"))
664+
self.complete_from_to('breakpoint set -N ', 'breakpoint set -N nn')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[
2+
{
3+
"Breakpoint": {
4+
"BKPTOptions": {
5+
"AutoContinue": false,
6+
"ConditionText": "",
7+
"EnabledState": true,
8+
"IgnoreCount": 0,
9+
"OneShotState": false
10+
},
11+
"BKPTResolver": {
12+
"Options": {
13+
"NameMask": [
14+
56
15+
],
16+
"Offset": 0,
17+
"SkipPrologue": true,
18+
"SymbolNames": [
19+
"main"
20+
]
21+
},
22+
"Type": "SymbolName"
23+
},
24+
"Hardware": false,
25+
"Names": [
26+
"mm"
27+
],
28+
"SearchFilter": {
29+
"Options": {},
30+
"Type": "Unconstrained"
31+
}
32+
}
33+
}
34+
]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{
3+
"Breakpoint": {
4+
}
5+
}
6+
]

0 commit comments

Comments
 (0)