[Lldb-commits] [lldb] 4d78881 - [LLDB]Provide clearer error message for invalid commands. (#111891)

via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 15 07:14:51 PDT 2024


Author: Vy Nguyen
Date: 2024-10-15T10:14:48-04:00
New Revision: 4d788814061a1003f577e293f2cd74b30223e050

URL: https://github.com/llvm/llvm-project/commit/4d788814061a1003f577e293f2cd74b30223e050
DIFF: https://github.com/llvm/llvm-project/commit/4d788814061a1003f577e293f2cd74b30223e050.diff

LOG: [LLDB]Provide clearer error message for invalid commands. (#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.

Added: 
    lldb/test/Shell/Commands/command-wrong-subcommand-error-msg.test

Modified: 
    lldb/include/lldb/Interpreter/CommandObjectMultiword.h
    lldb/source/Commands/CommandObjectMultiword.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
index bceb7f0e51edb6..c5e366e682600f 100644
--- a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
+++ b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h
@@ -70,6 +70,8 @@ class CommandObjectMultiword : public CommandObject {
     return m_subcommand_dict;
   }
 
+  std::string GetSubcommandsHintText();
+
   CommandObject::CommandMap m_subcommand_dict;
   bool m_can_be_removed;
 };

diff  --git a/lldb/source/Commands/CommandObjectMultiword.cpp b/lldb/source/Commands/CommandObjectMultiword.cpp
index 4efa5652a71703..ab3369c6f9c20a 100644
--- a/lldb/source/Commands/CommandObjectMultiword.cpp
+++ b/lldb/source/Commands/CommandObjectMultiword.cpp
@@ -194,28 +194,54 @@ void CommandObjectMultiword::Execute(const char *args_string,
 
   std::string error_msg;
   const size_t num_subcmd_matches = matches.GetSize();
-  if (num_subcmd_matches > 0)
+  if (num_subcmd_matches > 0) {
     error_msg.assign("ambiguous command ");
-  else
-    error_msg.assign("invalid command ");
-
-  error_msg.append("'");
-  error_msg.append(std::string(GetCommandName()));
-  error_msg.append(" ");
-  error_msg.append(std::string(sub_command));
-  error_msg.append("'.");
+    error_msg.append("'");
+    error_msg.append(std::string(GetCommandName()));
+    error_msg.append(" ");
+    error_msg.append(std::string(sub_command));
+    error_msg.append("'.");
 
-  if (num_subcmd_matches > 0) {
     error_msg.append(" Possible completions:");
     for (const std::string &match : matches) {
       error_msg.append("\n\t");
       error_msg.append(match);
     }
+  } else {
+    // Try to offer some alternatives to help correct the command.
+    error_msg.assign(
+        llvm::Twine("\"" + sub_command + "\" is not a valid subcommand of \"" +
+                    GetCommandName() + "\"." + GetSubcommandsHintText() +
+                    " Use \"help " + GetCommandName() + "\" to find out more.")
+            .str());
   }
   error_msg.append("\n");
   result.AppendRawError(error_msg.c_str());
 }
 
+std::string CommandObjectMultiword::GetSubcommandsHintText() {
+  if (m_subcommand_dict.empty())
+    return "";
+  const size_t maxCount = 5;
+  size_t i = 0;
+  std::string buffer = " Valid subcommand";
+  buffer.append(m_subcommand_dict.size() > 1 ? "s are:" : " is");
+  CommandMap::iterator pos;
+  for (pos = m_subcommand_dict.begin();
+       pos != m_subcommand_dict.end() && i < maxCount; ++pos, ++i) {
+    buffer.append(" ");
+    buffer.append(pos->first);
+    buffer.append(",");
+  }
+  if (i < m_subcommand_dict.size())
+    buffer.append(" and others");
+  else
+    buffer.pop_back();
+
+  buffer.append(".");
+  return buffer;
+}
+
 void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
   // First time through here, generate the help text for the object and push it
   // to the return result object as well

diff  --git a/lldb/test/Shell/Commands/command-wrong-subcommand-error-msg.test b/lldb/test/Shell/Commands/command-wrong-subcommand-error-msg.test
new file mode 100644
index 00000000000000..445f8d1c8361c4
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-wrong-subcommand-error-msg.test
@@ -0,0 +1,8 @@
+# UNSUPPORTED: system-windows
+#
+# RUN: %clang_host -g -O0 %S/Inputs/main.c -o %t.out
+# RUN: not %lldb -b -o 'breakpoint foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix BP-MSG
+# RUN: not %lldb -b -o 'watchpoint set foo' %t.out -o exit 2>&1 | FileCheck %s --check-prefix WP-MSG
+# CHECK: at main.c:2:21
+# 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.
+# WP-MSG: "foo" is not a valid subcommand of "watchpoint set". Valid subcommands are: expression, variable. Use "help watchpoint set" to find out more.
\ No newline at end of file


        


More information about the lldb-commits mailing list