Skip to content

Commit c1b07d6

Browse files
committed
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
1 parent 6824eee commit c1b07d6

27 files changed

+335
-323
lines changed

lldb/include/lldb/lldb-enumerations.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,11 @@ enum CommandArgumentType {
603603
eArgTypeModuleUUID,
604604
eArgTypeSaveCoreStyle,
605605
eArgTypeLogHandler,
606+
eArgTypeSEDStylePair,
607+
eArgTypeRecognizerID,
608+
eArgTypeConnectURL,
609+
eArgTypeTargetID,
610+
eArgTypeStopHookID,
606611
eArgTypeLastArg // Always keep this entry as the last entry in this
607612
// enumeration!!
608613
};

lldb/source/API/SBCommandInterpreter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ class CommandPluginInterfaceImplementation : public CommandObjectParsed {
4747
auto_repeat_command == nullptr
4848
? llvm::None
4949
: llvm::Optional<std::string>(auto_repeat_command);
50+
// We don't know whether any given command coming from this interface takes
51+
// arguments or not so here we're just disabling the basic args check.
52+
CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar};
53+
m_arguments.push_back({none_arg});
5054
}
5155

5256
bool IsRemovable() const override { return true; }

lldb/source/Commands/CommandObjectCommands.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,8 @@ a number follows 'f':"
824824
R"(
825825
826826
(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
827+
CommandArgumentData thread_arg{eArgTypeSEDStylePair, eArgRepeatOptional};
828+
m_arguments.push_back({thread_arg});
827829
}
828830

829831
~CommandObjectCommandsAddRegex() override = default;
@@ -1664,11 +1666,6 @@ class CommandObjectCommandsScriptList : public CommandObjectParsed {
16641666
~CommandObjectCommandsScriptList() override = default;
16651667

16661668
bool DoExecute(Args &command, CommandReturnObject &result) override {
1667-
if (command.GetArgumentCount() != 0) {
1668-
result.AppendError("'command script list' doesn't take any arguments");
1669-
return false;
1670-
}
1671-
16721669
m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
16731670

16741671
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -1689,11 +1686,6 @@ class CommandObjectCommandsScriptClear : public CommandObjectParsed {
16891686

16901687
protected:
16911688
bool DoExecute(Args &command, CommandReturnObject &result) override {
1692-
if (command.GetArgumentCount() != 0) {
1693-
result.AppendError("'command script clear' doesn't take any arguments");
1694-
return false;
1695-
}
1696-
16971689
m_interpreter.RemoveAllUser();
16981690

16991691
result.SetStatus(eReturnStatusSuccessFinishResult);

lldb/source/Commands/CommandObjectFrame.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,11 @@ class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
924924
public:
925925
CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
926926
: CommandObjectParsed(interpreter, "frame recognizer delete",
927-
"Delete an existing frame recognizer.", nullptr) {}
927+
"Delete an existing frame recognizer by id.",
928+
nullptr) {
929+
CommandArgumentData thread_arg{eArgTypeRecognizerID, eArgRepeatPlain};
930+
m_arguments.push_back({thread_arg});
931+
}
928932

929933
~CommandObjectFrameRecognizerDelete() override = default;
930934

lldb/source/Commands/CommandObjectGUI.cpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,18 @@ CommandObjectGUI::~CommandObjectGUI() = default;
2626

2727
bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) {
2828
#if LLDB_ENABLE_CURSES
29-
if (args.GetArgumentCount() == 0) {
30-
Debugger &debugger = GetDebugger();
31-
32-
File &input = debugger.GetInputFile();
33-
File &output = debugger.GetOutputFile();
34-
if (input.GetStream() && output.GetStream() && input.GetIsRealTerminal() &&
35-
input.GetIsInteractive()) {
36-
IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger));
37-
if (io_handler_sp)
38-
debugger.RunIOHandlerAsync(io_handler_sp);
39-
result.SetStatus(eReturnStatusSuccessFinishResult);
40-
} else {
41-
result.AppendError("the gui command requires an interactive terminal.");
42-
}
29+
Debugger &debugger = GetDebugger();
30+
31+
File &input = debugger.GetInputFile();
32+
File &output = debugger.GetOutputFile();
33+
if (input.GetStream() && output.GetStream() && input.GetIsRealTerminal() &&
34+
input.GetIsInteractive()) {
35+
IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger));
36+
if (io_handler_sp)
37+
debugger.RunIOHandlerAsync(io_handler_sp);
38+
result.SetStatus(eReturnStatusSuccessFinishResult);
4339
} else {
44-
result.AppendError("the gui command takes no arguments.");
40+
result.AppendError("the gui command requires an interactive terminal.");
4541
}
4642
return true;
4743
#else

