This revision was automatically updated to reflect the committed changes.
Closed by commit rGc1b07d617705: Have CommandObjectParsed check for 
"commands that take no arguments". (authored by jingham).

Changed prior to commit:
  https://reviews.llvm.org/D128453?vs=439443&id=440411#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128453/new/

https://reviews.llvm.org/D128453

Files:
  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

Index: lldb/test/API/functionalities/completion/TestCompletion.py
===================================================================
--- lldb/test/API/functionalities/completion/TestCompletion.py
+++ lldb/test/API/functionalities/completion/TestCompletion.py
@@ -675,7 +675,7 @@
 
         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 + ' ',
Index: lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
===================================================================
--- lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
+++ lldb/test/API/commands/watchpoints/multi_watchpoint_slots/TestWatchpointMultipleSlots.py
@@ -88,10 +88,10 @@
         # 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.
Index: lldb/test/API/commands/version/TestVersion.py
===================================================================
--- lldb/test/API/commands/version/TestVersion.py
+++ lldb/test/API/commands/version/TestVersion.py
@@ -14,4 +14,4 @@
     @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."])
Index: lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
===================================================================
--- lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
+++ lldb/test/API/commands/target/dump/TestTargetDumpTypeSystem.py
@@ -28,4 +28,4 @@
         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."])
Index: lldb/test/API/commands/target/basic/TestTargetCommand.py
===================================================================
--- lldb/test/API/commands/target/basic/TestTargetCommand.py
+++ lldb/test/API/commands/target/basic/TestTargetCommand.py
@@ -325,7 +325,7 @@
     @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):
Index: lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
===================================================================
--- lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
+++ lldb/test/API/commands/reproducer/invalid-args/TestInvalidArgsReproducer.py
@@ -7,9 +7,9 @@
     @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"])
Index: lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
===================================================================
--- lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
+++ lldb/test/API/commands/gui/invalid-args/TestInvalidArgsGui.py
@@ -8,4 +8,4 @@
     @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."])
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -5008,19 +5008,12 @@
   ~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 @@
       : 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 @@
                             "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;
 
Index: lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
===================================================================
--- lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -883,87 +883,81 @@
   ~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;
   }
Index: lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
===================================================================
--- lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
+++ lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
@@ -39,7 +39,10 @@
             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;
 
Index: lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
===================================================================
--- lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -4067,7 +4067,10 @@
             "<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 @@
             "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 @@
             "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 @@
                             "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 @@
             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 @@
                             "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;
 
Index: lldb/source/Interpreter/CommandObject.cpp
===================================================================
--- lldb/source/Interpreter/CommandObject.cpp
+++ lldb/source/Interpreter/CommandObject.cpp
@@ -995,6 +995,11 @@
       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 @@
     { 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
 };
 
Index: lldb/source/Commands/CommandObjectVersion.cpp
===================================================================
--- lldb/source/Commands/CommandObjectVersion.cpp
+++ lldb/source/Commands/CommandObjectVersion.cpp
@@ -23,11 +23,7 @@
 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;
 }
Index: lldb/source/Commands/CommandObjectType.cpp
===================================================================
--- lldb/source/Commands/CommandObjectType.cpp
+++ lldb/source/Commands/CommandObjectType.cpp
@@ -914,7 +914,10 @@
                                   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;
 
Index: lldb/source/Commands/CommandObjectTrace.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTrace.cpp
+++ lldb/source/Commands/CommandObjectTrace.cpp
@@ -75,7 +75,10 @@
       : 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 @@
       : 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;
 
Index: lldb/source/Commands/CommandObjectThreadUtil.cpp
===================================================================
--- lldb/source/Commands/CommandObjectThreadUtil.cpp
+++ lldb/source/Commands/CommandObjectThreadUtil.cpp
@@ -19,7 +19,11 @@
 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) {
Index: lldb/source/Commands/CommandObjectTarget.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTarget.cpp
+++ lldb/source/Commands/CommandObjectTarget.cpp
@@ -487,18 +487,14 @@
 
 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 @@
       : 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 @@
     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 @@
 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 @@
                           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 @@
     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 @@
   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 @@
                                            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 @@
 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 @@
 
 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());
Index: lldb/source/Commands/CommandObjectSource.cpp
===================================================================
--- lldb/source/Commands/CommandObjectSource.cpp
+++ lldb/source/Commands/CommandObjectSource.cpp
@@ -538,14 +538,6 @@
   }
 
   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 @@
   }
 
   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()) {
Index: lldb/source/Commands/CommandObjectReproducer.cpp
===================================================================
--- lldb/source/Commands/CommandObjectReproducer.cpp
+++ lldb/source/Commands/CommandObjectReproducer.cpp
@@ -182,12 +182,6 @@
 
 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 @@
 
 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 @@
 
 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 @@
 
 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);
Index: lldb/source/Commands/CommandObjectQuit.cpp
===================================================================
--- lldb/source/Commands/CommandObjectQuit.cpp
+++ lldb/source/Commands/CommandObjectQuit.cpp
@@ -20,7 +20,10 @@
 
 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;
 
Index: lldb/source/Commands/CommandObjectProcess.cpp
===================================================================
--- lldb/source/Commands/CommandObjectProcess.cpp
+++ lldb/source/Commands/CommandObjectProcess.cpp
@@ -414,12 +414,6 @@
     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 @@
     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 @@
   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 @@
                             "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 @@
             "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 @@
       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 @@
       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 @@
             "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 @@
     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();
Index: lldb/source/Commands/CommandObjectPlatform.cpp
===================================================================
--- lldb/source/Commands/CommandObjectPlatform.cpp
+++ lldb/source/Commands/CommandObjectPlatform.cpp
@@ -150,6 +150,8 @@
   {
     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 @@
       : 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 @@
   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 @@
 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 @@
 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 @@
   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 @@
   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 @@
     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 @@
                             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 @@
 
     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 @@
   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 @@
       : 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;
 
Index: lldb/source/Commands/CommandObjectGUI.cpp
===================================================================
--- lldb/source/Commands/CommandObjectGUI.cpp
+++ lldb/source/Commands/CommandObjectGUI.cpp
@@ -26,22 +26,18 @@
 
 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
Index: lldb/source/Commands/CommandObjectFrame.cpp
===================================================================
--- lldb/source/Commands/CommandObjectFrame.cpp
+++ lldb/source/Commands/CommandObjectFrame.cpp
@@ -924,7 +924,11 @@
 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;
 
Index: lldb/source/Commands/CommandObjectCommands.cpp
===================================================================
--- lldb/source/Commands/CommandObjectCommands.cpp
+++ lldb/source/Commands/CommandObjectCommands.cpp
@@ -824,6 +824,8 @@
         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 @@
   ~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 @@
 
 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);
Index: lldb/source/API/SBCommandInterpreter.cpp
===================================================================
--- lldb/source/API/SBCommandInterpreter.cpp
+++ lldb/source/API/SBCommandInterpreter.cpp
@@ -47,6 +47,10 @@
         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; }
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -603,6 +603,11 @@
   eArgTypeModuleUUID,
   eArgTypeSaveCoreStyle,
   eArgTypeLogHandler,
+  eArgTypeSEDStylePair,
+  eArgTypeRecognizerID,
+  eArgTypeConnectURL,
+  eArgTypeTargetID,
+  eArgTypeStopHookID,
   eArgTypeLastArg // Always keep this entry as the last entry in this
                   // enumeration!!
 };
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to