//===--- ModuleDependencyScanner.h - Import Swift modules --------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 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 "swift/AST/ASTContext.h" #include "swift/Frontend/ModuleInterfaceLoader.h" #include "swift/Serialization/SerializedModuleLoader.h" namespace swift { /// A module "loader" that looks for .swiftinterface and .swiftmodule files /// for the purpose of determining dependencies, but does not attempt to /// load the module files. class ModuleDependencyScanner : public SerializedModuleLoaderBase { public: enum ScannerKind { MDS_plain, MDS_placeholder }; private: /// The kind of scanner this is (LLVM-style RTTI) const ScannerKind kind; /// The module we're scanning dependencies of. Identifier moduleName; /// Scan the given interface file to determine dependencies. llvm::ErrorOr scanInterfaceFile( Twine moduleInterfacePath, bool isFramework); InterfaceSubContextDelegate &astDelegate; public: Optional dependencies; ModuleDependencyScanner( ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName, InterfaceSubContextDelegate &astDelegate, ScannerKind kind = MDS_plain) : SerializedModuleLoaderBase(ctx, nullptr, LoadMode, /*IgnoreSwiftSourceInfoFile=*/true), kind(kind), moduleName(moduleName), astDelegate(astDelegate) {} std::error_code findModuleFilesInDirectory( ImportPath::Element ModuleID, const SerializedModuleBaseName &BaseName, SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, std::unique_ptr *ModuleSourceInfoBuffer, bool skipBuildingInterface, bool IsFramework) override; virtual void collectVisibleTopLevelModuleNames( SmallVectorImpl &names) const override { llvm_unreachable("Not used"); } ScannerKind getKind() const { return kind; } static bool classof(const ModuleDependencyScanner *MDS) { return MDS->getKind() == MDS_plain; } }; /// A ModuleLoader that loads placeholder dependency module stubs specified in /// -placeholder-dependency-module-map-file /// This loader is used only in dependency scanning to inform the scanner that a /// set of modules constitute placeholder dependencies that are not visible to the /// scanner but will nevertheless be provided by the scanner's clients. /// This "loader" will not attempt to load any module files. class PlaceholderSwiftModuleScanner : public ModuleDependencyScanner { /// Scan the given placeholder module map void parsePlaceholderModuleMap(StringRef fileName) { ExplicitModuleMapParser parser(Allocator); auto result = parser.parseSwiftExplicitModuleMap(fileName, PlaceholderDependencyModuleMap); if (result == std::errc::invalid_argument) { Ctx.Diags.diagnose(SourceLoc(), diag::placeholder_dependency_module_map_corrupted, fileName); } else if (result == std::errc::no_such_file_or_directory) { Ctx.Diags.diagnose(SourceLoc(), diag::placeholder_dependency_module_map_missing, fileName); } } llvm::StringMap PlaceholderDependencyModuleMap; llvm::BumpPtrAllocator Allocator; public: PlaceholderSwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName, StringRef PlaceholderDependencyModuleMap, InterfaceSubContextDelegate &astDelegate) : ModuleDependencyScanner(ctx, LoadMode, moduleName, astDelegate, MDS_placeholder) { // FIXME: Find a better place for this map to live, to avoid // doing the parsing on every module. if (!PlaceholderDependencyModuleMap.empty()) { parsePlaceholderModuleMap(PlaceholderDependencyModuleMap); } } std::error_code findModuleFilesInDirectory( ImportPath::Element ModuleID, const SerializedModuleBaseName &BaseName, SmallVectorImpl *ModuleInterfacePath, std::unique_ptr *ModuleBuffer, std::unique_ptr *ModuleDocBuffer, std::unique_ptr *ModuleSourceInfoBuffer, bool skipBuildingInterface, bool IsFramework) override; static bool classof(const ModuleDependencyScanner *MDS) { return MDS->getKind() == MDS_placeholder; } }; }