//===--- ScanDependencies.cpp -- Scans the dependencies of a module -------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "ScanDependencies.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/Module.h"
#include "swift/AST/ModuleDependencies.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/SourceFile.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/Frontend/ModuleInterfaceLoader.h"
#include "swift/Strings.h"
#include "clang/Basic/Module.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/YAMLParser.h"
#include <set>

using namespace swift;
using namespace llvm::yaml;

namespace {
struct BatchScanInput {
  StringRef moduleName;
  StringRef arguments;
  StringRef outputPath;
  bool isSwift;
};

static std::string getScalaNodeText(Node *N) {
  SmallString<32> Buffer;
  return cast<ScalarNode>(N)->getValue(Buffer).str();
}

/// Parse an entry like this, where the "platforms" key-value pair is optional:
///  {
///     "swiftModuleName": "Foo",
///     "arguments": "-target 10.15",
///     "output": "../Foo.json"
///  },
static bool parseBatchInputEntries(ASTContext &Ctx, llvm::StringSaver &saver,
                                   Node *Node, std::vector<BatchScanInput> &result) {
  auto *SN = cast<SequenceNode>(Node);
  if (!SN)
    return true;
  for (auto It = SN->begin(); It != SN->end(); ++It) {
    auto *MN = cast<MappingNode>(&*It);
    BatchScanInput entry;
    Optional<std::set<int8_t>> Platforms;
    for (auto &Pair: *MN) {
      auto Key = getScalaNodeText(Pair.getKey());
      auto* Value = Pair.getValue();
      if (Key == "clangModuleName") {
        entry.moduleName = saver.save(getScalaNodeText(Value));
        entry.isSwift = false;
      } else if (Key == "swiftModuleName") {
        entry.moduleName = saver.save(getScalaNodeText(Value));
        entry.isSwift = true;
      } else if (Key == "arguments") {
        entry.arguments = saver.save(getScalaNodeText(Value));
      } else if (Key == "output") {
        entry.outputPath = saver.save(getScalaNodeText(Value));
      } else {
        // Future proof.
        continue;
      }
    }
    if (entry.moduleName.empty())
      return true;
    if (entry.outputPath.empty())
      return true;
    result.emplace_back(std::move(entry));
  }
  return false;
}

static Optional<std::vector<BatchScanInput>>
parseBatchScanInputFile(ASTContext &ctx, StringRef batchInputPath,
                        llvm::StringSaver &saver) {
  assert(!batchInputPath.empty());
  namespace yaml = llvm::yaml;
  std::vector<BatchScanInput> result;

  // Load the input file.
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
    llvm::MemoryBuffer::getFile(batchInputPath);
  if (!FileBufOrErr) {
    ctx.Diags.diagnose(SourceLoc(), diag::batch_scan_input_file_missing,
                       batchInputPath);
    return None;
  }
  StringRef Buffer = FileBufOrErr->get()->getBuffer();

  // Use a new source manager instead of the one from ASTContext because we
  // don't want the Json file to be persistent.
  SourceManager SM;
  yaml::Stream Stream(llvm::MemoryBufferRef(Buffer, batchInputPath),
                      SM.getLLVMSourceMgr());
  for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) {
    assert(DI != Stream.end() && "Failed to read a document");
    yaml::Node *N = DI->getRoot();
    assert(N && "Failed to find a root");
    if (parseBatchInputEntries(ctx, saver, N, result)) {
      ctx.Diags.diagnose(SourceLoc(), diag::batch_scan_input_file_corrupted,
                         batchInputPath);
      return None;
    }
  }
  return result;
}
}

/// Find all of the imported Clang modules starting with the given module name.
static void findAllImportedClangModules(ASTContext &ctx, StringRef moduleName,
                                        ModuleDependenciesCache &cache,
                                        std::vector<std::string> &allModules,
                                        llvm::StringSet<> &knownModules) {
  if (!knownModules.insert(moduleName).second)
    return;
  allModules.push_back(moduleName.str());

  auto dependencies = cache.findDependencies(
      moduleName, ModuleDependenciesKind::Clang);
  if (!dependencies)
    return;

  for (const auto &dep : dependencies->getModuleDependencies()) {
    findAllImportedClangModules(ctx, dep, cache, allModules, knownModules);
  }
}

