int makeOptions_main()

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;
}