Files
swift-mirror/include/swift/Serialization/ScanningLoaders.h
Steven Wu d4c90d6eeb [DependencyScanning] Handle testable dependencies correctly
Teach scanner to pick and choose binary modules correctly based on if it
is testable import or not. Some situations that scanner need to be
careful when testable is involved:

* When it is a regular import, it should not import binary modules that
  are built with -enable-testing, it should prefer interfaces if that is
  available.
* When testable import, it should only load binary module and it should
  make sure the internal imports from binary modules are actually
  required for testable import to work.

If a testable import only find a regular binary module, dependency
scanner currently will just preceed with such module and leave the
diagnostics to swift-frontend, because the alternative (failed to find
module) can be confusing to users.

rdar://125914165
2024-04-05 07:52:16 -07:00

124 lines
4.9 KiB
C++

//===--- ScanningLoaders.h - Swift module scanning --------------*- C++ -*-===//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SCANNINGLOADERS_H
#define SWIFT_SCANNINGLOADERS_H
#include "swift/AST/ASTContext.h"
#include "swift/AST/ModuleDependencies.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 SwiftModuleScanner : 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<ModuleDependencyInfo>
scanInterfaceFile(Twine moduleInterfacePath, bool isFramework,
bool isTestableImport);
InterfaceSubContextDelegate &astDelegate;
/// Location where pre-built moduels are to be built into.
std::string moduleOutputPath;
public:
std::optional<ModuleDependencyInfo> dependencies;
SwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode,
Identifier moduleName,
InterfaceSubContextDelegate &astDelegate,
StringRef moduleOutputPath, ScannerKind kind = MDS_plain)
: SerializedModuleLoaderBase(ctx, nullptr, LoadMode,
/*IgnoreSwiftSourceInfoFile=*/true),
kind(kind), moduleName(moduleName), astDelegate(astDelegate),
moduleOutputPath(moduleOutputPath) {}
std::error_code findModuleFilesInDirectory(
ImportPath::Element ModuleID, const SerializedModuleBaseName &BaseName,
SmallVectorImpl<char> *ModuleInterfacePath,
SmallVectorImpl<char> *ModuleInterfaceSourcePath,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
bool SkipBuildingInterface, bool IsFramework,
bool IsTestableDependencyLookup) override;
virtual void collectVisibleTopLevelModuleNames(
SmallVectorImpl<Identifier> &names) const override {
llvm_unreachable("Not used");
}
ScannerKind getKind() const { return kind; }
static bool classof(const SwiftModuleScanner *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 SwiftModuleScanner {
/// Scan the given placeholder module map
void parsePlaceholderModuleMap(StringRef fileName);
llvm::StringMap<ExplicitSwiftModuleInputInfo> PlaceholderDependencyModuleMap;
llvm::BumpPtrAllocator Allocator;
public:
PlaceholderSwiftModuleScanner(ASTContext &ctx, ModuleLoadingMode LoadMode,
Identifier moduleName,
StringRef PlaceholderDependencyModuleMap,
InterfaceSubContextDelegate &astDelegate,
StringRef moduleOutputPath)
: SwiftModuleScanner(ctx, LoadMode, moduleName, astDelegate,
moduleOutputPath, 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);
}
}
virtual bool
findModule(ImportPath::Element moduleID,
SmallVectorImpl<char> *moduleInterfacePath,
SmallVectorImpl<char> *moduleInterfaceSourcePath,
std::unique_ptr<llvm::MemoryBuffer> *moduleBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
bool skipBuildingInterface, bool isTestableDependencyLookup,
bool &isFramework, bool &isSystemModule) override;
static bool classof(const SwiftModuleScanner *MDS) {
return MDS->getKind() == MDS_placeholder;
}
};
} // namespace swift
#endif // SWIFT_SCANNINGLOADERS_H