/// Resolve the direct dependencies of the given module.
static std::vector<ModuleDependencyID> resolveDirectDependencies(
    CompilerInstance &instance, ModuleDependencyID module,
    ModuleDependenciesCache &cache,
    InterfaceSubContextDelegate &ASTDelegate) {
  auto &ctx = instance.getASTContext();
  auto knownDependencies = *cache.findDependencies(module.first, module.second);
  auto isSwift = knownDependencies.isSwiftTextualModule();

  // Find the dependencies of every module this module directly depends on.
  std::set<ModuleDependencyID> result;
  for (auto dependsOn : knownDependencies.getModuleDependencies()) {
    // Figure out what kind of module we need.
    bool onlyClangModule = !isSwift || module.first == dependsOn;

    // Retrieve the dependencies for this module.
    if (auto found = ctx.getModuleDependencies(
            dependsOn, onlyClangModule, cache, ASTDelegate)) {
      result.insert({dependsOn, found->getKind()});
    }
  }

  if (isSwift) {
    // A record of all of the Clang modules referenced from this Swift module.
    std::vector<std::string> allClangModules;
    llvm::StringSet<> knownModules;

    // If the Swift module has a bridging header, add those dependencies.
    if (knownDependencies.getBridgingHeader()) {
      auto clangImporter =
          static_cast<ClangImporter *>(ctx.getClangModuleLoader());
      if (!clangImporter->addBridgingHeaderDependencies(module.first, cache)) {
        // Grab the updated module dependencies.
        // FIXME: This is such a hack.
        knownDependencies = *cache.findDependencies(module.first, module.second);

        // Add the Clang modules referenced from the bridging header to the
        // set of Clang modules we know about.
        auto swiftDeps = knownDependencies.getAsSwiftTextualModule();
        for (const auto &clangDep : swiftDeps->bridgingModuleDependencies) {
          findAllImportedClangModules(ctx, clangDep, cache, allClangModules,
                                      knownModules);
        }
      }
    }

    // Find all of the Clang modules this Swift module depends on.
    for (const auto &dep : result) {
      if (dep.second != ModuleDependenciesKind::Clang)
        continue;

      findAllImportedClangModules(ctx, dep.first, cache, allClangModules,
                                  knownModules);
    }

    // Look for overlays for each of the Clang modules. The Swift module
    // directly depends on these.
    for (const auto &clangDep : allClangModules) {
      if (auto found = ctx.getModuleDependencies(
              clangDep, /*onlyClangModule=*/false, cache, ASTDelegate)) {
        // ASTContext::getModuleDependencies returns dependencies for a module with a given name.
        // This Clang module may have the same name as the Swift module we are resolving, so we
        // need to make sure we don't add a dependency from a Swift module to itself.
        if ((found->getKind() == ModuleDependenciesKind::SwiftTextual ||
             found->getKind() == ModuleDependenciesKind::SwiftBinary ||
             found->getKind() == ModuleDependenciesKind::SwiftPlaceholder) &&
            clangDep != module.first) {
          result.insert({clangDep, found->getKind()});
        }
      }
    }
  }
  return std::vector<ModuleDependencyID>(result.begin(), result.end());
}

