Author: Jim Ingham
Date: 2022-06-27T15:14:41-07:00
New Revision: c1b07d617705dfdb3aabbdda51c1a40d99f7cc1a

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

LOG: Have CommandObjectParsed check for "commands that take no arguments".

This is currently being done in an ad hoc way, and so for some
commands it isn't being checked.  We have the info to make this check,
since commands are supposed to add their arguments to the m_arguments
field of the CommandObject.  This change uses that info to check whether
the command received arguments in error.

A handful of commands weren't defining their argument types, I also had
to fix them.  And a bunch of commands were checking for arguments by
hand, so I removed those checks in favor of the CommandObject one.  That
also meant I had to change some tests that were checking for the ad hoc
error outputs.

Differential Revision: https://reviews.llvm.org/D128453

Added: 
    

Modified: 
    lldb/include/lldb/lldb-enumerations.h
    lldb/source/API/SBCommandInterpreter.cpp
    lldb/source/Commands/CommandObjectCommands.cpp
    lldb/source/Commands/CommandObjectFrame.cpp
    lldb/source/Commands/CommandObjectGUI.cpp
    lldb/source/Commands/CommandObjectPlatform.cpp
    lldb/source/Commands/CommandObjectProcess.cpp
    lldb/source/Commands/CommandObjectQuit.cpp
    lldb/source/Commands/CommandObjectReproducer.cpp
    lldb/source/Commands/CommandObjectSource.cpp
    lldb/source/Commands/CommandObjectTarget.cpp
    lldb/source/Commands/CommandObjectThreadUtil.cpp
    lldb/source/Commands/CommandObjectTrace.cpp
    lldb/source/Commands/CommandObjectType.cpp
    lldb/source/Commands/CommandObjectVersion.cpp
    lldb/source/Interpreter/CommandObject.cpp
    
lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
    
lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
    lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
    lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
    lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
    lldb/test/API/commands/target/basic/TestTargetCommand.py
    lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
    lldb/test/API/commands/version/TestVersion.py
    
lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
    lldb/test/API/functionalities/completion/TestCompletion.py

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/lldb-enumerations.h 
b/lldb/include/lldb/lldb-enumerations.h
index 74a82f6216c7f..e1e3332eddc58 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -603,6 +603,11 @@ enum CommandArgumentType {
   eArgTypeModuleUUID,
   eArgTypeSaveCoreStyle,
   eArgTypeLogHandler,
+  eArgTypeSEDStylePair,
+  eArgTypeRecognizerID,
+  eArgTypeConnectURL,
+  eArgTypeTargetID,
+  eArgTypeStopHookID,
   eArgTypeLastArg // Always keep this entry as the last entry in this
                   // enumeration!!
 };

diff  --git a/lldb/source/API/SBCommandInterpreter.cpp 
b/lldb/source/API/SBCommandInterpreter.cpp
index a19ad48dde042..aa46f1085dc9f 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -47,6 +47,10 @@ class CommandPluginInterfaceImplementation : public 
CommandObjectParsed {
         auto_repeat_command == nullptr
             ? llvm::None
             : llvm::Optional<std::string>(auto_repeat_command);
+    // We don't know whether any given command coming from this interface takes
+    // arguments or not so here we're just disabling the basic args check.
+    CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar};
+    m_arguments.push_back({none_arg});
   }
 
   bool IsRemovable() const override { return true; }

diff  --git a/lldb/source/Commands/CommandObjectCommands.cpp 
b/lldb/source/Commands/CommandObjectCommands.cpp
index 2334759ea0f47..39c7207bbdbec 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -824,6 +824,8 @@ a number follows 'f':"
         R"(
 
     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
+    CommandArgumentData thread_arg{eArgTypeSEDStylePair, eArgRepeatOptional};
+    m_arguments.push_back({thread_arg});
   }
 
   ~CommandObjectCommandsAddRegex() override = default;
@@ -1664,11 +1666,6 @@ class CommandObjectCommandsScriptList : public 
CommandObjectParsed {
   ~CommandObjectCommandsScriptList() override = default;
 
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (command.GetArgumentCount() != 0) {
-      result.AppendError("'command script list' doesn't take any arguments");
-      return false;
-    }
-
     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
 
     result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -1689,11 +1686,6 @@ class CommandObjectCommandsScriptClear : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (command.GetArgumentCount() != 0) {
-      result.AppendError("'command script clear' doesn't take any arguments");
-      return false;
-    }
-
     m_interpreter.RemoveAllUser();
 
     result.SetStatus(eReturnStatusSuccessFinishResult);

diff  --git a/lldb/source/Commands/CommandObjectFrame.cpp 
b/lldb/source/Commands/CommandObjectFrame.cpp
index 93c41ee5a0be3..9f2c79d84ad4c 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -924,7 +924,11 @@ class CommandObjectFrameRecognizerDelete : public 
CommandObjectParsed {
 public:
   CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "frame recognizer delete",
-                            "Delete an existing frame recognizer.", nullptr) {}
+                            "Delete an existing frame recognizer by id.",
+                            nullptr) {
+    CommandArgumentData thread_arg{eArgTypeRecognizerID, eArgRepeatPlain};
+    m_arguments.push_back({thread_arg});
+  }
 
   ~CommandObjectFrameRecognizerDelete() override = default;
 

diff  --git a/lldb/source/Commands/CommandObjectGUI.cpp 
b/lldb/source/Commands/CommandObjectGUI.cpp
index 86c47a2f06349..a63d1718610c1 100644
--- a/lldb/source/Commands/CommandObjectGUI.cpp
+++ b/lldb/source/Commands/CommandObjectGUI.cpp
@@ -26,22 +26,18 @@ CommandObjectGUI::~CommandObjectGUI() = default;
 
 bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {
 #if LLDB_ENABLE_CURSES
-  if (args.GetArgumentCount() == 0) {
-    Debugger &debugger = GetDebugger();
-
-    File &input = debugger.GetInputFile();
-    File &output = debugger.GetOutputFile();
-    if (input.GetStream() && output.GetStream() && input.GetIsRealTerminal() &&
-        input.GetIsInteractive()) {
-      IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger));
-      if (io_handler_sp)
-        debugger.RunIOHandlerAsync(io_handler_sp);
-      result.SetStatus(eReturnStatusSuccessFinishResult);
-    } else {
-      result.AppendError("the gui command requires an interactive terminal.");
-    }
+  Debugger &debugger = GetDebugger();
+
+  File &input = debugger.GetInputFile();
+  File &output = debugger.GetOutputFile();
+  if (input.GetStream() && output.GetStream() && input.GetIsRealTerminal() &&
+      input.GetIsInteractive()) {
+    IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger));
+    if (io_handler_sp)
+      debugger.RunIOHandlerAsync(io_handler_sp);
+    result.SetStatus(eReturnStatusSuccessFinishResult);
   } else {
-    result.AppendError("the gui command takes no arguments.");
+    result.AppendError("the gui command requires an interactive terminal.");
   }
   return true;
 #else