lldb/source/Commands/CommandObjectPlatform.cpp

Lines changed: 108 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ class CommandObjectPlatformSelect : public CommandObjectParsed {
150150
{
151151
m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
152152
m_option_group.Finalize();
153+
CommandArgumentData platform_arg{eArgTypePlatform, eArgRepeatPlain};
154+
m_arguments.push_back({platform_arg});
153155
}
154156

155157
~CommandObjectPlatformSelect() override = default;
@@ -271,7 +273,10 @@ class CommandObjectPlatformConnect : public CommandObjectParsed {
271273
: CommandObjectParsed(
272274
interpreter, "platform connect",
273275
"Select the current platform by providing a connection URL.",
274-
"platform connect <connect-url>", 0) {}
276+
"platform connect <connect-url>", 0) {
277+
CommandArgumentData platform_arg{eArgTypeConnectURL, eArgRepeatPlain};
278+
m_arguments.push_back({platform_arg});
279+
}
275280

276281
~CommandObjectPlatformConnect() override = default;
277282

@@ -415,7 +420,10 @@ class CommandObjectPlatformMkDir : public CommandObjectParsed {
415420
CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
416421
: CommandObjectParsed(interpreter, "platform mkdir",
417422
"Make a new directory on the remote end.", nullptr,
418-
0) {}
423+
0) {
424+
CommandArgumentData thread_arg{eArgTypePath, eArgRepeatPlain};
425+
m_arguments.push_back({thread_arg});
426+
}
419427

420428
~CommandObjectPlatformMkDir() override = default;
421429

@@ -461,7 +469,10 @@ class CommandObjectPlatformFOpen : public CommandObjectParsed {
461469
public:
462470
CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
463471
: CommandObjectParsed(interpreter, "platform file open",
464-
"Open a file on the remote end.", nullptr, 0) {}
472+
"Open a file on the remote end.", nullptr, 0) {
473+
CommandArgumentData path_arg{eArgTypePath, eArgRepeatPlain};
474+
m_arguments.push_back({path_arg});
475+
}
465476

466477
~CommandObjectPlatformFOpen() override = default;
467478

@@ -521,7 +532,10 @@ class CommandObjectPlatformFClose : public CommandObjectParsed {
521532
public:
522533
CommandObjectPlatformFClose(CommandInterpreter &interpreter)
523534
: CommandObjectParsed(interpreter, "platform file close",
524-
"Close a file on the remote end.", nullptr, 0) {}
535+
"Close a file on the remote end.", nullptr, 0) {
536+
CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
537+
m_arguments.push_back({path_arg});
538+
}
525539

526540
~CommandObjectPlatformFClose() override = default;
527541

@@ -562,7 +576,10 @@ class CommandObjectPlatformFRead : public CommandObjectParsed {
562576
CommandObjectPlatformFRead(CommandInterpreter &interpreter)
563577
: CommandObjectParsed(interpreter, "platform file read",
564578
"Read data from a file on the remote end.", nullptr,
565-
0) {}
579+
0) {
580+
CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
581+
m_arguments.push_back({path_arg});
582+
}
566583

567584
~CommandObjectPlatformFRead() override = default;
568585

@@ -655,7 +672,10 @@ class CommandObjectPlatformFWrite : public CommandObjectParsed {
655672
CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
656673
: CommandObjectParsed(interpreter, "platform file write",
657674
"Write data to a file on the remote end.", nullptr,
658-
0) {}
675+
0) {
676+
CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
677+
m_arguments.push_back({path_arg});
678+
}
659679

660680
~CommandObjectPlatformFWrite() override = default;
661681

@@ -1070,6 +1090,10 @@ class CommandObjectPlatformPutFile : public CommandObjectParsed {
10701090
Relative source file paths are resolved against lldb's local working directory.
10711091
10721092
Omitting the destination places the file in the platform working directory.)");
1093+
CommandArgumentData source_arg{eArgTypePath, eArgRepeatPlain};
1094+
CommandArgumentData path_arg{eArgTypePath, eArgRepeatOptional};
1095+
m_arguments.push_back({source_arg});
1096+
m_arguments.push_back({path_arg});
10731097
}
10741098