static void discoverCrosssImportOverlayDependencies(
    CompilerInstance &instance, StringRef mainModuleName,
    ArrayRef<ModuleDependencyID> allDependencies,
    ModuleDependenciesCache &cache, InterfaceSubContextDelegate &ASTDelegate,
    llvm::function_ref<void(ModuleDependencyID)> action) {
  // Modules explicitly imported. Only these can be secondary module.
  llvm::SetVector<Identifier> newOverlays;
  for (auto dep: allDependencies) {
    auto moduleName = dep.first;
    auto dependencies = *cache.findDependencies(moduleName, dep.second);
    // Collect a map from secondary module name to cross-import overlay names.
    auto overlayMap = dependencies.collectCrossImportOverlayNames(
      instance.getASTContext(), moduleName);
    if (overlayMap.empty())
      continue;
    std::for_each(allDependencies.begin(), allDependencies.end(),
                  [&](ModuleDependencyID Id) {
      // check if any explicitly imported modules can serve as a secondary
      // module, and add the overlay names to the dependencies list.
      for (auto overlayName: overlayMap[Id.first]) {
        if (std::find_if(allDependencies.begin(), allDependencies.end(),
            [&](ModuleDependencyID Id) { return Id.first == overlayName.str(); })
                == allDependencies.end()) {
          newOverlays.insert(overlayName);
        }
      }
    });
  }
  // No new cross-import overlays are found, return.
  if (newOverlays.empty())
    return;
  // Construct a dummy main to resolve the newly discovered cross import overlays.
  StringRef dummyMainName = "DummyMainModuleForResolvingCrossImportOverlays";
  auto dummyMainDependencies = ModuleDependencies::forMainSwiftModule({});

  // Update main module's dependencies to include these new overlays.
  auto mainDep = *cache.findDependencies(mainModuleName,
                                         ModuleDependenciesKind::SwiftTextual);
  std::for_each(newOverlays.begin(), newOverlays.end(), [&](Identifier modName) {
    dummyMainDependencies.addModuleDependency(modName.str());
    mainDep.addModuleDependency(modName.str());
  });
  cache.updateDependencies({mainModuleName.str(),
                            ModuleDependenciesKind::SwiftTextual}, mainDep);

  // Record the dummy main module's direct dependencies. The dummy main module
  // only directly depend on these newly discovered overlay modules.
  cache.recordDependencies(dummyMainName, dummyMainDependencies);
  llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
                  std::set<ModuleDependencyID>> allModules;

  // Seed the all module list from the dummpy main module.
  allModules.insert({dummyMainName.str(), dummyMainDependencies.getKind()});

  // Explore the dependencies of every module.
  for (unsigned currentModuleIdx = 0;
       currentModuleIdx < allModules.size();
       ++currentModuleIdx) {
    auto module = allModules[currentModuleIdx];
    auto discoveredModules = resolveDirectDependencies(instance, module,
                                                       cache, ASTDelegate);
    allModules.insert(discoveredModules.begin(), discoveredModules.end());
  }
  // Report any discovered modules to the clients, which include all overlays
  // and their dependencies.
  std::for_each(/* +1 to exclude dummy main*/allModules.begin() + 1,
                allModules.end(), action);
}

/// Write a single JSON field.
namespace {
  template<typename T>
  void writeJSONSingleField(llvm::raw_ostream &out,
                            StringRef fieldName,
                            const T &value,
                            unsigned indentLevel,
                            bool trailingComma);

  /// Write a string value as JSON.
  void writeJSONValue(llvm::raw_ostream &out,
                      StringRef value,
                      unsigned indentLevel) {
    out << "\"";
    out << value;
    out << "\"";
  }

  /// Write a boolean value as JSON.
  void writeJSONValue(llvm::raw_ostream &out,
                      bool value,
                      unsigned indentLevel) {
    out.write_escaped(value ? "true" : "false");
  }

  /// Write a module identifier.
  void writeJSONValue(llvm::raw_ostream &out,
                      const ModuleDependencyID &module,
                      unsigned indentLevel) {
    out << "{\n";
    std::string moduleKind;
    if (module.second == ModuleDependenciesKind::SwiftTextual)
      moduleKind = "swift";
    else if (module.second == ModuleDependenciesKind::SwiftBinary)
      // FIXME: rename to be consistent in the clients (swift-driver)
      moduleKind = "swiftPrebuiltExternal";
    else if (module.second == ModuleDependenciesKind::SwiftPlaceholder)
      moduleKind = "swiftPlaceholder";
    else
      moduleKind = "clang";

    writeJSONSingleField(
        out,
        moduleKind,
        module.first,
        indentLevel + 1,
        /*trailingComma=*/false);

    out.indent(indentLevel * 2);
    out << "}";
  }

  /// Write a JSON array.
  template<typename T>
  void writeJSONValue(llvm::raw_ostream &out,
                      ArrayRef<T> values,
                      unsigned indentLevel) {
    out << "[\n";

    for (const auto &value: values) {

      out.indent((indentLevel + 1) * 2);

      writeJSONValue(out, value, indentLevel + 1);

      if (&value != &values.back()) {
        out << ",";
      }
      out << "\n";
    }

    out.indent(indentLevel * 2);
    out << "]";
  }

  /// Write a JSON array.
  template<typename T>
  void writeJSONValue(llvm::raw_ostream &out,
                      const std::vector<T> &values,
                      unsigned indentLevel) {
    writeJSONValue(out, llvm::makeArrayRef(values), indentLevel);
  }

  /// Write a single JSON field.
  template<typename T>
  void writeJSONSingleField(llvm::raw_ostream &out,
                            StringRef fieldName,
                            const T &value,
                            unsigned indentLevel,
                            bool trailingComma) {
    out.indent(indentLevel * 2);
    writeJSONValue(out, fieldName, indentLevel);
    out << ": ";
    writeJSONValue(out, value, indentLevel);
    if (trailingComma)
      out << ",";
    out << "\n";
  }
}

