//===--- ModuleDependencies.h - Module Dependencies -------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// // // This file implements data structures for capturing module dependencies. // //===----------------------------------------------------------------------===// #include "swift/AST/ModuleDependencies.h" #include "swift/AST/Decl.h" #include "swift/AST/SourceFile.h" using namespace swift; ModuleDependenciesStorageBase::~ModuleDependenciesStorageBase() { } bool ModuleDependencies::isSwiftModule() const { return isa(storage.get()); } /// Retrieve the dependencies for a Swift module. const SwiftModuleDependenciesStorage * ModuleDependencies::getAsSwiftModule() const { return dyn_cast(storage.get()); } /// Retrieve the dependencies for a Clang module. const ClangModuleDependenciesStorage * ModuleDependencies::getAsClangModule() const { return dyn_cast(storage.get()); } void ModuleDependencies::addModuleDependency( StringRef module, llvm::StringSet<> &alreadyAddedModules) { if (alreadyAddedModules.insert(module).second) storage->moduleDependencies.push_back(module); } void ModuleDependencies::addModuleDependencies( const SourceFile &sf, llvm::StringSet<> &alreadyAddedModules) { // Add all of the module dependencies. SmallVector decls; sf.getTopLevelDecls(decls); for (auto decl : decls) { auto importDecl = dyn_cast(decl); if (!importDecl) continue; addModuleDependency(importDecl->getModulePath().front().Item.str(), alreadyAddedModules); } auto fileName = sf.getFilename(); if (fileName.empty()) return; // If the storage is for an interface file, the only source file we // should see is that interface file. auto swiftStorage = cast(storage.get()); if (swiftStorage->swiftInterfaceFile) { assert(fileName == *swiftStorage->swiftInterfaceFile); return; } // Otherwise, record the source file. swiftStorage->sourceFiles.push_back(fileName); } void ModuleDependencies::addBridgingHeader(StringRef bridgingHeader) { auto swiftStorage = cast(storage.get()); assert(!swiftStorage->bridgingHeaderFile); swiftStorage->bridgingHeaderFile = bridgingHeader; } llvm::StringMap & ModuleDependenciesCache::getDependenciesMap(ModuleDependenciesKind kind) { switch (kind) { case ModuleDependenciesKind::Swift: return SwiftModuleDependencies; case ModuleDependenciesKind::Clang: return ClangModuleDependencies; } } const llvm::StringMap & ModuleDependenciesCache::getDependenciesMap(ModuleDependenciesKind kind) const { switch (kind) { case ModuleDependenciesKind::Swift: return SwiftModuleDependencies; case ModuleDependenciesKind::Clang: return ClangModuleDependencies; } } bool ModuleDependenciesCache::hasDependencies( StringRef moduleName, Optional kind) const { if (!kind) { return hasDependencies(moduleName, ModuleDependenciesKind::Swift) || hasDependencies(moduleName, ModuleDependenciesKind::Clang); } const auto &map = getDependenciesMap(*kind); return map.count(moduleName) > 0; } Optional ModuleDependenciesCache::findDependencies( StringRef moduleName, Optional kind) const { if (!kind) { if (auto swiftDep = findDependencies( moduleName, ModuleDependenciesKind::Swift)) return swiftDep; return findDependencies(moduleName, ModuleDependenciesKind::Clang); } const auto &map = getDependenciesMap(*kind); auto known = map.find(moduleName); if (known != map.end()) return known->second; return None; } void ModuleDependenciesCache::recordDependencies( StringRef moduleName, ModuleDependencies dependencies, ModuleDependenciesKind kind) { auto &map = getDependenciesMap(kind); assert(map.count(moduleName) == 0 && "Already added to map"); map.insert({moduleName, std::move(dependencies)}); AllModules.push_back({moduleName, kind}); }