mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[CommandLine] Allow Options to specify multiple OptionCategory's.
Summary: It's not uncommon for separate components to share common Options, e.g., it's common for related Passes to share Options in addition to the Pass specific ones. With this change, components can use OptionCategory's to simply help output even if some of the options are shared. Reviewed By: MaskRay Tags: #llvm Differential Revision: https://reviews.llvm.org/D61574 llvm-svn: 360179
This commit is contained in:
parent
7b21a4a264
commit
42885681b9
@ -281,7 +281,8 @@ public:
|
||||
StringRef ArgStr; // The argument string itself (ex: "help", "o")
|
||||
StringRef HelpStr; // The descriptive text message for -help
|
||||
StringRef ValueStr; // String describing what the value of this option is
|
||||
OptionCategory *Category; // The Category this option belongs to
|
||||
SmallVector<OptionCategory *, 2>
|
||||
Categories; // The Categories this option belongs to
|
||||
SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
|
||||
bool FullyInitialized = false; // Has addArgument been called?
|
||||
|
||||
@ -333,14 +334,16 @@ public:
|
||||
void setFormattingFlag(enum FormattingFlags V) { Formatting = V; }
|
||||
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
|
||||
void setPosition(unsigned pos) { Position = pos; }
|
||||
void setCategory(OptionCategory &C) { Category = &C; }
|
||||
void addCategory(OptionCategory &C);
|
||||
void addSubCommand(SubCommand &S) { Subs.insert(&S); }
|
||||
|
||||
protected:
|
||||
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
|
||||
enum OptionHidden Hidden)
|
||||
: Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden),
|
||||
Formatting(NormalFormatting), Misc(0), Category(&GeneralCategory) {}
|
||||
Formatting(NormalFormatting), Misc(0) {
|
||||
Categories.push_back(&GeneralCategory);
|
||||
}
|
||||
|
||||
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
|
||||
|
||||
@ -451,7 +454,7 @@ struct cat {
|
||||
|
||||
cat(OptionCategory &c) : Category(c) {}
|
||||
|
||||
template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
|
||||
template <class Opt> void apply(Opt &O) const { O.addCategory(Category); }
|
||||
};
|
||||
|
||||
// sub - Specify the subcommand that this option belongs to.
|
||||
@ -1770,7 +1773,7 @@ class alias : public Option {
|
||||
if (!Subs.empty())
|
||||
error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
|
||||
Subs = AliasFor->Subs;
|
||||
Category = AliasFor->Category;
|
||||
Categories = AliasFor->Categories;
|
||||
addArgument();
|
||||
}
|
||||
|
||||
|
@ -425,6 +425,17 @@ void Option::setArgStr(StringRef S) {
|
||||
setMiscFlag(Grouping);
|
||||
}
|
||||
|
||||
void Option::addCategory(OptionCategory &C) {
|
||||
assert(!Categories.empty() && "Categories cannot be empty.");
|
||||
// Maintain backward compatibility by replacing the default GeneralCategory
|
||||
// if it's still set. Otherwise, just add the new one. The GeneralCategory
|
||||
// must be explicitly added if you want multiple categories that include it.
|
||||
if (&C != &GeneralCategory && Categories[0] == &GeneralCategory)
|
||||
Categories[0] = &C;
|
||||
else
|
||||
Categories.push_back(&C);
|
||||
}
|
||||
|
||||
void Option::reset() {
|
||||
NumOccurrences = 0;
|
||||
setDefault();
|
||||
@ -2132,9 +2143,11 @@ protected:
|
||||
// options within categories will also be alphabetically sorted.
|
||||
for (size_t I = 0, E = Opts.size(); I != E; ++I) {
|
||||
Option *Opt = Opts[I].second;
|
||||
assert(CategorizedOptions.count(Opt->Category) > 0 &&
|
||||
"Option has an unregistered category");
|
||||
CategorizedOptions[Opt->Category].push_back(Opt);
|
||||
for (auto &Cat : Opt->Categories) {
|
||||
assert(CategorizedOptions.count(Cat) > 0 &&
|
||||
"Option has an unregistered category");
|
||||
CategorizedOptions[Cat].push_back(Opt);
|
||||
}
|
||||
}
|
||||
|
||||
// Now do printing.
|
||||
@ -2391,21 +2404,21 @@ cl::getRegisteredSubcommands() {
|
||||
|
||||
void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
|
||||
for (auto &I : Sub.OptionsMap) {
|
||||
if (I.second->Category != &Category &&
|
||||
I.second->Category != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
for (auto &Cat : I.second->Categories) {
|
||||
if (Cat != &Category &&
|
||||
Cat != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
|
||||
SubCommand &Sub) {
|
||||
auto CategoriesBegin = Categories.begin();
|
||||
auto CategoriesEnd = Categories.end();
|
||||
for (auto &I : Sub.OptionsMap) {
|
||||
if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) ==
|
||||
CategoriesEnd &&
|
||||
I.second->Category != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
for (auto &Cat : I.second->Categories) {
|
||||
if (find(Categories, Cat) == Categories.end() && Cat != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,12 +95,20 @@ TEST(CommandLineTest, ModifyExisitingOption) {
|
||||
cl::Option *Retrieved = Map["test-option"];
|
||||
ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
|
||||
|
||||
ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) <<
|
||||
"Incorrect default option category.";
|
||||
ASSERT_NE(Retrieved->Categories.end(),
|
||||
find_if(Retrieved->Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &cl::GeneralCategory;
|
||||
}))
|
||||
<< "Incorrect default option category.";
|
||||
|
||||
Retrieved->setCategory(TestCategory);
|
||||
ASSERT_EQ(&TestCategory,Retrieved->Category) <<
|
||||
"Failed to modify option's option category.";
|
||||
Retrieved->addCategory(TestCategory);
|
||||
ASSERT_NE(Retrieved->Categories.end(),
|
||||
find_if(Retrieved->Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
<< "Failed to modify option's option category.";
|
||||
|
||||
Retrieved->setDescription(Description);
|
||||
ASSERT_STREQ(Retrieved->HelpStr.data(), Description)
|
||||
@ -152,8 +160,52 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
|
||||
TEST(CommandLineTest, UseOptionCategory) {
|
||||
StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
|
||||
|
||||
ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
|
||||
"Category.";
|
||||
ASSERT_NE(TestOption2.Categories.end(),
|
||||
find_if(TestOption2.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
<< "Failed to assign Option Category.";
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, UseMultipleCategories) {
|
||||
StackOption<int> TestOption2("test-option2", cl::cat(TestCategory),
|
||||
cl::cat(cl::GeneralCategory));
|
||||
|
||||
ASSERT_NE(TestOption2.Categories.end(),
|
||||
find_if(TestOption2.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
<< "Failed to assign Option Category.";
|
||||
ASSERT_NE(TestOption2.Categories.end(),
|
||||
find_if(TestOption2.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &cl::GeneralCategory;
|
||||
}))
|
||||
<< "Failed to assign General Category.";
|
||||
|
||||
cl::OptionCategory AnotherCategory("Additional test Options", "Description");
|
||||
StackOption<int> TestOption("test-option", cl::cat(TestCategory),
|
||||
cl::cat(AnotherCategory));
|
||||
ASSERT_EQ(TestOption.Categories.end(),
|
||||
find_if(TestOption.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &cl::GeneralCategory;
|
||||
}))
|
||||
<< "Failed to remove General Category.";
|
||||
ASSERT_NE(TestOption.Categories.end(),
|
||||
find_if(TestOption.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
<< "Failed to assign Option Category.";
|
||||
ASSERT_NE(TestOption.Categories.end(),
|
||||
find_if(TestOption.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &AnotherCategory;
|
||||
}))
|
||||
<< "Failed to assign Another Category.";
|
||||
}
|
||||
|
||||
typedef void ParserFunction(StringRef Source, StringSaver &Saver,
|
||||
|
Loading…
Reference in New Issue
Block a user