diff  --git a/lldb/source/Commands/CommandObjectPlatform.cpp 
b/lldb/source/Commands/CommandObjectPlatform.cpp
index 774ef6c6191e2..42b19db5efc4e 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -150,6 +150,8 @@ class CommandObjectPlatformSelect : public 
CommandObjectParsed {
   {
     m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
     m_option_group.Finalize();
+    CommandArgumentData platform_arg{eArgTypePlatform, eArgRepeatPlain};
+    m_arguments.push_back({platform_arg});
   }
 
   ~CommandObjectPlatformSelect() override = default;
@@ -271,7 +273,10 @@ class CommandObjectPlatformConnect : public 
CommandObjectParsed {
       : CommandObjectParsed(
             interpreter, "platform connect",
             "Select the current platform by providing a connection URL.",
-            "platform connect <connect-url>", 0) {}
+            "platform connect <connect-url>", 0) {
+    CommandArgumentData platform_arg{eArgTypeConnectURL, eArgRepeatPlain};
+    m_arguments.push_back({platform_arg});
+  }
 
   ~CommandObjectPlatformConnect() override = default;
 
@@ -415,7 +420,10 @@ class CommandObjectPlatformMkDir : public 
CommandObjectParsed {
   CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "platform mkdir",
                             "Make a new directory on the remote end.", nullptr,
-                            0) {}
+                            0) {
+    CommandArgumentData thread_arg{eArgTypePath, eArgRepeatPlain};
+    m_arguments.push_back({thread_arg});
+  }
 
   ~CommandObjectPlatformMkDir() override = default;
 
@@ -461,7 +469,10 @@ class CommandObjectPlatformFOpen : public 
CommandObjectParsed {
 public:
   CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "platform file open",
-                            "Open a file on the remote end.", nullptr, 0) {}
+                            "Open a file on the remote end.", nullptr, 0) {
+    CommandArgumentData path_arg{eArgTypePath, eArgRepeatPlain};
+    m_arguments.push_back({path_arg});
+  }
 
   ~CommandObjectPlatformFOpen() override = default;
 
@@ -521,7 +532,10 @@ class CommandObjectPlatformFClose : public 
CommandObjectParsed {
 public:
   CommandObjectPlatformFClose(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "platform file close",
-                            "Close a file on the remote end.", nullptr, 0) {}
+                            "Close a file on the remote end.", nullptr, 0) {
+    CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    m_arguments.push_back({path_arg});
+  }
 
   ~CommandObjectPlatformFClose() override = default;
 
@@ -562,7 +576,10 @@ class CommandObjectPlatformFRead : public 
CommandObjectParsed {
   CommandObjectPlatformFRead(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "platform file read",
                             "Read data from a file on the remote end.", 
nullptr,
-                            0) {}
+                            0) {
+    CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    m_arguments.push_back({path_arg});
+  }
 
   ~CommandObjectPlatformFRead() override = default;
 
@@ -655,7 +672,10 @@ class CommandObjectPlatformFWrite : public 
CommandObjectParsed {
   CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "platform file write",
                             "Write data to a file on the remote end.", nullptr,
-                            0) {}
+                            0) {
+    CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    m_arguments.push_back({path_arg});
+  }
 
   ~CommandObjectPlatformFWrite() override = default;
 
@@ -1070,6 +1090,10 @@ class CommandObjectPlatformPutFile : public 
CommandObjectParsed {
     Relative source file paths are resolved against lldb's local working 
directory.
 
     Omitting the destination places the file in the platform working 
directory.)");
+    CommandArgumentData source_arg{eArgTypePath, eArgRepeatPlain};
+    CommandArgumentData path_arg{eArgTypePath, eArgRepeatOptional};
+    m_arguments.push_back({source_arg});
+    m_arguments.push_back({path_arg});
   }
 
   ~CommandObjectPlatformPutFile() override = default;
@@ -1121,6 +1145,8 @@ class CommandObjectPlatformProcessLaunch : public 
CommandObjectParsed {
                             eCommandRequiresTarget | eCommandTryTargetAPILock) 
{
     m_all_options.Append(&m_options);
     m_all_options.Finalize();
+    CommandArgumentData run_arg_arg{eArgTypeRunArgs, eArgRepeatStar};
+    m_arguments.push_back({run_arg_arg});
   }
 
   ~CommandObjectPlatformProcessLaunch() override = default;
