Merge pull request #33032 from artemcm/ExplicitPackageBuilds

[Dependency Scanner] Add a scanner for explicit placeholder module dependencies
This commit is contained in:
Artem Chikin
2020-07-28 14:36:26 -07:00
committed by GitHub
15 changed files with 540 additions and 152 deletions

View File

@@ -1512,103 +1512,21 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN
}
struct ExplicitSwiftModuleLoader::Implementation {
// Information about explicitly specified Swift module files.
struct ExplicitModuleInfo {
// Path of the .swiftmodule file.
StringRef modulePath;
// Path of the .swiftmoduledoc file.
StringRef moduleDocPath;
// Path of the .swiftsourceinfo file.
StringRef moduleSourceInfoPath;
// Opened buffer for the .swiftmodule file.
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
};
ASTContext &Ctx;
llvm::BumpPtrAllocator Allocator;
llvm::StringSaver Saver;
llvm::StringMap<ExplicitModuleInfo> ExplicitModuleMap;
Implementation(ASTContext &Ctx): Ctx(Ctx), Saver(Allocator) {}
Implementation(ASTContext &Ctx) : Ctx(Ctx) {}
StringRef getScalaNodeText(llvm::yaml::Node *N) {
SmallString<32> Buffer;
return Saver.save(cast<llvm::yaml::ScalarNode>(N)->getValue(Buffer));
}
bool parseSingleModuleEntry(llvm::yaml::Node &node) {
using namespace llvm::yaml;
auto *mapNode = dyn_cast<MappingNode>(&node);
if (!mapNode)
return true;
StringRef moduleName;
ExplicitModuleInfo result;
for (auto &entry: *mapNode) {
auto key = getScalaNodeText(entry.getKey());
auto val = getScalaNodeText(entry.getValue());
if (key == "moduleName") {
moduleName = val;
} else if (key == "modulePath") {
result.modulePath = val;
} else if (key == "docPath") {
result.moduleDocPath = val;
} else if (key == "sourceInfoPath") {
result.moduleSourceInfoPath = val;
} else {
// Being forgiving for future fields.
continue;
}
}
if (moduleName.empty())
return true;
ExplicitModuleMap[moduleName] = std::move(result);
return false;
}
// [
// {
// "moduleName": "A",
// "modulePath": "A.swiftmodule",
// "docPath": "A.swiftdoc",
// "sourceInfoPath": "A.swiftsourceinfo"
// },
// {
// "moduleName": "B",
// "modulePath": "B.swiftmodule",
// "docPath": "B.swiftdoc",
// "sourceInfoPath": "B.swiftsourceinfo"
// }
// ]
void parseSwiftExplicitModuleMap(StringRef fileName) {
using namespace llvm::yaml;
// Load the input file.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
llvm::MemoryBuffer::getFile(fileName);
if (!fileBufOrErr) {
ExplicitModuleMapParser parser(Allocator);
auto result =
parser.parseSwiftExplicitModuleMap(fileName, ExplicitModuleMap);
if (result == std::errc::invalid_argument)
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
fileName);
else if (result == std::errc::no_such_file_or_directory)
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_missing,
fileName);
return;
}
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.
llvm::SourceMgr SM;
Stream Stream(llvm::MemoryBufferRef(Buffer, fileName), SM);
for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) {
assert(DI != Stream.end() && "Failed to read a document");
if (auto *MN = dyn_cast_or_null<SequenceNode>(DI->getRoot())) {
for (auto &entry: *MN) {
if (parseSingleModuleEntry(entry)) {
Ctx.Diags.diagnose(SourceLoc(),
diag::explicit_swift_module_map_corrupted,
fileName);
return;
}
}
} else {
Ctx.Diags.diagnose(SourceLoc(),
diag::explicit_swift_module_map_corrupted,
fileName);
return;
}
}
}
};