static void writePrescanJSON(llvm::raw_ostream &out,
                             const ModuleDependencies &mainModuleDependencies) {
  // Write out a JSON containing all main module imports.
  out << "{\n";
  SWIFT_DEFER {
    out << "}\n";
  };

  writeJSONSingleField(out, "imports", mainModuleDependencies.getModuleDependencies(), 0, false);
}

static void writeJSON(llvm::raw_ostream &out,
                      CompilerInstance &instance,
                      ModuleDependenciesCache &cache,
                      InterfaceSubContextDelegate &ASTDelegate,
                      ArrayRef<ModuleDependencyID> allModules) {
  // Write out a JSON description of all of the dependencies.
  out << "{\n";
  SWIFT_DEFER {
    out << "}\n";
  };

  // Name of the main module.
  writeJSONSingleField(out, "mainModuleName", allModules.front().first,
                       /*indentLevel=*/1, /*trailingComma=*/true);

  // Write out all of the modules.
  out << "  \"modules\": [\n";
  SWIFT_DEFER {
    out << "  ]\n";
  };
  for (const auto &module : allModules) {
    auto directDependencies = resolveDirectDependencies(
      instance, ModuleDependencyID(module.first, module.second), cache,
      ASTDelegate);

    // Grab the completed module dependencies.
    auto moduleDeps = *cache.findDependencies(module.first, module.second);

    // The module we are describing.
    out.indent(2 * 2);
    writeJSONValue(out, module, 2);
    out << ",\n";

    out.indent(2 * 2);
    out << "{\n";

    auto swiftPlaceholderDeps = moduleDeps.getAsPlaceholderDependencyModule();
    auto swiftTextualDeps = moduleDeps.getAsSwiftTextualModule();
    auto swiftBinaryDeps = moduleDeps.getAsSwiftBinaryModule();
    auto clangDeps = moduleDeps.getAsClangModule();

    // Module path.
    const char *modulePathSuffix =
        moduleDeps.isSwiftModule() ? ".swiftmodule" : ".pcm";

    std::string modulePath;
    if (swiftPlaceholderDeps)
      modulePath = swiftPlaceholderDeps->compiledModulePath;
    else if (swiftBinaryDeps)
      modulePath = swiftBinaryDeps->compiledModulePath;
    else
      modulePath = module.first + modulePathSuffix;

    writeJSONSingleField(out, "modulePath", modulePath, /*indentLevel=*/3,
                         /*trailingComma=*/true);

    // Source files.
    if (swiftTextualDeps) {
      writeJSONSingleField(out, "sourceFiles", swiftTextualDeps->sourceFiles, 3,
                           /*trailingComma=*/true);
    } else if (clangDeps) {
      writeJSONSingleField(out, "sourceFiles", clangDeps->fileDependencies, 3,
                           /*trailingComma=*/true);
    }

    // Direct dependencies.
    if (swiftTextualDeps || swiftBinaryDeps || clangDeps)
      writeJSONSingleField(out, "directDependencies", directDependencies, 3,
                           /*trailingComma=*/true);

    // Swift and Clang-specific details.
    out.indent(3 * 2);
    out << "\"details\": {\n";
    out.indent(4 * 2);
    if (swiftTextualDeps) {
      out << "\"swift\": {\n";

      /// Swift interface file, if there is one. The main module, for example, will not have
      /// an interface file.
      if (swiftTextualDeps->swiftInterfaceFile) {
        writeJSONSingleField(out, "moduleInterfacePath",
                             *swiftTextualDeps->swiftInterfaceFile, 5,
                             /*trailingComma=*/true);
        writeJSONSingleField(out, "contextHash",
                             swiftTextualDeps->contextHash, 5,
                             /*trailingComma=*/true);
        out.indent(5 * 2);
        out << "\"commandLine\": [\n";
        for (auto &arg :swiftTextualDeps->buildCommandLine) {

          out.indent(6 * 2);
          out << "\"" << arg << "\"";
          if (&arg != &swiftTextualDeps->buildCommandLine.back())
            out << ",";
          out << "\n";
        }
        out.indent(5 * 2);
        out << "],\n";
        out.indent(5 * 2);
        out << "\"compiledModuleCandidates\": [\n";
        for (auto &candidate: swiftTextualDeps->compiledModuleCandidates) {
          out.indent(6 * 2);
          out << "\"" << candidate << "\"";
          if (&candidate != &swiftTextualDeps->compiledModuleCandidates.back())
            out << ",";
          out << "\n";
        }
        out.indent(5 * 2);
        out << "],\n";
      }
      writeJSONSingleField(
          out, "isFramework",
          swiftTextualDeps->isFramework, 5,
          /*trailingComma=*/!swiftTextualDeps->extraPCMArgs.empty() ||
                           swiftTextualDeps->bridgingHeaderFile.hasValue());
      if (!swiftTextualDeps->extraPCMArgs.empty()) {
        out.indent(5 * 2);
        out << "\"extraPcmArgs\": [\n";
        for (auto &arg : swiftTextualDeps->extraPCMArgs) {
          out.indent(6 * 2);
          out << "\"" << arg << "\"";
          if (&arg != &swiftTextualDeps->extraPCMArgs.back())
            out << ",";
          out << "\n";
        }
        out.indent(5 * 2);
        out << (swiftTextualDeps->bridgingHeaderFile.hasValue() ? "],\n" : "]\n");
      }
      /// Bridging header and its source file dependencies, if any.
      if (swiftTextualDeps->bridgingHeaderFile) {
        out.indent(5 * 2);
        out << "\"bridgingHeader\": {\n";
        writeJSONSingleField(out, "path", *swiftTextualDeps->bridgingHeaderFile, 6,
                             /*trailingComma=*/true);
        writeJSONSingleField(out, "sourceFiles", swiftTextualDeps->bridgingSourceFiles,
                             6,
                             /*trailingComma=*/true);
        writeJSONSingleField(out, "moduleDependencies",
                             swiftTextualDeps->bridgingModuleDependencies, 6,
                             /*trailingComma=*/false);
        out.indent(5 * 2);
        out << "}\n";
      }
    } else if (swiftPlaceholderDeps) {
      out << "\"swiftPlaceholder\": {\n";

      // Module doc file
      if (swiftPlaceholderDeps->moduleDocPath != "")
        writeJSONSingleField(out, "moduleDocPath",
                             swiftPlaceholderDeps->moduleDocPath,
                             /*indentLevel=*/5,
                             /*trailingComma=*/true);

      // Module Source Info file
      if (swiftPlaceholderDeps->moduleDocPath != "")
        writeJSONSingleField(out, "moduleSourceInfoPath",
                             swiftPlaceholderDeps->sourceInfoPath,
                             /*indentLevel=*/5,
                             /*trailingComma=*/false);
    } else if (swiftBinaryDeps) {
      out << "\"swiftPrebuiltExternal\": {\n";
      assert(swiftBinaryDeps->compiledModulePath != "" &&
             "Expected .swiftmodule for a Binary Swift Module Dependency.");
      writeJSONSingleField(out, "compiledModulePath",
                           swiftBinaryDeps->compiledModulePath,
                           /*indentLevel=*/5,
                           /*trailingComma=*/true);
      // Module doc file
      if (swiftBinaryDeps->moduleDocPath != "")
        writeJSONSingleField(out, "moduleDocPath",
                             swiftBinaryDeps->moduleDocPath,
                             /*indentLevel=*/5,
                             /*trailingComma=*/true);

      // Module Source Info file
      if (swiftBinaryDeps->moduleDocPath != "")
        writeJSONSingleField(out, "moduleSourceInfoPath",
                             swiftBinaryDeps->sourceInfoPath,
                             /*indentLevel=*/5,
                             /*trailingComma=*/false);
    } else {
      out << "\"clang\": {\n";

      // Module map file.
      writeJSONSingleField(out, "moduleMapPath", clangDeps->moduleMapFile, 5,
                           /*trailingComma=*/true);

      // Context hash.
      writeJSONSingleField(out, "contextHash", clangDeps->contextHash, 5,
                           /*trailingComma=*/true);

      // Command line.
      writeJSONSingleField(out, "commandLine", clangDeps->nonPathCommandLine, 5,
                           /*trailingComma=*/false);
    }

    out.indent(4 * 2);
    out << "}\n";
    out.indent(3 * 2);
    out << "}\n";
    out.indent(2 * 2);
    out << "}";

    if (&module != &allModules.back())
      out << ",";
    out << "\n";
  }
}