@@ -1229,83 +1255,78 @@ class CommandObjectPlatformProcessList : public 
CommandObjectParsed {
 
     if (platform_sp) {
       Status error;
-      if (args.GetArgumentCount() == 0) {
-        if (platform_sp) {
-          Stream &ostrm = result.GetOutputStream();
-
-          lldb::pid_t pid =
-              m_options.match_info.GetProcessInfo().GetProcessID();
-          if (pid != LLDB_INVALID_PROCESS_ID) {
-            ProcessInstanceInfo proc_info;
-            if (platform_sp->GetProcessInfo(pid, proc_info)) {
-              ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
-                                                   m_options.verbose);
-              proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
-                                       m_options.show_args, m_options.verbose);
-              result.SetStatus(eReturnStatusSuccessFinishResult);
-            } else {
-              result.AppendErrorWithFormat(
-                  "no process found with pid = %" PRIu64 "\n", pid);
-            }
+      if (platform_sp) {
+        Stream &ostrm = result.GetOutputStream();
+
+        lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
+        if (pid != LLDB_INVALID_PROCESS_ID) {
+          ProcessInstanceInfo proc_info;
+          if (platform_sp->GetProcessInfo(pid, proc_info)) {
+            ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
+                                                 m_options.verbose);
+            proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
+                                     m_options.show_args, m_options.verbose);
+            result.SetStatus(eReturnStatusSuccessFinishResult);
           } else {
-            ProcessInstanceInfoList proc_infos;
-            const uint32_t matches =
-                platform_sp->FindProcesses(m_options.match_info, proc_infos);
-            const char *match_desc = nullptr;
-            const char *match_name =
-                m_options.match_info.GetProcessInfo().GetName();
-            if (match_name && match_name[0]) {
-              switch (m_options.match_info.GetNameMatchType()) {
-              case NameMatch::Ignore:
-                break;
-              case NameMatch::Equals:
-                match_desc = "matched";
-                break;
-              case NameMatch::Contains:
-                match_desc = "contained";
-                break;
-              case NameMatch::StartsWith:
-                match_desc = "started with";
-                break;
-              case NameMatch::EndsWith:
-                match_desc = "ended with";
-                break;
-              case NameMatch::RegularExpression:
-                match_desc = "matched the regular expression";
-                break;
-              }
+            result.AppendErrorWithFormat(
+                "no process found with pid = %" PRIu64 "\n", pid);
+          }
+        } else {
+          ProcessInstanceInfoList proc_infos;
+          const uint32_t matches =
+              platform_sp->FindProcesses(m_options.match_info, proc_infos);
+          const char *match_desc = nullptr;
+          const char *match_name =
+              m_options.match_info.GetProcessInfo().GetName();
+          if (match_name && match_name[0]) {
+            switch (m_options.match_info.GetNameMatchType()) {
+            case NameMatch::Ignore:
+              break;
+            case NameMatch::Equals:
+              match_desc = "matched";
+              break;
+            case NameMatch::Contains:
+              match_desc = "contained";
+              break;
+            case NameMatch::StartsWith:
+              match_desc = "started with";
+              break;
+            case NameMatch::EndsWith:
+              match_desc = "ended with";
+              break;
+            case NameMatch::RegularExpression:
+              match_desc = "matched the regular expression";
+              break;
             }
+          }
 
-            if (matches == 0) {
-              if (match_desc)
-                result.AppendErrorWithFormatv(
-                    "no processes were found that {0} \"{1}\" on the \"{2}\" "
-                    "platform\n",
-                    match_desc, match_name, platform_sp->GetName());
-              else
-                result.AppendErrorWithFormatv(
-                    "no processes were found on the \"{0}\" platform\n",
-                    platform_sp->GetName());
-            } else {
-              result.AppendMessageWithFormatv(
-                  "{0} matching process{1} found on \"{2}\"", matches,
-                  matches > 1 ? "es were" : " was", platform_sp->GetName());
-              if (match_desc)
-                result.AppendMessageWithFormat(" whose name %s \"%s\"",
-                                               match_desc, match_name);
-              result.AppendMessageWithFormat("\n");
-              ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
-                                                   m_options.verbose);
-              for (uint32_t i = 0; i < matches; ++i) {
-                proc_infos[i].DumpAsTableRow(
-                    ostrm, platform_sp->GetUserIDResolver(),
-                    m_options.show_args, m_options.verbose);
-              }
+          if (matches == 0) {
+            if (match_desc)
+              result.AppendErrorWithFormatv(
+                  "no processes were found that {0} \"{1}\" on the \"{2}\" "
+                  "platform\n",
+                  match_desc, match_name, platform_sp->GetName());
+            else
+              result.AppendErrorWithFormatv(
+                  "no processes were found on the \"{0}\" platform\n",
+                  platform_sp->GetName());
+          } else {
+            result.AppendMessageWithFormatv(
+                "{0} matching process{1} found on \"{2}\"", matches,
+                matches > 1 ? "es were" : " was", platform_sp->GetName());
+            if (match_desc)
+              result.AppendMessageWithFormat(" whose name %s \"%s\"",
+                                             match_desc, match_name);
+            result.AppendMessageWithFormat("\n");
+            ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
+                                                 m_options.verbose);
+            for (uint32_t i = 0; i < matches; ++i) {
+              proc_infos[i].DumpAsTableRow(
+                  ostrm, platform_sp->GetUserIDResolver(), m_options.show_args,
+                  m_options.verbose);
             }
           }
         }
-      } else {
-        result.AppendError("invalid args: process list takes only options\n");
       }
     } else {
       result.AppendError("no platform is selected\n");
@@ -1737,7 +1758,10 @@ class CommandObjectPlatformShell : public 
CommandObjectRaw {
   CommandObjectPlatformShell(CommandInterpreter &interpreter)
       : CommandObjectRaw(interpreter, "platform shell",
                          "Run a shell command on the current platform.",
-                         "platform shell <shell-command>", 0) {}
+                         "platform shell <shell-command>", 0) {
+    CommandArgumentData thread_arg{eArgTypeNone, eArgRepeatStar};
+    m_arguments.push_back({thread_arg});
+  }
 
   ~CommandObjectPlatformShell() override = default;
 
@@ -1824,7 +1848,12 @@ class CommandObjectPlatformInstall : public 
CommandObjectParsed {
       : CommandObjectParsed(
             interpreter, "platform target-install",
             "Install a target (bundle or executable file) to the remote end.",
-            "platform target-install <local-thing> <remote-sandbox>", 0) {}
+            "platform target-install <local-thing> <remote-sandbox>", 0) {
+    CommandArgumentData local_arg{eArgTypePath, eArgRepeatPlain};
+    CommandArgumentData remote_arg{eArgTypePath, eArgRepeatPlain};
+    m_arguments.push_back({local_arg});
+    m_arguments.push_back({remote_arg});
+  }
 
   ~CommandObjectPlatformInstall() override = default;
 

diff  --git a/lldb/source/Commands/CommandObjectProcess.cpp 
b/lldb/source/Commands/CommandObjectProcess.cpp
index 2f5f649636aef..c76ae99057f2a 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -414,12 +414,6 @@ class CommandObjectProcessAttach : public 
CommandObjectProcessLaunchOrAttach {
     ModuleSP old_exec_module_sp = target->GetExecutableModule();
     ArchSpec old_arch_spec = target->GetArchitecture();
 
-    if (command.GetArgumentCount()) {
-      result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
-                                   m_cmd_name.c_str(), m_cmd_syntax.c_str());
-      return false;
-    }
-
     StreamString stream;
     ProcessSP process_sp;
     const auto error = target->Attach(m_options.attach_info, &stream);
@@ -562,13 +556,6 @@ class CommandObjectProcessContinue : public 
CommandObjectParsed {
     bool synchronous_execution = m_interpreter.GetSynchronous();
     StateType state = process->GetState();
     if (state == eStateStopped) {
-      if (command.GetArgumentCount() != 0) {
-        result.AppendErrorWithFormat(
-            "The '%s' command does not take any arguments.\n",
-            m_cmd_name.c_str());
-        return false;
-      }
-
       if (m_options.m_ignore > 0) {
         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
         if (sel_thread_sp) {
@@ -943,7 +930,10 @@ class CommandObjectProcessConnect : public 
CommandObjectParsed {
   CommandObjectProcessConnect(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "process connect",
                             "Connect to a remote debug service.",
-                            "process connect <remote-url>", 0) {}
+                            "process connect <remote-url>", 0) {
+    CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain};
+    m_arguments.push_back({connect_arg});
+  }
 
   ~CommandObjectProcessConnect() override = default;
 
@@ -1068,7 +1058,10 @@ class CommandObjectProcessLoad : public 
CommandObjectParsed {
                             "process load <filename> [<filename> ...]",
                             eCommandRequiresProcess | eCommandTryTargetAPILock 
|
                                 eCommandProcessMustBeLaunched |
-                                eCommandProcessMustBePaused) {}
+                                eCommandProcessMustBePaused) {
+    CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus};
+    m_arguments.push_back({file_arg});
+  }
 
   ~CommandObjectProcessLoad() override = default;
 
@@ -1143,7 +1136,10 @@ class CommandObjectProcessUnload : public 
CommandObjectParsed {
             "returned by a previous call to \"process load\".",
             "process unload <index>",
             eCommandRequiresProcess | eCommandTryTargetAPILock |
-                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
+                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
+    CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    m_arguments.push_back({load_idx_arg});
+  }
 
   ~CommandObjectProcessUnload() override = default;
 
@@ -1291,18 +1287,13 @@ class CommandObjectProcessInterrupt : public 
CommandObjectParsed {
       return false;
     }
 
-    if (command.GetArgumentCount() == 0) {
-      bool clear_thread_plans = true;
-      Status error(process->Halt(clear_thread_plans));
-      if (error.Success()) {
-        result.SetStatus(eReturnStatusSuccessFinishResult);
-      } else {
-        result.AppendErrorWithFormat("Failed to halt process: %s\n",
-                                     error.AsCString());
-      }
+    bool clear_thread_plans = true;
+    Status error(process->Halt(clear_thread_plans));
+    if (error.Success()) {
+      result.SetStatus(eReturnStatusSuccessFinishResult);
     } else {
-      result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
-                                   m_cmd_name.c_str(), m_cmd_syntax.c_str());
+      result.AppendErrorWithFormat("Failed to halt process: %s\n",
+                                   error.AsCString());
     }
     return result.Succeeded();
   }
@@ -1330,17 +1321,12 @@ class CommandObjectProcessKill : public 
CommandObjectParsed {
       return false;
     }
 
-    if (command.GetArgumentCount() == 0) {
-      Status error(process->Destroy(true));
-      if (error.Success()) {
-        result.SetStatus(eReturnStatusSuccessFinishResult);
-      } else {
-        result.AppendErrorWithFormat("Failed to kill process: %s\n",
-                                     error.AsCString());
-      }
+    Status error(process->Destroy(true));
+    if (error.Success()) {
+      result.SetStatus(eReturnStatusSuccessFinishResult);
     } else {
-      result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
-                                   m_cmd_name.c_str(), m_cmd_syntax.c_str());
+      result.AppendErrorWithFormat("Failed to kill process: %s\n",
+                                   error.AsCString());
     }
     return result.Succeeded();
   }
