1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[Support][CommandLine] Add cl::getRegisteredSubcommands()

This should allow users of the library to get a range to iterate through
all the subcommands that are registered to the global parser. This
allows users to define subcommands in libraries that self-register to
have dispatch done at a different stage (like main). It allows for
writing code like the following:

    for (auto *S : cl::getRegisteredSubcommands()) {
      if (*S) {
	// Dispatch on S->getName().
      }
    }

This change also contains tests that show this usage pattern.

Reviewers: zturner, dblaikie, echristo

Subscribers: llvm-commits, mehdi_amini

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

llvm-svn: 281290
This commit is contained in:
Dean Michael Berris 2016-09-13 02:35:00 +00:00
parent c66bb3ef24
commit 7d7d82f567
3 changed files with 56 additions and 0 deletions

View File

@ -1736,6 +1736,28 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false);
/// than just handing around a global list.
StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand);
/// \brief Use this to get all registered SubCommands from the provided parser.
///
/// \return A range of all SubCommand pointers registered with the parser.
///
/// Typical usage:
/// \code
/// main(int argc, char* argv[]) {
/// llvm::cl::ParseCommandLineOptions(argc, argv);
/// for (auto* S : llvm::cl::getRegisteredSubcommands()) {
/// if (*S) {
/// std::cout << "Executing subcommand: " << S->getName() << std::endl;
/// // Execute some function based on the name...
/// }
/// }
/// }
/// \endcode
///
/// This interface is useful for defining subcommands in libraries and
/// the dispatch from a single point (like in the main function).
iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator>
getRegisteredSubcommands();
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
//

View File

@ -309,6 +309,12 @@ public:
RegisteredSubCommands.erase(sub);
}
iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator>
getRegisteredSubcommands() {
return make_range(RegisteredSubCommands.begin(),
RegisteredSubCommands.end());
}
void reset() {
ActiveSubCommand = nullptr;
ProgramName.clear();
@ -2105,6 +2111,11 @@ StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {
return Sub.OptionsMap;
}
iterator_range<typename SmallPtrSet<SubCommand *, 4>::iterator>
cl::getRegisteredSubcommands() {
return GlobalParser->getRegisteredSubcommands();
}
void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
for (auto &I : Sub.OptionsMap) {
if (I.second->Category != &Category &&

View File

@ -476,4 +476,27 @@ TEST(CommandLineTest, RemoveFromAllSubCommands) {
EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
}
TEST(CommandLineTest, GetRegisteredSubcommands) {
cl::ResetCommandLineParser();
StackSubCommand SC1("sc1", "First Subcommand");
StackSubCommand SC2("sc2", "Second subcommand");
const char *args0[] = {"prog", "sc1"};
const char *args1[] = {"prog", "sc2"};
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, nullptr, true));
for (auto *S : cl::getRegisteredSubcommands()) {
if (*S)
EXPECT_STREQ("sc1", S->getName());
}
cl::ResetAllOptionOccurrences();
EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1, nullptr, true));
for (auto *S : cl::getRegisteredSubcommands()) {
if (*S)
EXPECT_STREQ("sc2", S->getName());
}
}
} // anonymous namespace