static bool diagnoseCycle(CompilerInstance &instance,
                          ModuleDependenciesCache &cache,
                          ModuleDependencyID mainId,
                          InterfaceSubContextDelegate &astDelegate) {
  llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
                  std::set<ModuleDependencyID>> openSet;
  llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
                  std::set<ModuleDependencyID>> closeSet;
  // Start from the main module.
  openSet.insert(mainId);
  while(!openSet.empty()) {
    auto &lastOpen = openSet.back();
    auto beforeSize = openSet.size();
    for (auto dep: resolveDirectDependencies(instance, lastOpen, cache,
                                             astDelegate)) {
      if (closeSet.count(dep))
        continue;
      if (openSet.insert(dep)) {
        break;
      } else {
        // Find a cycle, diagnose.
        auto startIt = std::find(openSet.begin(), openSet.end(), dep);
        assert(startIt != openSet.end());
        llvm::SmallString<64> buffer;
        for (auto it = startIt; it != openSet.end(); ++ it) {
          buffer.append(it->first);
          buffer.append((it->second == ModuleDependenciesKind::SwiftTextual ||
                         it->second == ModuleDependenciesKind::SwiftBinary)?
                        ".swiftmodule": ".pcm");
          buffer.append(" -> ");
        }
        buffer.append(startIt->first);
        buffer.append((startIt->second == ModuleDependenciesKind::SwiftTextual ||
                       startIt->second == ModuleDependenciesKind::SwiftBinary)?
                      ".swiftmodule": ".pcm");
        instance.getASTContext().Diags.diagnose(SourceLoc(),
                                                diag::scanner_find_cycle,
                                                buffer.str());
        return true;
      }
    }
    // No new node added. We can close this node
    if (openSet.size() == beforeSize) {
      closeSet.insert(openSet.back());
      openSet.pop_back();
    } else {
      assert(openSet.size() == beforeSize + 1);
    }
  }
  assert(openSet.empty());
  return false;
}