@@ -1372,7 +1358,10 @@ class CommandObjectProcessSaveCore : public 
CommandObjectParsed {
             "appropriate file type.",
             "process save-core [-s corefile-style -p plugin-name] FILE",
             eCommandRequiresProcess | eCommandTryTargetAPILock |
-                eCommandProcessMustBeLaunched) {}
+                eCommandProcessMustBeLaunched) {
+    CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain};
+    m_arguments.push_back({file_arg});
+  }
 
   ~CommandObjectProcessSaveCore() override = default;
 
@@ -1519,11 +1508,6 @@ class CommandObjectProcessStatus : public 
CommandObjectParsed {
     Stream &strm = result.GetOutputStream();
     result.SetStatus(eReturnStatusSuccessFinishNoResult);
 
-    if (command.GetArgumentCount()) {
-      result.AppendError("'process status' takes no arguments");
-      return result.Succeeded();
-    }
-
     // No need to check "process" for validity as eCommandRequiresProcess
     // ensures it is valid
     Process *process = m_exe_ctx.GetProcessPtr();

diff  --git a/lldb/source/Commands/CommandObjectQuit.cpp 
b/lldb/source/Commands/CommandObjectQuit.cpp
index c6e2e21de6b61..650cfca2c050a 100644
--- a/lldb/source/Commands/CommandObjectQuit.cpp
+++ b/lldb/source/Commands/CommandObjectQuit.cpp
@@ -20,7 +20,10 @@ using namespace lldb_private;
 
 CommandObjectQuit::CommandObjectQuit(CommandInterpreter &interpreter)
     : CommandObjectParsed(interpreter, "quit", "Quit the LLDB debugger.",
-                          "quit [exit-code]") {}
+                          "quit [exit-code]") {
+  CommandArgumentData exit_code_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+  m_arguments.push_back({exit_code_arg});
+}
 
 CommandObjectQuit::~CommandObjectQuit() = default;
 

diff  --git a/lldb/source/Commands/CommandObjectReproducer.cpp 
b/lldb/source/Commands/CommandObjectReproducer.cpp
index 31ed02f9259f1..8d12decba9743 100644
--- a/lldb/source/Commands/CommandObjectReproducer.cpp
+++ b/lldb/source/Commands/CommandObjectReproducer.cpp
@@ -182,12 +182,6 @@ class CommandObjectReproducerGenerate : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
-      return false;
-    }
-
     auto &r = Reproducer::Instance();
     if (auto generator = r.GetGenerator()) {
       generator->Keep();
@@ -260,12 +254,6 @@ class CommandObjectReproducerXCrash : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
-      return false;
-    }
-
     auto &r = Reproducer::Instance();
 
     if (!r.IsCapturing()) {
@@ -309,12 +297,6 @@ class CommandObjectReproducerStatus : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
-      return false;
-    }
-
     auto &r = Reproducer::Instance();
     if (r.IsCapturing()) {
       result.GetOutputStream() << "Reproducer is in capture mode.\n";
@@ -394,12 +376,6 @@ class CommandObjectReproducerDump : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
-      return false;
-    }
-
     llvm::Optional<Loader> loader_storage;
     Loader *loader =
         GetLoaderFromPathOrCurrent(loader_storage, result, m_options.file);

diff  --git a/lldb/source/Commands/CommandObjectSource.cpp 
b/lldb/source/Commands/CommandObjectSource.cpp
index 67286c20cc8ad..f87981859844c 100644
--- a/lldb/source/Commands/CommandObjectSource.cpp
+++ b/lldb/source/Commands/CommandObjectSource.cpp
@@ -538,14 +538,6 @@ class CommandObjectSourceInfo : public CommandObjectParsed 
{
   }
 
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    const size_t argc = command.GetArgumentCount();
-
-    if (argc != 0) {
-      result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n",
-                                   GetCommandName().str().c_str());
-      return false;
-    }
-
     Target *target = m_exe_ctx.GetTargetPtr();
     if (target == nullptr) {
       target = GetDebugger().GetSelectedTarget().get();
@@ -924,14 +916,6 @@ class CommandObjectSourceList : public CommandObjectParsed 
{
   }
 
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    const size_t argc = command.GetArgumentCount();
-
-    if (argc != 0) {
-      result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n",
-                                   GetCommandName().str().c_str());
-      return false;
-    }
-
     Target *target = m_exe_ctx.GetTargetPtr();
 
     if (!m_options.symbol_name.empty()) {

diff  --git a/lldb/source/Commands/CommandObjectTarget.cpp 
b/lldb/source/Commands/CommandObjectTarget.cpp
index 23ebbdb64d028..2b71f1bc7bc86 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -487,18 +487,14 @@ class CommandObjectTargetList : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &args, CommandReturnObject &result) override {
-    if (args.GetArgumentCount() == 0) {
-      Stream &strm = result.GetOutputStream();
+    Stream &strm = result.GetOutputStream();
 
-      bool show_stopped_process_status = false;
-      if (DumpTargetList(GetDebugger().GetTargetList(),
-                         show_stopped_process_status, strm) == 0) {
-        strm.PutCString("No targets.\n");
-      }
-      result.SetStatus(eReturnStatusSuccessFinishResult);
-    } else {
-      result.AppendError("the 'target list' command takes no arguments\n");
+    bool show_stopped_process_status = false;
+    if (DumpTargetList(GetDebugger().GetTargetList(),
+                       show_stopped_process_status, strm) == 0) {
+      strm.PutCString("No targets.\n");
     }
+    result.SetStatus(eReturnStatusSuccessFinishResult);
     return result.Succeeded();
   }
 };
