Skip to content

Commit 2390919

Browse files
oontvooDanielCChen
authored andcommitted
[LLDB]Provide clearer error message for invalid commands. (llvm#111891)
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 ee780c8 commit 2390919

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-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 GetSubcommandsHintText();
74+
7375
CommandObject::CommandMap m_subcommand_dict;
7476
bool m_can_be_removed;
7577
};

lldb/source/Commands/CommandObjectMultiword.cpp

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,28 +194,54 @@ 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+
// Try to offer some alternatives to help correct the command.
212+
error_msg.assign(
213+
llvm::Twine("\"" + sub_command + "\" is not a valid subcommand of \"" +
214+
GetCommandName() + "\"." + GetSubcommandsHintText() +
215+
" Use \"help " + GetCommandName() + "\" to find out more.")
216+
.str());
214217
}
215218
error_msg.append("\n");
216219
result.AppendRawError(error_msg.c_str());
217220
}
218221

222+
std::string CommandObjectMultiword::GetSubcommandsHintText() {
223+
if (m_subcommand_dict.empty())
224+
return "";
225+
const size_t maxCount = 5;
226+
size_t i = 0;
227+
std::string buffer = " Valid subcommand";
228+
buffer.append(m_subcommand_dict.size() > 1 ? "s are:" : " is");
229+
CommandMap::iterator pos;
230+
for (pos = m_subcommand_dict.begin();
231+
pos != m_subcommand_dict.end() && i < maxCount; ++pos, ++i) {
232+
buffer.append(" ");
233+
buffer.append(pos->first);
234+
buffer.append(",");
235+
}
236+
if (i < m_subcommand_dict.size())
237+
buffer.append(" and others");
238+
else
239+
buffer.pop_back();
240+
241+
buffer.append(".");
242+
return buffer;
243+
}
244+
219245
void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
220246
// First time through here, generate the help text for the object and push it
221247
// to the return result object as well
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# UNSUPPORTED: system-windows
2+
#
3+
# RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out
4+
# RUN: not %lldb -b -o 'breakpoint foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix BP-MSG
5+
# RUN: not %lldb -b -o 'watchpoint set foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix WP-MSG
6+
# CHECK: at main.c:2:21
7+
# BP-MSG: "foo" is not a valid subcommand of "breakpoint". Valid subcommands are: clear, command, delete, disable, enable, and others. Use "help breakpoint" to find out more.
8+
# WP-MSG: "foo" is not a valid subcommand of "watchpoint set". Valid subcommands are: expression, variable. Use "help watchpoint set" to find out more.

0 commit comments

Comments
 (0)