Skip to content

Commit 4493bf0

Browse files
committed
[LLDB]Provide clearer error message for invalid commands.
Sometimes users (esp. gdb-longtime users) accidentally use GDB syntax, such as `breakpoint foo`, and they would get an error message from LLDB saying simply `Invalid command "breakpoint foo"`, which is not very helpful. This change provides additional suggestions to help correcting the mistake.
1 parent 36c34ec commit 4493bf0

File tree

3 files changed

+36
-10
lines changed

3 files changed

+36
-10
lines changed

lldb/include/lldb/Interpreter/CommandObjectMultiword.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class CommandObjectMultiword : public CommandObject {
7070
return m_subcommand_dict;
7171
}
7272

73+
std::string GetTopSubcommands(int count);
74+
7375
CommandObject::CommandMap m_subcommand_dict;
7476
bool m_can_be_removed;
7577
};

lldb/source/Commands/CommandObjectMultiword.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,28 +194,50 @@ void CommandObjectMultiword::Execute(const char *args_string,
194194

195195
std::string error_msg;
196196
const size_t num_subcmd_matches = matches.GetSize();
197-
if (num_subcmd_matches > 0)
197+
if (num_subcmd_matches > 0) {
198198
error_msg.assign("ambiguous command ");
199-
else
200-
error_msg.assign("invalid command ");
201-
202-
error_msg.append("'");
203-
error_msg.append(std::string(GetCommandName()));
204-
error_msg.append(" ");
205-
error_msg.append(std::string(sub_command));
206-
error_msg.append("'.");
199+
error_msg.append("'");
200+
error_msg.append(std::string(GetCommandName()));
201+
error_msg.append(" ");
202+
error_msg.append(std::string(sub_command));
203+
error_msg.append("'.");
207204

208-
if (num_subcmd_matches > 0) {
209205
error_msg.append(" Possible completions:");
210206
for (const std::string &match : matches) {
211207
error_msg.append("\n\t");
212208
error_msg.append(match);
213209
}
210+
} else {
211+
// Rather than simply complaining about the invalid (sub) command,
212+
// try to offer some alternatives.
213+
// This is especially useful for cases where the user types something
214+
// seamingly trivial, such as `breakpoint foo`.
215+
error_msg.assign(
216+
llvm::Twine("'" + sub_command + "' is not a valid subcommand of \"" +
217+
GetCommandName() + "\". Valid subcommands are " +
218+
GetTopSubcommands(/*count=*/5) + ". Use \"help " +
219+
GetCommandName() + "\" to find out more.")
220+
.str());
214221
}
215222
error_msg.append("\n");
216223
result.AppendRawError(error_msg.c_str());
217224
}
218225

226+
std::string CommandObjectMultiword::GetTopSubcommands(int count) {
227+
if (m_subcommand_dict.empty())
228+
return "<NONE>";
229+
std::string buffer = "{";
230+
CommandMap::iterator pos;
231+
for (pos = m_subcommand_dict.begin();
232+
pos != m_subcommand_dict.end() && count > 0; ++pos, --count) {
233+
buffer.append("'");
234+
buffer.append(pos->first);
235+
buffer.append("',");
236+
}
237+
buffer.append("...}");
238+
return buffer;
239+
}
240+
219241
void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
220242
// First time through here, generate the help text for the object and push it
221243
// to the return result object as well

lldb/test/Shell/Commands/command-breakpoint-col.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
# RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out
44
# RUN: %lldb -b -o 'help breakpoint set' -o 'breakpoint set -f main.c -l 2 -u 21' %t.out | FileCheck %s --check-prefix HELP --check-prefix CHECK
55
# RUN: %lldb -b -o 'help _regexp-break' -o 'b main.c:2:21' %t.out | FileCheck %s --check-prefix HELP-REGEX --check-prefix CHECK
6+
# RUN: not %lldb -b -o 'breakpoint foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix ERROR-MSG
67
# HELP: -u <column> ( --column <column> )
78
# HELP: Specifies the column number on which to set this breakpoint.
89
# HELP-REGEX: _regexp-break <filename>:<linenum>:<colnum>
910
# HELP-REGEX: main.c:12:21{{.*}}Break at line 12 and column 21 of main.c
1011
# CHECK: at main.c:2:21
12+
# ERROR-MSG: 'foo' is not a valid subcommand of "breakpoint". Valid subcommands are {'clear','command','delete','disable','enable',...}. Use "help breakpoint" to find out more.

0 commit comments

Comments
 (0)