@@ -511,6 +507,8 @@ class CommandObjectTargetSelect : public 
CommandObjectParsed {
       : CommandObjectParsed(
             interpreter, "target select",
             "Select a target as the current target by target index.", nullptr) 
{
+    CommandArgumentData target_arg{eArgTypeTargetID, eArgRepeatPlain};
+    m_arguments.push_back({target_arg});
   }
 
   ~CommandObjectTargetSelect() override = default;
@@ -575,6 +573,8 @@ class CommandObjectTargetDelete : public 
CommandObjectParsed {
     m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Finalize();
+    CommandArgumentData target_arg{eArgTypeTargetID, eArgRepeatStar};
+    m_arguments.push_back({target_arg});
   }
 
   ~CommandObjectTargetDelete() override = default;
@@ -1230,10 +1230,6 @@ class CommandObjectTargetModulesSearchPathsList : public 
CommandObjectParsed {
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
     Target *target = &GetSelectedTarget();
-    if (command.GetArgumentCount() != 0) {
-      result.AppendError("list takes no arguments\n");
-      return result.Succeeded();
-    }
 
     target->GetImageSearchPathList().Dump(&result.GetOutputStream());
     result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -2454,6 +2450,8 @@ class CommandObjectTargetModulesAdd : public 
CommandObjectParsed {
                           LLDB_OPT_SET_1);
     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
     m_option_group.Finalize();
+    CommandArgumentData module_arg{eArgTypePath, eArgRepeatStar};
+    m_arguments.push_back({module_arg});
   }
 
   ~CommandObjectTargetModulesAdd() override = default;
@@ -4019,6 +4017,8 @@ class CommandObjectTargetSymbolsAdd : public 
CommandObjectParsed {
     m_option_group.Append(&m_current_stack_option, LLDB_OPT_SET_2,
                           LLDB_OPT_SET_2);
     m_option_group.Finalize();
+    CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatPlain};
+    m_arguments.push_back({module_arg});
   }
 
   ~CommandObjectTargetSymbolsAdd() override = default;
@@ -4867,7 +4867,10 @@ class CommandObjectTargetStopHookDelete : public 
CommandObjectParsed {
   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "target stop-hook delete",
                             "Delete a stop-hook.",
-                            "target stop-hook delete [<idx>]") {}
+                            "target stop-hook delete [<idx>]") {
+    CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
+    m_arguments.push_back({hook_arg});
+  }
 
   ~CommandObjectTargetStopHookDelete() override = default;
 
@@ -4921,6 +4924,8 @@ class CommandObjectTargetStopHookEnableDisable : public 
CommandObjectParsed {
                                            bool enable, const char *name,
                                            const char *help, const char 
*syntax)
       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) 
{
+    CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
+    m_arguments.push_back({hook_arg});
   }
 
   ~CommandObjectTargetStopHookEnableDisable() override = default;
@@ -4976,8 +4981,7 @@ class CommandObjectTargetStopHookList : public 
CommandObjectParsed {
 public:
   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "target stop-hook list",
-                            "List all stop-hooks.",
-                            "target stop-hook list [<type>]") {}
+                            "List all stop-hooks.", "target stop-hook list") {}
 
   ~CommandObjectTargetStopHookList() override = default;
 