static bool scanModuleDependencies(CompilerInstance &instance,
                                   StringRef moduleName,
                                   bool isClang,
                                   StringRef outputPath) {
  ASTContext &ctx = instance.getASTContext();
  auto &FEOpts = instance.getInvocation().getFrontendOptions();
  ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
  auto ModuleCachePath = getModuleCachePathFromClang(ctx
    .getClangModuleLoader()->getClangInstance());

  llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
                  std::set<ModuleDependencyID>> allModules;
  // Retrieve the instance's module dependency cache.
  ModuleDependenciesCache *cache = instance.getModuleDependencyCache();
  assert(cache &&
         "Dependency Scanner expected a ModuleDependenciesCache on a compiler instance.");
  InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
                                              ctx.SearchPathOpts, ctx.LangOpts,
                                              ctx.ClangImporterOpts,
                                              LoaderOpts,
                                              /*buildModuleCacheDirIfAbsent*/false,
                                              ModuleCachePath,
                                              FEOpts.PrebuiltModuleCachePath,
                                              FEOpts.SerializeModuleInterfaceDependencyHashes,
                                              FEOpts.shouldTrackSystemDependencies());
  std::error_code EC;
  llvm::raw_fd_ostream out(outputPath, EC, llvm::sys::fs::F_None);
  Optional<ModuleDependencies> rootDeps;
  if (isClang) {
    // Loading the clang module using Clang importer.
    // This action will populate the cache with the main module's dependencies.
    rootDeps = ctx.getModuleDependencies(moduleName, /*IsClang*/true, *cache,
                                         ASTDelegate);
  } else {
    // Loading the swift module's dependencies.
    rootDeps = ctx.getSwiftModuleDependencies(moduleName, *cache, ASTDelegate);
  }
  if (!rootDeps.hasValue()) {
    // We cannot find the clang module, abort.
    return true;
  }
  // Add the main module.
  allModules.insert({moduleName.str(), isClang ? ModuleDependenciesKind::Clang:
                                        ModuleDependenciesKind::SwiftTextual});

  // Output module prescan.
  if (FEOpts.ImportPrescan) {
    writePrescanJSON(out, rootDeps.getValue());
    return false;
  }

  // Explore the dependencies of every module.
  for (unsigned currentModuleIdx = 0;
       currentModuleIdx < allModules.size();
       ++currentModuleIdx) {
    auto module = allModules[currentModuleIdx];
    auto discoveredModules =
        resolveDirectDependencies(instance, module, *cache, ASTDelegate);
    allModules.insert(discoveredModules.begin(), discoveredModules.end());
  }
  // Write out the JSON description.
  writeJSON(out, instance, *cache, ASTDelegate, allModules.getArrayRef());
  return false;
}

bool swift::scanClangDependencies(CompilerInstance &instance) {
  return scanModuleDependencies(instance,
                                instance.getMainModule()->getNameStr(),
                                /*isClang*/true,
                                instance.getInvocation().getFrontendOptions()
                                  .InputsAndOutputs.getSingleOutputFilename());
}

