in Sources/makeOptions/makeOptions.cpp [194:399]
int makeOptions_main() {
// Check if options were available.
if (sizeof(rawOptions) == 0) {
std::cerr << "error: swift/Options/Options.inc unavailable at compile time\n";
return 1;
}
// Form the groups & record the ID mappings.
unsigned rawOptionIdx = 0;
for (const auto &rawOption : rawOptions) {
if (rawOption.isGroup()) {
std::string idName = rawOption.idName;
auto groupSuffixStart = idName.rfind("Group");
if (groupSuffixStart != std::string::npos) {
idName.erase(idName.begin() + groupSuffixStart, idName.end());
idName = swiftify(idName);
}
groupIndexByID[rawOption.id] = groups.size();
groups.push_back({idName, rawOption.spelling, rawOption.helpText});
++rawOptionIdx;
continue;
}
optionIndexByID[rawOption.id] = rawOptionIdx++;
}
// Add static properties to Option for each of the options.
auto &out = std::cout;
out <<
"//===--------------- Options.swift - Swift Driver Options -----------------===//\n"
"//\n"
"// This source file is part of the Swift.org open source project\n"
"//\n"
"// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors\n"
"// Licensed under Apache License v2.0 with Runtime Library Exception\n"
"//\n"
"// See https://swift.org/LICENSE.txt for license information\n"
"// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors\n"
"//\n"
"//===----------------------------------------------------------------------===//\n\n";
out << "extension Option {\n";
forEachOption([&](const RawOption &option) {
// Look through each spelling of the option.
forEachSpelling(option.prefixes, option.spelling,
[&](const std::string &spelling,
bool isAlternateSpelling) {
out << " public static let " << option.idName;
// Add a '_' suffix if this is an alternate spelling.
if (isAlternateSpelling)
out << "_";
// All options have Option type.
out << ": Option = Option(\"" << spelling << "\"";
out << ", ";
switch (option.kind) {
case OptionKind::Input:
out << ".input";
break;
case OptionKind::CommaJoined:
out << ".commaJoined";
break;
case OptionKind::Flag:
out << ".flag";
break;
case OptionKind::Joined:
out << ".joined";
break;
case OptionKind::JoinedOrSeparate:
out << ".joinedOrSeparate";
break;
case OptionKind::RemainingArgs:
out << ".remaining";
break;
case OptionKind::Separate:
out << ".separate";
break;
case OptionKind::Group:
case OptionKind::Unknown:
assert(false && "Should have been filtered out");
}
if (option.isAlias()) {
const auto &aliased = rawOptions[optionIndexByID[option.alias]];
out << ", alias: Option." << aliased.idName;
} else if (isAlternateSpelling) {
out << ", alias: Option." << option.idName;
}
if (option.flags != 0 || option.kind == OptionKind::Input) {
bool anyEmitted = false;
auto emitFlag = [&](const char *name) {
if (anyEmitted) {
out << ", ";
} else {
anyEmitted = true;
}
out << name;
};
auto emitFlagIf = [&](SwiftFlags flag, const char *name) {
if ((option.flags & flag) == 0) { return; }
emitFlag(name);
};
out << ", attributes: [";
emitFlagIf(HelpHidden, ".helpHidden");
emitFlagIf(FrontendOption, ".frontend");
emitFlagIf(NoDriverOption, ".noDriver");
emitFlagIf(NoInteractiveOption, ".noInteractive");
emitFlagIf(NoBatchOption, ".noBatch");
emitFlagIf(DoesNotAffectIncrementalBuild, ".doesNotAffectIncrementalBuild");
emitFlagIf(AutolinkExtractOption, ".autolinkExtract");
emitFlagIf(ModuleWrapOption, ".moduleWrap");
emitFlagIf(SwiftIndentOption, ".indent");
if (option.kind == OptionKind::Input)
emitFlag(".argumentIsPath");
else
emitFlagIf(ArgumentIsPath, ".argumentIsPath");
emitFlagIf(ModuleInterfaceOption, ".moduleInterface");
emitFlagIf(SupplementaryOutput, ".supplementaryOutput");
out << "]";
}
if (option.metaVar) {
out << ", metaVar: " << stringOrNil(option.metaVar);
}
if (option.helpText) {
out << ", helpText: " << stringOrNilLeftTrimmed(option.helpText);
}
if (option.group != OptionID::Opt_INVALID) {
out << ", group: ." << groups[groupIndexByID[option.group]].id;
}
out << ")\n";
});
});
out << "}\n";
// Produce an "allOptions" property containing all of the known options.
out << "\nextension Option {\n";
out << " public static var allOptions: [Option] {\n"
<< " return [\n";
forEachOption([&](const RawOption &option) {
// Look through each spelling of the option.
forEachSpelling(option.prefixes, option.spelling,
[&](const std::string &spelling,
bool isAlternateSpelling) {
out << " Option." << option.idName;
if (isAlternateSpelling)
out << "_";
out << ",\n";
});
});
out << " ]\n";
out << " }\n";
out << "}\n";
// Render the Option.Group type.
out << "\nextension Option {\n";
out << " public enum Group {\n";
for (const auto &group : groups) {
out << " case " << group.id << "\n";
}
out << " }\n";
out << "}\n";
// Retrieve the display name of the group.
out << "\n";
out << "extension Option.Group {\n";
out << " public var name: String {\n";
out << " switch self {\n";
for (const auto &group : groups) {
out << " case ." << group.id << ":\n";
out << " return \"" << group.name << "\"\n";
}
out << " }\n";
out << " }\n";
out << "}\n";
// Retrieve the help text for the group.
out << "\n";
out << "extension Option.Group {\n";
out << " public var helpText: String? {\n";
out << " switch self {\n";
for (const auto &group : groups) {
out << " case ." << group.id << ":\n";
out << " return " << stringOrNil(group.description) << "\n";
}
out << " }\n";
out << " }\n";
out << "}\n";
return 0;
}