@@ -5049,11 +5053,6 @@ class CommandObjectTargetDumpTypesystem : public 
CommandObjectParsed {
 
 protected:
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    if (!command.empty()) {
-      result.AppendError("target dump typesystem doesn't take arguments.");
-      return result.Succeeded();
-    }
-
     // Go over every scratch TypeSystem and dump to the command output.
     for (TypeSystem *ts : GetSelectedTarget().GetScratchTypeSystems())
       ts->Dump(result.GetOutputStream().AsRawOstream());

diff  --git a/lldb/source/Commands/CommandObjectThreadUtil.cpp 
b/lldb/source/Commands/CommandObjectThreadUtil.cpp
index d330da7e684ea..cac1bef3e9dff 100644
--- a/lldb/source/Commands/CommandObjectThreadUtil.cpp
+++ b/lldb/source/Commands/CommandObjectThreadUtil.cpp
@@ -19,7 +19,11 @@ using namespace llvm;
 CommandObjectIterateOverThreads::CommandObjectIterateOverThreads(
     CommandInterpreter &interpreter, const char *name, const char *help,
     const char *syntax, uint32_t flags)
-    : CommandObjectParsed(interpreter, name, help, syntax, flags) {}
+    : CommandObjectParsed(interpreter, name, help, syntax, flags) {
+  // These commands all take thread ID's as arguments.
+  CommandArgumentData thread_arg{eArgTypeThreadIndex, eArgRepeatStar};
+  m_arguments.push_back({thread_arg});
+}
 
 bool CommandObjectIterateOverThreads::DoExecute(Args &command,
                                                 CommandReturnObject &result) {

diff  --git a/lldb/source/Commands/CommandObjectTrace.cpp 
b/lldb/source/Commands/CommandObjectTrace.cpp
index 2fa68f1a3dbd6..17aded9ed2a0c 100644
--- a/lldb/source/Commands/CommandObjectTrace.cpp
+++ b/lldb/source/Commands/CommandObjectTrace.cpp
@@ -75,7 +75,10 @@ class CommandObjectTraceLoad : public CommandObjectParsed {
       : CommandObjectParsed(
             interpreter, "trace load",
             "Load a post-mortem processor trace session from a trace bundle.",
-            "trace load") {}
+            "trace load") {
+    CommandArgumentData session_file_arg{eArgTypePath, eArgRepeatPlain};
+    m_arguments.push_back({session_file_arg});
+  }
 
   ~CommandObjectTraceLoad() override = default;
 
@@ -223,7 +226,10 @@ class CommandObjectTraceSchema : public 
CommandObjectParsed {
       : CommandObjectParsed(interpreter, "trace schema",
                             "Show the schema of the given trace plugin.",
                             "trace schema <plug-in>. Use the plug-in name "
-                            "\"all\" to see all schemas.\n") {}
+                            "\"all\" to see all schemas.\n") {
+    CommandArgumentData plugin_arg{eArgTypeNone, eArgRepeatPlain};
+    m_arguments.push_back({plugin_arg});
+  }
 
   ~CommandObjectTraceSchema() override = default;
 

diff  --git a/lldb/source/Commands/CommandObjectType.cpp 
b/lldb/source/Commands/CommandObjectType.cpp
index b79c19bcae850..3ad3571b390cc 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -914,7 +914,10 @@ class CommandObjectTypeFormatterClear : public 
CommandObjectParsed {
                                   uint32_t formatter_kind_mask,
                                   const char *name, const char *help)
       : CommandObjectParsed(interpreter, name, help, nullptr),
-        m_formatter_kind_mask(formatter_kind_mask) {}
+        m_formatter_kind_mask(formatter_kind_mask) {
+    CommandArgumentData category_arg{eArgTypeName, eArgRepeatOptional};
+    m_arguments.push_back({category_arg});
+  }
 
   ~CommandObjectTypeFormatterClear() override = default;
 

diff  --git a/lldb/source/Commands/CommandObjectVersion.cpp 
b/lldb/source/Commands/CommandObjectVersion.cpp
index e15faba5661e7..9b3c9e67a1a74 100644
--- a/lldb/source/Commands/CommandObjectVersion.cpp
+++ b/lldb/source/Commands/CommandObjectVersion.cpp
@@ -23,11 +23,7 @@ 
CommandObjectVersion::CommandObjectVersion(CommandInterpreter &interpreter)
 CommandObjectVersion::~CommandObjectVersion() = default;
 
 bool CommandObjectVersion::DoExecute(Args &args, CommandReturnObject &result) {
-  if (args.GetArgumentCount() == 0) {
-    result.AppendMessageWithFormat("%s\n", lldb_private::GetVersion());
-    result.SetStatus(eReturnStatusSuccessFinishResult);
-  } else {
-    result.AppendError("the version command takes no arguments.");
-  }
+  result.AppendMessageWithFormat("%s\n", lldb_private::GetVersion());
+  result.SetStatus(eReturnStatusSuccessFinishResult);
   return true;
 }

diff  --git a/lldb/source/Interpreter/CommandObject.cpp 
b/lldb/source/Interpreter/CommandObject.cpp
index 824c34c0e324d..c92fec53a55e9 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -995,6 +995,11 @@ bool CommandObjectParsed::Execute(const char *args_string,
       if (ParseOptions(cmd_args, result)) {
         // Call the command-specific version of 'Execute', passing it the
         // already processed arguments.
+        if (cmd_args.GetArgumentCount() != 0 && m_arguments.empty()) {
+          result.AppendErrorWithFormatv("'{0}' doesn't take any arguments.",
+                                        GetCommandName());
+          return false;
+        }
         handled = DoExecute(cmd_args, result);
       }
     }
@@ -1128,6 +1133,10 @@ CommandObject::ArgumentTableEntry 
CommandObject::g_arguments_data[] = {
     { eArgTypeModuleUUID, "module-uuid", 
CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID 
value." },
     { eArgTypeSaveCoreStyle, "corefile-style", 
CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile 
that lldb will try to create, dependant on this target's capabilities." },
     { eArgTypeLogHandler, "log-handler", CommandCompletions::eNoCompletion, { 
nullptr, false }, "The log handle that will be used to write out log messages." 
},
+    { eArgTypeSEDStylePair, "substitution-pair", 
CommandCompletions::eNoCompletion, { nullptr, false }, "A sed-style pattern and 
target pair." },
+    { eArgTypeConnectURL, "process-connect-url", 
CommandCompletions::eNoCompletion, { nullptr, false }, "A URL-style 
specification for a remote connection." },
+    { eArgTypeTargetID, "target-id", CommandCompletions::eNoCompletion, { 
nullptr, false }, "The index ID for an lldb Target." },
+    { eArgTypeStopHookID, "stop-hook-id", CommandCompletions::eNoCompletion, { 
nullptr, false }, "The ID you receive when you create a stop-hook." }
     // clang-format on
 };
 

diff  --git 
a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
 
b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 2cf166bc8a1d5..bc8e43764af69 100644
--- 
a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ 
b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -4067,7 +4067,10 @@ class 
CommandObjectRenderScriptRuntimeReductionBreakpointSet
             "<reduction_kernel_type,...>]",
             eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                 eCommandProcessMustBePaused),
-        m_options(){};
+        m_options() {
+    CommandArgumentData name_arg{eArgTypeName, eArgRepeatPlain};
+    m_arguments.push_back({name_arg});
+  };
 
   class CommandOptions : public Options {
   public:
@@ -4216,7 +4219,10 @@ class CommandObjectRenderScriptRuntimeKernelBreakpointSet
             "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
             eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                 eCommandProcessMustBePaused),
-        m_options() {}
+        m_options() {
+    CommandArgumentData name_arg{eArgTypeName, eArgRepeatPlain};
+    m_arguments.push_back({name_arg});
+  }
 
   ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
 
@@ -4311,7 +4317,10 @@ class CommandObjectRenderScriptRuntimeKernelBreakpointAll
             "but does not remove currently set breakpoints.",
             "renderscript kernel breakpoint all <enable/disable>",
             eCommandRequiresProcess | eCommandProcessMustBeLaunched |
-                eCommandProcessMustBePaused) {}
+                eCommandProcessMustBePaused) {
+    CommandArgumentData enable_arg{eArgTypeNone, eArgRepeatPlain};
+    m_arguments.push_back({enable_arg});
+  }
 
   ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
 
@@ -4493,7 +4502,10 @@ class CommandObjectRenderScriptRuntimeAllocationDump
                             "renderscript allocation dump <ID>",
                             eCommandRequiresProcess |
                                 eCommandProcessMustBeLaunched),
-        m_options() {}
+        m_options() {
+    CommandArgumentData id_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    m_arguments.push_back({id_arg});
+  }
 
   ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
 
@@ -4679,7 +4691,12 @@ class CommandObjectRenderScriptRuntimeAllocationLoad
             interpreter, "renderscript allocation load",
             "Loads renderscript allocation contents from a file.",
             "renderscript allocation load <ID> <filename>",
-            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {
+    CommandArgumentData id_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    CommandArgumentData name_arg{eArgTypeFilename, eArgRepeatPlain};
+    m_arguments.push_back({id_arg});
+    m_arguments.push_back({name_arg});
+  }
 
   ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
 
@@ -4726,7 +4743,12 @@ class CommandObjectRenderScriptRuntimeAllocationSave
                             "Write renderscript allocation contents to a 
file.",
                             "renderscript allocation save <ID> <filename>",
                             eCommandRequiresProcess |
-                                eCommandProcessMustBeLaunched) {}
+                                eCommandProcessMustBeLaunched) {
+    CommandArgumentData id_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    CommandArgumentData name_arg{eArgTypeFilename, eArgRepeatPlain};
+    m_arguments.push_back({id_arg});
+    m_arguments.push_back({name_arg});
+  }
 
   ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
 