bool swift::batchScanModuleDependencies(CompilerInstance &instance,
                                        llvm::StringRef batchInputFile) {
  const CompilerInvocation &invok = instance.getInvocation();

  (void)instance.getMainModule();
  llvm::BumpPtrAllocator alloc;
  llvm::StringSaver saver(alloc);
  auto results = parseBatchScanInputFile(instance.getASTContext(),
                                         batchInputFile, saver);
  if (!results.hasValue())
    return true;
  auto &diags = instance.getDiags();
  ForwardingDiagnosticConsumer FDC(diags);
  // Keep track of all compiler instances we have created.
  llvm::StringMap<std::unique_ptr<CompilerInstance>> subInstanceMap;
  for (auto &entry: *results) {
    CompilerInstance *pInstance = nullptr;
    if (entry.arguments.empty()) {
      // Use the compiler's instance if no arguments are specified.
      pInstance = &instance;
    } else if (subInstanceMap.count(entry.arguments)) {
      // Use the previously created instance if we've seen the arguments before.
      pInstance = subInstanceMap[entry.arguments].get();
    } else {
      // Create a new instance by the arguments and save it in the map.
      pInstance = subInstanceMap.insert({entry.arguments,
        std::make_unique<CompilerInstance>()}).first->getValue().get();
      SmallVector<const char*, 4> args;
      llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args);
      CompilerInvocation subInvok = invok;
      pInstance->addDiagnosticConsumer(&FDC);
      if (subInvok.parseArgs(args, diags)) {
        instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid,
                                     entry.arguments);
        return true;
      }
      if (pInstance->setup(subInvok)) {
        instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid,
                                     entry.arguments);
        return true;
      }
    }
    assert(pInstance);
    // Scan using the chosen compiler instance.
    if (scanModuleDependencies(*pInstance, entry.moduleName, !entry.isSwift,
                               entry.outputPath)) {
      return true;
    }
  }
  return false;
}

