int main()

in tools/swift-ide-test/swift-ide-test.cpp [4120:4647]


int main(int argc, char *argv[]) {
  PROGRAM_START(argc, argv);
  INITIALIZE_LLVM();

  if (argc > 1) {
    // Handle integrated test tools which do not use
    // llvm::cl::ParseCommandLineOptions.
    StringRef FirstArg(argv[1]);
    if (FirstArg == "-test-createCompilerInvocation") {
      bool ForceNoOutputs = false;
      ArrayRef<const char *> Args(argv + 2, argc - 2);
      if (argc > 2 && StringRef(argv[2]) == "-force-no-outputs") {
        ForceNoOutputs = true;
        Args = Args.drop_front();
      }
      return doTestCreateCompilerInvocation(Args, ForceNoOutputs);
    }
  }

  // '--cc-args' separates swift-ide-test options from clang arguments.
  ArrayRef<const char *> CCArgs;
  for (int i = 1; i < argc; ++i) {
    if (StringRef(argv[i]) == "--cc-args") {
      CCArgs = llvm::makeArrayRef(argv+i+1, argc-i-1);
      argc = i;
    }
  }

  llvm::cl::HideUnrelatedOptions(options::Category);
  llvm::cl::ParseCommandLineOptions(argc, argv, "Swift IDE Test\n");

  if (options::Action == ActionType::None) {
    llvm::errs() << "action required\n";
    llvm::cl::PrintHelpMessage();
    return 1;
  }

  if (options::Action == ActionType::TestCreateCompilerInvocation) {
    llvm::errs() << "-test-createCompilerInvocation must be specified before "
                    "all other arguments\n";
    return 1;
  }

  if (options::Action == ActionType::GenerateModuleAPIDescription) {
    return doGenerateModuleAPIDescription(
        llvm::sys::fs::getMainExecutable(
            argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable)),
        options::InputFilenames);
  }

  if (options::Action == ActionType::DumpCompletionCache) {
    if (options::InputFilenames.empty()) {
      llvm::errs() << "-dump-completion-cache requires an input file\n";
      return 1;
    }

    for (StringRef filename : options::InputFilenames) {
      auto resultsOpt = ide::OnDiskCodeCompletionCache::getFromFile(filename);
      if (!resultsOpt) {
        // FIXME: error?
        continue;
      }
      printCodeCompletionResultsImpl(
          resultsOpt->get()->Sink.Results, llvm::outs(),
          options::CodeCompletionKeywords, options::CodeCompletionComments,
          options::CodeCompletionSourceText,
          options::CodeCompletionAnnotateResults);
    }

    return 0;
  }

  if (options::SourceFilename.empty()) {
    llvm::errs() << "source file required\n";
    llvm::cl::PrintHelpMessage();
    return 1;
  }

  if (options::Action == ActionType::CompilerInvocationFromModule) {
    return doTestCompilerInvocationFromModule(options::SourceFilename);
  }

  // If no SDK was specified via -sdk, check environment variable SDKROOT.
  if (options::SDK.getNumOccurrences() == 0) {
    const char *SDKROOT = getenv("SDKROOT");
    if (SDKROOT)
      options::SDK = SDKROOT;
  }

  if (options::PrintStats)
    llvm::EnableStatistics();

  CompilerInvocation InitInvok;

  InitInvok.getFrontendOptions().RequestedAction = FrontendOptions::ActionType::Typecheck;

  for (auto &File : options::InputFilenames)
    InitInvok.getFrontendOptions().InputsAndOutputs.addInputFile(File);

  InitInvok.setMainExecutablePath(
      llvm::sys::fs::getMainExecutable(argv[0],
          reinterpret_cast<void *>(&anchorForGetMainExecutable)));
  InitInvok.setModuleName(options::ModuleName);

  InitInvok.setSDKPath(options::SDK);

  if (!options::DefineAvailability.empty()) {
    InitInvok.getLangOptions().AvailabilityMacros.push_back(options::DefineAvailability);
  }
  for (auto map: options::SerializedPathObfuscate) {
    auto SplitMap = StringRef(map).split('=');
    InitInvok.getFrontendOptions().serializedPathObfuscator
      .addMapping(SplitMap.first, SplitMap.second);
    InitInvok.getSearchPathOptions().DeserializedPathRecoverer
      .addMapping(SplitMap.first, SplitMap.second);
  }
  InitInvok.getLangOptions().CollectParsedToken = true;
  InitInvok.getLangOptions().BuildSyntaxTree = true;
  InitInvok.getLangOptions().EnableCrossImportOverlays =
    options::EnableCrossImportOverlays;
  if (options::DisableObjCInterop) {
    InitInvok.getLangOptions().EnableObjCInterop = false;
  } else if (options::EnableObjCInterop) {
    InitInvok.getLangOptions().EnableObjCInterop = true;
  } else if (!options::Triple.empty()) {
    InitInvok.getLangOptions().EnableObjCInterop =
        llvm::Triple(options::Triple).isOSDarwin();
  }
  if (options::EnableCxxInterop) {
    InitInvok.getLangOptions().EnableCXXInterop = true;
  }
  if (options::EnableExperimentalConcurrency) {
    InitInvok.getLangOptions().EnableExperimentalConcurrency = true;
  }
  if (options::WarnConcurrency) {
    InitInvok.getLangOptions().WarnConcurrency = true;
  }
  if (options::DisableImplicitConcurrencyImport) {
    InitInvok.getLangOptions().DisableImplicitConcurrencyModuleImport = true;
  }
  if (options::EnableExperimentalNamedOpaqueTypes) {
    InitInvok.getLangOptions().EnableExperimentalNamedOpaqueTypes = true;
  }

  if (options::EnableExperimentalDistributed) {
    // distributed implies concurrency features:
    InitInvok.getLangOptions().EnableExperimentalConcurrency = true;
    // enable 'distributed' parsing and features
    InitInvok.getLangOptions().EnableExperimentalDistributed = true;
  }

  if (!options::Triple.empty())
    InitInvok.setTargetTriple(options::Triple);
  if (!options::SwiftVersion.empty()) {
    // Honor the *last* -swift-version specified.
    const auto &LastSwiftVersion =
      options::SwiftVersion[options::SwiftVersion.size()-1];
    if (auto swiftVersion =
          version::Version::parseVersionString(LastSwiftVersion,
                                               SourceLoc(), nullptr)) {
      if (auto actual = swiftVersion.getValue().getEffectiveLanguageVersion())
        InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue();
    }
  }
  if (!options::ToolsDirectory.empty()) {
    SmallString<128> toolsDir(options::ToolsDirectory);
    llvm::sys::path::append(toolsDir, "clang");
    InitInvok.getClangImporterOptions().clangPath =
        std::string(toolsDir);
  }
  if (!options::ModuleCachePath.empty()) {
    // Honor the *last* -module-cache-path specified.
    InitInvok.getClangImporterOptions().ModuleCachePath =
        options::ModuleCachePath[options::ModuleCachePath.size()-1];
  }
  if (!options::AccessNotesPath.empty()) {
    InitInvok.getFrontendOptions().AccessNotesPath =
        options::AccessNotesPath[options::AccessNotesPath.size()-1];
  }
  if (options::ParseAsLibrary) {
    InitInvok.getFrontendOptions().InputMode =
        swift::FrontendOptions::ParseInputMode::SwiftLibrary;
  }
  InitInvok.getClangImporterOptions().PrecompiledHeaderOutputDir =
    options::PCHOutputDir;
  InitInvok.setImportSearchPaths(options::ImportPaths);
  std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths;
  for (const auto &path : options::FrameworkPaths) {
    FramePaths.push_back({path, /*isSystem=*/false});
  }
  for (const auto &path : options::SystemFrameworkPaths) {
    FramePaths.push_back({path, /*isSystem=*/true});
  }
  InitInvok.setFrameworkSearchPaths(FramePaths);
  InitInvok.getFrontendOptions().EnableSourceImport |=
    options::EnableSourceImport;
  InitInvok.getFrontendOptions().ImplicitObjCHeaderPath =
    options::ImportObjCHeader;
  InitInvok.getClangImporterOptions().BridgingHeader =
    options::ImportObjCHeader;
  InitInvok.getLangOptions().EnableAccessControl =
    !options::DisableAccessControl;
  InitInvok.getLangOptions().EnableSwift3ObjCInference =
    options::EnableSwift3ObjCInference;
  InitInvok.getClangImporterOptions().ImportForwardDeclarations |=
    options::ObjCForwardDeclarations;
  if (!options::ResourceDir.empty()) {
    InitInvok.setRuntimeResourcePath(options::ResourceDir);
  }
  for (auto &Arg : options::ClangXCC) {
    InitInvok.getClangImporterOptions().ExtraArgs.push_back(Arg);
  }
  InitInvok.getLangOptions().EnableObjCAttrRequiresFoundation =
    !options::DisableObjCAttrRequiresFoundationModule;
  InitInvok.getTypeCheckerOptions().DebugForbidTypecheckPrefix =
    options::DebugForbidTypecheckPrefix;
  InitInvok.getTypeCheckerOptions().DebugConstraintSolver =
      options::DebugConstraintSolver;

  for (auto ConfigName : options::BuildConfigs)
    InitInvok.getLangOptions().addCustomConditionalCompilationFlag(ConfigName);

  if (!options::ExplicitSwiftModuleMap.empty()) {
    InitInvok.getSearchPathOptions().ExplicitSwiftModuleMap =
      options::ExplicitSwiftModuleMap;
    InitInvok.getFrontendOptions().DisableImplicitModules = true;
  }

  if (options::AllowCompilerErrors) {
    InitInvok.getFrontendOptions().AllowModuleWithCompilerErrors = true;
    InitInvok.getLangOptions().AllowModuleWithCompilerErrors = true;
  }

  if (!options::ModuleAliases.empty()) {
    PrintingDiagnosticConsumer PDC;
    SourceManager SM;
    DiagnosticEngine Diags(SM);
    Diags.addConsumer(PDC);
    if (!InitInvok.setModuleAliasMap(options::ModuleAliases, Diags)) {
      llvm::errs() << "invalid module alias arguments\n";
      return 1;
    }
  }

  // Process the clang arguments last and allow them to override previously
  // set options.
  if (!CCArgs.empty()) {
    std::string Error;
    if (initInvocationByClangArguments(CCArgs, InitInvok, Error)) {
      llvm::errs() << "error initializing invocation with clang args: "
        << Error << '\n';
      return 1;
    }
  }

  PrintOptions PrintOpts;
  if (options::PrintInterface) {
    PrintOpts = PrintOptions::printModuleInterface(
        InitInvok.getFrontendOptions().PrintFullConvention);
  } else if (options::PrintInterfaceForDoc) {
    PrintOpts = PrintOptions::printDocInterface();
  } else {
    PrintOpts = PrintOptions::printEverything();
    PrintOpts.FullyQualifiedTypes = options::FullyQualifiedTypes;
    PrintOpts.FullyQualifiedTypesIfAmbiguous =
      options::FullyQualifiedTypesIfAmbiguous;
    PrintOpts.SynthesizeSugarOnTypes = options::SynthesizeSugarOnTypes;
    PrintOpts.AbstractAccessors = options::AbstractAccessors;
    PrintOpts.FunctionDefinitions = options::FunctionDefinitions;
    PrintOpts.PrintExprs = options::Expressions;
    PrintOpts.PreferTypeRepr = options::PreferTypeRepr;
    PrintOpts.ExplodePatternBindingDecls = options::ExplodePatternBindingDecls;
    PrintOpts.PrintImplicitAttrs = options::PrintImplicitAttrs;
    PrintOpts.PrintAccess = options::PrintAccess;
    PrintOpts.AccessFilter = options::AccessFilter;
    PrintOpts.PrintDocumentationComments = !options::SkipDocumentationComments;
    PrintOpts.PrintRegularClangComments = options::PrintRegularComments;
    PrintOpts.SkipPrivateStdlibDecls = options::SkipPrivateStdlibDecls;
    PrintOpts.SkipUnavailable = options::SkipUnavailable;
    PrintOpts.SkipDeinit = options::SkipDeinit;
    PrintOpts.SkipImports = options::SkipImports;
    PrintOpts.SkipOverrides = options::SkipOverrides;
    if (options::SkipParameterNames) {
      PrintOpts.ArgAndParamPrinting
        = PrintOptions::ArgAndParamPrintingMode::ArgumentOnly;
    } else if (options::AlwaysArgumentLabels) {
      PrintOpts.ArgAndParamPrinting
        = PrintOptions::ArgAndParamPrintingMode::BothAlways;
    }
  }
  if (options::SkipUnderscoredStdlibProtocols)
    PrintOpts.SkipUnderscoredStdlibProtocols = true;
  if (options::PrintOriginalSourceText)
    PrintOpts.PrintOriginalSourceText = true;

  if (PrintOpts.PrintDocumentationComments) {
    InitInvok.getLangOptions().AttachCommentsToDecls = true;
  }

  int ExitCode;

  switch (options::Action) {
  case ActionType::None:
  case ActionType::TestCreateCompilerInvocation:
  case ActionType::CompilerInvocationFromModule:
  case ActionType::GenerateModuleAPIDescription:
  case ActionType::DiffModuleAPI:
  case ActionType::DumpCompletionCache:
    llvm_unreachable("should be handled above");

  case ActionType::BatchCodeCompletion:
    if (options::FileCheckPath.empty() && !options::SkipFileCheck) {
      llvm::errs() << "'FileCheck' path required or explicitly specify "
                   << "'-skip-filecheck'\n";
      return 1;
    }
    ExitCode = doBatchCodeCompletion(
        InitInvok, options::SourceFilename, options::CodeCompletionDiagnostics,
        options::CodeCompletionKeywords, options::CodeCompletionComments,
        options::CodeCompletionAnnotateResults,
        options::CodeCompleteInitsInPostfixExpr,
        options::CodeCompleteCallPatternHeuristics,
        options::CodeCompletionAddCallWithNoDefaultArgs,
        options::CodeCompletionSourceText);
    break;

  case ActionType::CodeCompletion:
    if (options::CodeCompletionToken.empty()) {
      llvm::errs() << "code completion token name required\n";
      return 1;
    }
    ExitCode = doCodeCompletion(
        InitInvok, options::SourceFilename, options::SecondSourceFilename,
        options::CodeCompletionToken, options::CodeCompletionDiagnostics,
        options::CodeCompletionKeywords, options::CodeCompletionComments,
        options::CodeCompletionAnnotateResults,
        options::CodeCompleteInitsInPostfixExpr,
        options::CodeCompleteCallPatternHeuristics,
        options::CodeCompletionAddCallWithNoDefaultArgs,
        options::CodeCompletionSourceText);
    break;

  case ActionType::REPLCodeCompletion:
    ExitCode = doREPLCodeCompletion(InitInvok, options::SourceFilename);
    break;

  case ActionType::TypeContextInfo:
    if (options::CodeCompletionToken.empty()) {
      llvm::errs() << "token name required\n";
      return 1;
    }
    ExitCode = doTypeContextInfo(InitInvok,
                                  options::SourceFilename,
                                  options::SecondSourceFilename,
                                  options::CodeCompletionToken,
                                  options::CodeCompletionDiagnostics);
    break;

  case ActionType::PrintExpressionTypes:
    ExitCode = doPrintExpressionTypes(InitInvok,
                                      options::SourceFilename);
    break;


  case ActionType::ConformingMethodList:
    if (options::CodeCompletionToken.empty()) {
      llvm::errs() << "token name required\n";
      return 1;
    }
    ExitCode = doConformingMethodList(InitInvok,
                                      options::SourceFilename,
                                      options::SecondSourceFilename,
                                      options::CodeCompletionToken,
                                      options::CodeCompletionDiagnostics,
                                      options::ConformingMethodListExpectedTypes);
    break;

  case ActionType::SyntaxColoring:
    ExitCode = doSyntaxColoring(InitInvok,
                                options::SourceFilename,
                                options::TerminalOutput,
                                options::Typecheck,
                                options::Playground);
    break;

  case ActionType::DumpImporterLookupTable:
    ExitCode = doDumpImporterLookupTables(InitInvok, options::SourceFilename);
    break;

  case ActionType::Structure:
    ExitCode = doStructureAnnotation(InitInvok, options::SourceFilename);
    break;

  case ActionType::Annotation:
    ExitCode = doSemanticAnnotation(InitInvok,
                                    options::SourceFilename,
                                    options::TerminalOutput);
    break;

  case ActionType::TestInputCompleteness:
    ExitCode = doInputCompletenessTest(options::SourceFilename);
    break;

  case ActionType::PrintASTNotTypeChecked:
  case ActionType::PrintASTTypeChecked: {
    bool RunTypeChecker = (options::Action == ActionType::PrintASTTypeChecked);
    ExitCode = doPrintAST(InitInvok,
                          options::SourceFilename,
                          RunTypeChecker,
                          PrintOpts,
                          options::MangledNameToFind,
                          options::DebugClientDiscriminator);
    break;
  }
  case ActionType::PrintLocalTypes:
    ExitCode = doPrintLocalTypes(InitInvok, options::ModuleToPrint);
    break;

  case ActionType::PrintModuleGroups:
  case ActionType::PrintModule: {
    ide::ModuleTraversalOptions TraversalOptions;
    if (options::ModulePrintSubmodules)
      TraversalOptions |= ide::ModuleTraversal::VisitSubmodules;
    if (options::ModulePrintHidden)
      TraversalOptions |= ide::ModuleTraversal::VisitHidden;
    if (options::ModulePrintSkipOverlay)
      TraversalOptions |= ide::ModuleTraversal::SkipOverlay;

    if (options::Action == ActionType::PrintModuleGroups)
      ExitCode = doPrintModuleGroups(InitInvok, options::ModuleToPrint);
    else {
      if (options::NoEmptyLineBetweenMembers.getNumOccurrences() > 0)
        PrintOpts.EmptyLineBetweenMembers = !options::NoEmptyLineBetweenMembers;
      ExitCode = doPrintModules(
        InitInvok, options::ModuleToPrint, options::ModuleGroupToPrint,
        TraversalOptions, PrintOpts, options::AnnotatePrint,
        options::SynthesizeExtension);
    }
    break;
  }
  case ActionType::PrintModuleMetadata: {
    ExitCode = doPrintModuleMetaData(InitInvok, options::ModuleToPrint);
    break;
  }
  case ActionType::PrintHeader: {
    ExitCode = doPrintHeaders(
        InitInvok, options::HeaderToPrint, PrintOpts,
        options::AnnotatePrint);
    break;
  }

  case ActionType::PrintSwiftFileInterface: {
    ExitCode = doPrintSwiftFileInterface(
        InitInvok, options::SourceFilename,
        options::AnnotatePrint);
    break;
  }

  case ActionType::PrintDecl: {
    ExitCode = doPrintDecls(
        InitInvok, options::SourceFilename,
        options::DeclToPrint, PrintOpts, options::AnnotatePrint);
    break;
  }

  case ActionType::PrintTypes:
    ExitCode = doPrintTypes(InitInvok, options::SourceFilename,
                            options::FullyQualifiedTypes);
    break;

  case ActionType::PrintComments:
    ExitCode = doPrintComments(InitInvok, options::SourceFilename,
                               options::CommentsXMLSchema);
    break;

  case ActionType::DumpComments:
    ExitCode = doDumpComments(InitInvok, options::SourceFilename);
    break;

  case ActionType::PrintModuleComments:
    ExitCode = doPrintModuleComments(InitInvok, options::ModuleToPrint,
                                     options::CommentsXMLSchema);
    break;

  case ActionType::PrintModuleImports:
    ExitCode = doPrintModuleImports(InitInvok, options::ModuleToPrint);
    break;

  case ActionType::PrintUSRs:
    ExitCode = doPrintUSRs(InitInvok, options::SourceFilename);
    break;
  case ActionType::PrintTypeInterface:
    if (options::LineColumnPair.getNumOccurrences() == 1)
      ExitCode = doPrintTypeInterface(InitInvok,
                                      options::SourceFilename,
                                      options::LineColumnPair);
    else
      ExitCode = doPrintTypeInterfaceForTypeUsr(InitInvok,
                                                options::SourceFilename,
                                                options::USR);
    break;
  case ActionType::ReconstructType:
    ExitCode = doReconstructType(InitInvok, options::SourceFilename);
    break;
  case ActionType::Range:
    ExitCode = doPrintRangeInfo(InitInvok, options::SourceFilename,
                                options::LineColumnPair,
                                options::EndLineColumnPair);
    break;
  case ActionType::PrintIndexedSymbols:
      if (options::ModuleToPrint.empty()) {
        ExitCode = doPrintIndexedSymbols(InitInvok, options::SourceFilename,
                                         options::IncludeLocals);
      } else {
        if (options::ModuleToPrint.size() > 1) {
          llvm::errs() << "printing symbols for the first module name, the rest "
            "are ignored";
        }
        ExitCode = doPrintIndexedSymbolsFromModule(InitInvok,
                                               options::ModuleToPrint.front());
      }
  }

  if (options::PrintStats)
    llvm::PrintStatistics();

  return ExitCode;
}