diff  --git 
a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
 
b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
index b6f8b20c90c33..3eb2519dda9e6 100644
--- 
a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
+++ 
b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
@@ -39,7 +39,10 @@ class CommandObjectRenderScriptScriptGroupBreakpointSet
             interpreter, "renderscript scriptgroup breakpoint set",
             "Place a breakpoint on all kernels forming a script group.",
             "renderscript scriptgroup breakpoint set <group_name>",
-            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {
+    CommandArgumentData name_arg{eArgTypeName, eArgRepeatPlus};
+    m_arguments.push_back({name_arg});
+  }
 
   ~CommandObjectRenderScriptScriptGroupBreakpointSet() override = default;
 

diff  --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp 
b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index b77cf8012b5ea..feb878f039ab6 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -883,87 +883,81 @@ class CommandObjectProcessKDPPacketSend : public 
CommandObjectParsed {
   ~CommandObjectProcessKDPPacketSend() override = default;
 
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    const size_t argc = command.GetArgumentCount();
-    if (argc == 0) {
-      if (!m_command_byte.GetOptionValue().OptionWasSet()) {
-        result.AppendError(
-            "the --command option must be set to a valid command byte");
-      } else {
-        const uint64_t command_byte =
-            m_command_byte.GetOptionValue().GetUInt64Value(0);
-        if (command_byte > 0 && command_byte <= UINT8_MAX) {
-          ProcessKDP *process =
-              (ProcessKDP 
*)m_interpreter.GetExecutionContext().GetProcessPtr();
-          if (process) {
-            const StateType state = process->GetState();
-
-            if (StateIsStoppedState(state, true)) {
-              std::vector<uint8_t> payload_bytes;
-              const char *ascii_hex_bytes_cstr =
-                  m_packet_data.GetOptionValue().GetCurrentValue();
-              if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) {
-                StringExtractor extractor(ascii_hex_bytes_cstr);
-                const size_t ascii_hex_bytes_cstr_len =
-                    extractor.GetStringRef().size();
-                if (ascii_hex_bytes_cstr_len & 1) {
-                  result.AppendErrorWithFormat("payload data must contain an "
-                                               "even number of ASCII hex "
-                                               "characters: '%s'",
-                                               ascii_hex_bytes_cstr);
-                  return false;
-                }
-                payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);
-                if (extractor.GetHexBytes(payload_bytes, '\xdd') !=
-                    payload_bytes.size()) {
-                  result.AppendErrorWithFormat("payload data must only contain 
"
-                                               "ASCII hex characters (no "
-                                               "spaces or hex prefixes): '%s'",
-                                               ascii_hex_bytes_cstr);
-                  return false;
-                }
+    if (!m_command_byte.GetOptionValue().OptionWasSet()) {
+      result.AppendError(
+          "the --command option must be set to a valid command byte");
+    } else {
+      const uint64_t command_byte =
+          m_command_byte.GetOptionValue().GetUInt64Value(0);
+      if (command_byte > 0 && command_byte <= UINT8_MAX) {
+        ProcessKDP *process =
+            (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr();
+        if (process) {
+          const StateType state = process->GetState();
+
+          if (StateIsStoppedState(state, true)) {
+            std::vector<uint8_t> payload_bytes;
+            const char *ascii_hex_bytes_cstr =
+                m_packet_data.GetOptionValue().GetCurrentValue();
+            if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) {
+              StringExtractor extractor(ascii_hex_bytes_cstr);
+              const size_t ascii_hex_bytes_cstr_len =
+                  extractor.GetStringRef().size();
+              if (ascii_hex_bytes_cstr_len & 1) {
+                result.AppendErrorWithFormat("payload data must contain an "
+                                             "even number of ASCII hex "
+                                             "characters: '%s'",
+                                             ascii_hex_bytes_cstr);
+                return false;
               }
-              Status error;
-              DataExtractor reply;
-              process->GetCommunication().SendRawRequest(
-                  command_byte,
-                  payload_bytes.empty() ? NULL : payload_bytes.data(),
-                  payload_bytes.size(), reply, error);
-
-              if (error.Success()) {
-                // Copy the binary bytes into a hex ASCII string for the result
-                StreamString packet;
-                packet.PutBytesAsRawHex8(
-                    reply.GetDataStart(), reply.GetByteSize(),
-                    endian::InlHostByteOrder(), endian::InlHostByteOrder());
-                result.AppendMessage(packet.GetString());
-                result.SetStatus(eReturnStatusSuccessFinishResult);
-                return true;
-              } else {
-                const char *error_cstr = error.AsCString();
-                if (error_cstr && error_cstr[0])
-                  result.AppendError(error_cstr);
-                else
-                  result.AppendErrorWithFormat("unknown error 0x%8.8x",
-                                               error.GetError());
+              payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);
+              if (extractor.GetHexBytes(payload_bytes, '\xdd') !=
+                  payload_bytes.size()) {
+                result.AppendErrorWithFormat("payload data must only contain "
+                                             "ASCII hex characters (no "
+                                             "spaces or hex prefixes): '%s'",
+                                             ascii_hex_bytes_cstr);
                 return false;
               }
+            }
+            Status error;
+            DataExtractor reply;
+            process->GetCommunication().SendRawRequest(
+                command_byte,
+                payload_bytes.empty() ? NULL : payload_bytes.data(),
+                payload_bytes.size(), reply, error);
+
+            if (error.Success()) {
+              // Copy the binary bytes into a hex ASCII string for the result
+              StreamString packet;
+              packet.PutBytesAsRawHex8(
+                  reply.GetDataStart(), reply.GetByteSize(),
+                  endian::InlHostByteOrder(), endian::InlHostByteOrder());
+              result.AppendMessage(packet.GetString());
+              result.SetStatus(eReturnStatusSuccessFinishResult);
+              return true;
             } else {
-              result.AppendErrorWithFormat("process must be stopped in order "
-                                           "to send KDP packets, state is %s",
-                                           StateAsCString(state));
+              const char *error_cstr = error.AsCString();
+              if (error_cstr && error_cstr[0])
+                result.AppendError(error_cstr);
+              else
+                result.AppendErrorWithFormat("unknown error 0x%8.8x",
+                                             error.GetError());
+              return false;
             }
           } else {
-            result.AppendError("invalid process");
+            result.AppendErrorWithFormat("process must be stopped in order "
+                                         "to send KDP packets, state is %s",
+                                         StateAsCString(state));
           }
         } else {
-          result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64
-                                       ", valid values are 1 - 255",
-                                       command_byte);
+          result.AppendError("invalid process");
         }
+      } else {
+        result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64
+                                     ", valid values are 1 - 255",
+                                     command_byte);
       }
-    } else {
-      result.AppendErrorWithFormat("'%s' takes no arguments, only options.",
-                                   m_cmd_name.c_str());
     }
     return false;
   }

diff  --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp 
b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index a00961daf2755..fe6a3f9ed6c19 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -5008,19 +5008,12 @@ class CommandObjectProcessGDBRemotePacketHistory : 
public CommandObjectParsed {
   ~CommandObjectProcessGDBRemotePacketHistory() override = default;
 
   bool DoExecute(Args &command, CommandReturnObject &result) override {
-    const size_t argc = command.GetArgumentCount();
-    if (argc == 0) {
-      ProcessGDBRemote *process =
-          (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
-              .GetProcessPtr();
-      if (process) {
-        process->GetGDBRemote().DumpHistory(result.GetOutputStream());
-        result.SetStatus(eReturnStatusSuccessFinishResult);
-        return true;
-      }
-    } else {
-      result.AppendErrorWithFormat("'%s' takes no arguments",
-                                   m_cmd_name.c_str());
+    ProcessGDBRemote *process =
+        (ProcessGDBRemote 
*)m_interpreter.GetExecutionContext().GetProcessPtr();
+    if (process) {
+      process->GetGDBRemote().DumpHistory(result.GetOutputStream());
+      result.SetStatus(eReturnStatusSuccessFinishResult);
+      return true;
     }
     result.SetStatus(eReturnStatusFailed);
     return false;
@@ -5034,7 +5027,10 @@ class CommandObjectProcessGDBRemotePacketXferSize : 
public CommandObjectParsed {
       : CommandObjectParsed(
             interpreter, "process plugin packet xfer-size",
             "Maximum size that lldb will try to read/write one one chunk.",
-            nullptr) {}
+            nullptr) {
+    CommandArgumentData max_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
+    m_arguments.push_back({max_arg});
+  }
 
   ~CommandObjectProcessGDBRemotePacketXferSize() override = default;
 
@@ -5075,7 +5071,10 @@ class CommandObjectProcessGDBRemotePacketSend : public 
CommandObjectParsed {
                             "The packet header and footer will automatically "
                             "be added to the packet prior to sending and "
                             "stripped from the result.",
-                            nullptr) {}
+                            nullptr) {
+    CommandArgumentData packet_arg{eArgTypeNone, eArgRepeatStar};
+    m_arguments.push_back({packet_arg});
+  }
 
   ~CommandObjectProcessGDBRemotePacketSend() override = default;
 

diff  --git a/lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py 
b/lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
index 587a0021eca6c..c423405c2be15 100644
--- a/lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
+++ b/lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
@@ -8,4 +8,4 @@ class GuiTestCase(TestBase):
     @skipIfCursesSupportMissing
     def test_reproducer_generate_invalid_invocation(self):
         self.expect("gui blub", error=True,
-                    substrs=["the gui command takes no arguments."])
+                    substrs=["'gui' doesn't take any arguments."])

diff  --git 
a/lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py 
b/lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
index 03626c54a2c60..0c038ac94c65c 100644
--- 
a/lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
+++ 
b/lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
@@ -7,9 +7,9 @@ class ReproducerTestCase(TestBase):
     @no_debug_info_test
     def test_reproducer_generate_invalid_invocation(self):
         self.expect("reproducer generate f", error=True,
-                    substrs=["'reproducer generate' takes no arguments"])
+                    substrs=["'reproducer generate' doesn't take any 
arguments"])
 
     @no_debug_info_test
     def test_reproducer_status_invalid_invocation(self):
         self.expect("reproducer status f", error=True,
-                    substrs=["'reproducer status' takes no arguments"])
+                    substrs=["'reproducer status' doesn't take any arguments"])

diff  --git a/lldb/test/API/commands/target/basic/TestTargetCommand.py 
b/lldb/test/API/commands/target/basic/TestTargetCommand.py
index 91adc98d3c39b..efbde6acd9573 100644
--- a/lldb/test/API/commands/target/basic/TestTargetCommand.py
+++ b/lldb/test/API/commands/target/basic/TestTargetCommand.py
@@ -325,7 +325,7 @@ def test_target_stop_hook_delete(self):
     @no_debug_info_test
     def test_target_list_args(self):
         self.expect("target list blub", error=True,
-                    substrs=["the 'target list' command takes no arguments"])
+                    substrs=["'target list' doesn't take any arguments"])
 
     @no_debug_info_test
     def test_target_select_no_index(self):

diff  --git a/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py 
b/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
index e1a7caf0249ed..9bfa689527bf6 100644
--- a/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
+++ b/lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
@@ -28,4 +28,4 @@ def test_invalid_arg(self):
         self.build()
         self.createTestTarget()
         self.expect("target dump typesystem arg", error=True,
-                    substrs=["error: target dump typesystem doesn't take 
arguments."])
+                    substrs=["'target dump typesystem' doesn't take any 
arguments."])

diff  --git a/lldb/test/API/commands/version/TestVersion.py 
b/lldb/test/API/commands/version/TestVersion.py
index c6e91e38c68ea..138a91cb9ff2c 100644
--- a/lldb/test/API/commands/version/TestVersion.py
+++ b/lldb/test/API/commands/version/TestVersion.py
@@ -14,4 +14,4 @@ def test_version(self):
     @no_debug_info_test
     def test_version_invalid_invocation(self):
         self.expect("version a", error=True,
-                    substrs=['the version command takes no arguments.'])
+                    substrs=["'version' doesn't take any arguments."])

diff  --git 
a/lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
 
b/lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
index edb7a6b38c414..fe5f979a31b7e 100644
--- 
a/lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
+++ 
b/lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
@@ -88,10 +88,10 @@ def test_multiple_watchpoints_on_same_word(self):
         # The stop reason of the thread should be watchpoint.
         if self.platformIsDarwin():
             # On darwin we'll hit byteArray[3] which is watchpoint 2
-            self.expect("thread list -v", STOPPED_DUE_TO_WATCHPOINT,
+            self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
                         substrs=['stopped', 'stop reason = watchpoint 2'])
         else:
-            self.expect("thread list -v", STOPPED_DUE_TO_WATCHPOINT,
+            self.expect("thread list", STOPPED_DUE_TO_WATCHPOINT,
                         substrs=['stopped', 'stop reason = watchpoint 3'])
 
         # Resume inferior.

diff  --git a/lldb/test/API/functionalities/completion/TestCompletion.py 
b/lldb/test/API/functionalities/completion/TestCompletion.py
index f91049e6d5802..17c1b29362ae9 100644
--- a/lldb/test/API/functionalities/completion/TestCompletion.py
+++ b/lldb/test/API/functionalities/completion/TestCompletion.py
@@ -675,7 +675,7 @@ def test_common_completion_target_stophook_ids(self):
 
         self.build()
         self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
-        self.runCmd('target stop-hook add test DONE')
+        self.runCmd('target stop-hook add -o test')
 
         for subcommand in subcommands:
             self.complete_from_to('target stop-hook ' + subcommand + ' ',


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to