bool swift::scanDependencies(CompilerInstance &instance) {
  ASTContext &Context = instance.getASTContext();
  ModuleDecl *mainModule = instance.getMainModule();
  const CompilerInvocation &invocation = instance.getInvocation();
  const FrontendOptions &opts = invocation.getFrontendOptions();

  std::string path = opts.InputsAndOutputs.getSingleOutputFilename();
  std::error_code EC;
  llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);

  if (out.has_error() || EC) {
    Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path,
                           EC.message());
    out.clear_error();
    return true;
  }

  // Main module file name.
  auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
  llvm::SmallString<32> mainModulePath = mainModule->getName().str();
  llvm::sys::path::replace_extension(mainModulePath, newExt);

  std::string apinotesVer = (llvm::Twine("-fapinotes-swift-version=")
    + instance.getASTContext().LangOpts.EffectiveLanguageVersion
      .asAPINotesVersionString()).str();
  // Compute the dependencies of the main module.
  auto mainDependencies =
    ModuleDependencies::forMainSwiftModule({
      // ExtraPCMArgs
      "-Xcc", "-target", "-Xcc", instance.getASTContext().LangOpts.Target.str(),
      "-Xcc", apinotesVer
    });

  // Compute Implicit dependencies of the main module
  {
    llvm::StringSet<> alreadyAddedModules;
    for (auto fileUnit : mainModule->getFiles()) {
      auto sf = dyn_cast<SourceFile>(fileUnit);
      if (!sf)
        continue;

      mainDependencies.addModuleDependencies(*sf, alreadyAddedModules);
    }

    const auto &importInfo = mainModule->getImplicitImportInfo();

    // Swift standard library.
    switch (importInfo.StdlibKind) {
    case ImplicitStdlibKind::None:
    case ImplicitStdlibKind::Builtin:
      break;

    case ImplicitStdlibKind::Stdlib:
      mainDependencies.addModuleDependency("Swift", &alreadyAddedModules);
      break;
    }

    // Add any implicit module names.
    for (const auto &import : importInfo.AdditionalUnloadedImports) {
      mainDependencies.addModuleDependency(import.module.getModulePath(), &alreadyAddedModules);
    }

    // Already-loaded, implicitly imported module names.
    for (const auto &import : importInfo.AdditionalImports) {
      mainDependencies.addModuleDependency(import.module.importedModule->getNameStr(), &alreadyAddedModules);
    }

    // Add the bridging header.
    if (!importInfo.BridgingHeaderPath.empty()) {
      mainDependencies.addBridgingHeader(importInfo.BridgingHeaderPath);
    }

    // If we are to import the underlying Clang module of the same name,
    // add a dependency with the same name to trigger the search.
    if (importInfo.ShouldImportUnderlyingModule) {
      mainDependencies.addModuleDependency(mainModule->getName().str(),
                                           &alreadyAddedModules);
    }
  }

  // If import-prescan is specified, discover and serialize main module dependencies only and exit.
  if (opts.ImportPrescan) {
    writePrescanJSON(out, mainDependencies);
    // This process succeeds regardless of whether any errors occurred.
    // FIXME: We shouldn't need this, but it's masking bugs in our scanning
    // logic where we don't create a fresh context when scanning Swift interfaces
    // that includes their own command-line flags.
    Context.Diags.resetHadAnyError();
    return false;
  }

  // Add the main module.
  StringRef mainModuleName = mainModule->getNameStr();
  llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
                  std::set<ModuleDependencyID>> allModules;
  
  allModules.insert({mainModuleName.str(), mainDependencies.getKind()});

  // Retrieve the instance's module dependency cache.
  ModuleDependenciesCache *cache = instance.getModuleDependencyCache();
  assert(cache &&
         "Dependency Scanner expected a ModuleDependenciesCache on a compiler instance.");
  cache->recordDependencies(mainModuleName, std::move(mainDependencies));

  auto &ctx = instance.getASTContext();
  auto ModuleCachePath = getModuleCachePathFromClang(ctx
    .getClangModuleLoader()->getClangInstance());
  auto &FEOpts = instance.getInvocation().getFrontendOptions();
  ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
  InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
                                              ctx.SearchPathOpts, ctx.LangOpts,
                                              ctx.ClangImporterOpts,
                                              LoaderOpts,
                                              /*buildModuleCacheDirIfAbsent*/false,
                                              ModuleCachePath,
                                              FEOpts.PrebuiltModuleCachePath,
                                              FEOpts.SerializeModuleInterfaceDependencyHashes,
                                              FEOpts.shouldTrackSystemDependencies());

  // Explore the dependencies of every module.
  for (unsigned currentModuleIdx = 0;
       currentModuleIdx < allModules.size();
       ++currentModuleIdx) {
    auto module = allModules[currentModuleIdx];
    auto discoveredModules =
        resolveDirectDependencies(instance, module, *cache, ASTDelegate);
    allModules.insert(discoveredModules.begin(), discoveredModules.end());
  }

  // We have all explicit imports now, resolve cross import overlays.
  discoverCrosssImportOverlayDependencies(instance, mainModuleName,
      /*All transitive dependencies*/allModules.getArrayRef().slice(1), *cache,
      ASTDelegate, [&](ModuleDependencyID id) {
    allModules.insert(id);
  });

  // Dignose cycle in dependency graph.
  if (diagnoseCycle(instance, *cache, /*MainModule*/allModules.front(), ASTDelegate))
    return true;

  // Write out the JSON description.
  writeJSON(out, instance, *cache, ASTDelegate, allModules.getArrayRef());

  // Update the dependency tracker.
  if (auto depTracker = instance.getDependencyTracker()) {
    for (auto module : allModules) {
      auto deps = cache->findDependencies(module.first, module.second);
      if (!deps)
        continue;

      if (auto swiftDeps = deps->getAsSwiftTextualModule()) {
        if (auto swiftInterfaceFile = swiftDeps->swiftInterfaceFile)
          depTracker->addDependency(*swiftInterfaceFile, /*IsSystem=*/false);
        for (const auto &sourceFile : swiftDeps->sourceFiles)
          depTracker->addDependency(sourceFile, /*IsSystem=*/false);
        for (const auto &bridgingSourceFile : swiftDeps->bridgingSourceFiles)
          depTracker->addDependency(bridgingSourceFile, /*IsSystem=*/false);
      } else if (auto clangDeps = deps->getAsClangModule()) {
        if (!clangDeps->moduleMapFile.empty())
          depTracker->addDependency(clangDeps->moduleMapFile, /*IsSystem=*/false);
        for (const auto &sourceFile : clangDeps->fileDependencies)
          depTracker->addDependency(sourceFile, /*IsSystem=*/false);
      }
    }
  }

  // This process succeeds regardless of whether any errors occurred.
  // FIXME: We shouldn't need this, but it's masking bugs in our scanning
  // logic where we don't create a fresh context when scanning Swift interfaces
  // that includes their own command-line flags.
  Context.Diags.resetHadAnyError();
  return false;
}