10751099
~CommandObjectPlatformPutFile() override = default;
@@ -1121,6 +1145,8 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
11211145
eCommandRequiresTarget | eCommandTryTargetAPILock) {
11221146
m_all_options.Append(&m_options);
11231147
m_all_options.Finalize();
1148+
CommandArgumentData run_arg_arg{eArgTypeRunArgs, eArgRepeatStar};
1149+
m_arguments.push_back({run_arg_arg});
11241150
}
11251151

11261152
~CommandObjectPlatformProcessLaunch() override = default;
@@ -1229,83 +1255,78 @@ class CommandObjectPlatformProcessList : public CommandObjectParsed {
12291255

12301256
if (platform_sp) {
12311257
Status error;
1232-
if (args.GetArgumentCount() == 0) {
1233-
if (platform_sp) {
1234-
Stream &ostrm = result.GetOutputStream();
1235-
1236-
lldb::pid_t pid =
1237-
m_options.match_info.GetProcessInfo().GetProcessID();
1238-
if (pid != LLDB_INVALID_PROCESS_ID) {
1239-
ProcessInstanceInfo proc_info;
1240-
if (platform_sp->GetProcessInfo(pid, proc_info)) {
1241-
ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
1242-
m_options.verbose);
1243-
proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
1244-
m_options.show_args, m_options.verbose);
1245-
result.SetStatus(eReturnStatusSuccessFinishResult);
1246-
} else {
1247-
result.AppendErrorWithFormat(
1248-
"no process found with pid = %" PRIu64 "\n", pid);
1249-
}
1258+
if (platform_sp) {
1259+
Stream &ostrm = result.GetOutputStream();
1260+
1261+
lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
1262+
if (pid != LLDB_INVALID_PROCESS_ID) {
1263+
ProcessInstanceInfo proc_info;
1264+
if (platform_sp->GetProcessInfo(pid, proc_info)) {
1265+
ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
1266+
m_options.verbose);
1267+
proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
1268+
m_options.show_args, m_options.verbose);
1269+
result.SetStatus(eReturnStatusSuccessFinishResult);
12501270
} else {
1251-
ProcessInstanceInfoList proc_infos;
1252-
const uint32_t matches =
1253-
platform_sp->FindProcesses(m_options.match_info, proc_infos);
1254-
const char *match_desc = nullptr;
1255-
const char *match_name =
1256-
m_options.match_info.GetProcessInfo().GetName();
1257-
if (match_name && match_name[0]) {
1258-
switch (m_options.match_info.GetNameMatchType()) {
1259-
case NameMatch::Ignore:
1260-
break;
1261-
case NameMatch::Equals:
1262-
match_desc = "matched";
1263-
break;
1264-
case NameMatch::Contains:
1265-
match_desc = "contained";
1266-
break;
1267-
case NameMatch::StartsWith:
1268-
match_desc = "started with";
1269-
break;
1270-
case NameMatch::EndsWith:
1271-
match_desc = "ended with";
1272-
break;
1273-
case NameMatch::RegularExpression:
1274-
match_desc = "matched the regular expression";
1275-
break;
1276-
}
1271+
result.AppendErrorWithFormat(
1272+
"no process found with pid = %" PRIu64 "\n", pid);
1273+
}
1274+
} else {
1275+
ProcessInstanceInfoList proc_infos;
1276+
const uint32_t matches =
1277+
platform_sp->FindProcesses(m_options.match_info, proc_infos);
1278+
const char *match_desc = nullptr;
1279+
const char *match_name =
1280+
m_options.match_info.GetProcessInfo().GetName();
1281+
if (match_name && match_name[0]) {
1282+
switch (m_options.match_info.GetNameMatchType()) {
1283+
case NameMatch::Ignore:
1284+
break;
1285+
case NameMatch::Equals:
1286+
match_desc = "matched";
1287+
break;
1288+
case NameMatch::Contains:
1289+
match_desc = "contained";
1290+
break;
1291+
case NameMatch::StartsWith:
1292+
match_desc = "started with";
1293+
break;
1294+
case NameMatch::EndsWith:
1295+
match_desc = "ended with";
1296+
break;
1297+
case NameMatch::RegularExpression:
1298+
match_desc = "matched the regular expression";
1299+
break;
12771300
}
1301+
}
12781302

1279-
if (matches == 0) {
1280-
if (match_desc)
1281-
result.AppendErrorWithFormatv(
1282-
"no processes were found that {0} \"{1}\" on the \"{2}\" "
1283-
"platform\n",
1284-
match_desc, match_name, platform_sp->GetName());
1285-
else
1286-
result.AppendErrorWithFormatv(
1287-
"no processes were found on the \"{0}\" platform\n",
1288-
platform_sp->GetName());
1289-
} else {
1290-
result.AppendMessageWithFormatv(
1291-
"{0} matching process{1} found on \"{2}\"", matches,
1292-
matches > 1 ? "es were" : " was", platform_sp->GetName());
1293-
if (match_desc)
1294-
result.AppendMessageWithFormat(" whose name %s \"%s\"",
1295-
match_desc, match_name);
1296-
result.AppendMessageWithFormat("\n");
1297-
ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
1298-
m_options.verbose);
1299-
for (uint32_t i = 0; i < matches; ++i) {
1300-
proc_infos[i].DumpAsTableRow(
1301-
ostrm, platform_sp->GetUserIDResolver(),
1302-
m_options.show_args, m_options.verbose);
1303-
}
1303+
if (matches == 0) {
1304+
if (match_desc)
1305+
result.AppendErrorWithFormatv(
1306+
"no processes were found that {0} \"{1}\" on the \"{2}\" "
1307+
"platform\n",
1308+
match_desc, match_name, platform_sp->GetName());
1309+
else
1310+
result.AppendErrorWithFormatv(
1311+
"no processes were found on the \"{0}\" platform\n",
1312+
platform_sp->GetName());
1313+
} else {
1314+
result.AppendMessageWithFormatv(
1315+
"{0} matching process{1} found on \"{2}\"", matches,
1316+
matches > 1 ? "es were" : " was", platform_sp->GetName());
1317+
if (match_desc)
1318+
result.AppendMessageWithFormat(" whose name %s \"%s\"",
1319+
match_desc, match_name);
1320+
result.AppendMessageWithFormat("\n");
1321+
ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
1322+
m_options.verbose);
1323+
for (uint32_t i = 0; i < matches; ++i) {
1324+
proc_infos[i].DumpAsTableRow(
1325+
ostrm, platform_sp->GetUserIDResolver(), m_options.show_args,
1326+
m_options.verbose);
13041327
}
13051328
}
13061329
}
1307-
} else {
1308-
result.AppendError("invalid args: process list takes only options\n");
13091330
}
13101331
} else {
13111332
result.AppendError("no platform is selected\n");
@@ -1737,7 +1758,10 @@ class CommandObjectPlatformShell : public CommandObjectRaw {
17371758
CommandObjectPlatformShell(CommandInterpreter &interpreter)
17381759
: CommandObjectRaw(interpreter, "platform shell",
17391760
"Run a shell command on the current platform.",
1740-
"platform shell <shell-command>", 0) {}
1761+
"platform shell <shell-command>", 0) {
1762+
CommandArgumentData thread_arg{eArgTypeNone, eArgRepeatStar};
1763+
m_arguments.push_back({thread_arg});
1764+
}
17411765

17421766
~CommandObjectPlatformShell() override = default;
17431767

@@ -1824,7 +1848,12 @@ class CommandObjectPlatformInstall : public CommandObjectParsed {
18241848
: CommandObjectParsed(
18251849
interpreter, "platform target-install",
18261850
"Install a target (bundle or executable file) to the remote end.",
1827-
"platform target-install <local-thing> <remote-sandbox>", 0) {}
1851+
"platform target-install <local-thing> <remote-sandbox>", 0) {
1852+
CommandArgumentData local_arg{eArgTypePath, eArgRepeatPlain};
1853+
CommandArgumentData remote_arg{eArgTypePath, eArgRepeatPlain};
1854+
m_arguments.push_back({local_arg});
1855+
m_arguments.push_back({remote_arg});
1856+
}
18281857

18291858
~CommandObjectPlatformInstall() override = default;
18301859

0 commit comments

Comments
 (0)