mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Factor out Explicit Module Map parsing into a standalone utility.
This commit is contained in:
@@ -1512,106 +1512,89 @@ 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(Ctx);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
StringRef ExplicitModuleMapParser::getScalaNodeText(llvm::yaml::Node *N) {
|
||||
SmallString<32> Buffer;
|
||||
return Saver.save(cast<llvm::yaml::ScalarNode>(N)->getValue(Buffer));
|
||||
}
|
||||
|
||||
bool ExplicitModuleMapParser::parseSingleModuleEntry(
|
||||
llvm::yaml::Node &node, llvm::StringMap<ExplicitModuleInfo> &moduleMap) {
|
||||
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;
|
||||
moduleMap[moduleName] = std::move(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code ExplicitModuleMapParser::parseSwiftExplicitModuleMap(
|
||||
const StringRef fileName, llvm::StringMap<ExplicitModuleInfo> &moduleMap) {
|
||||
using namespace llvm::yaml;
|
||||
// Load the input file.
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
|
||||
llvm::MemoryBuffer::getFile(fileName);
|
||||
if (!fileBufOrErr) {
|
||||
return std::make_error_code(std::errc::no_such_file_or_directory);
|
||||
}
|
||||
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, moduleMap)) {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
|
||||
fileName);
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
}
|
||||
return std::error_code{}; // success
|
||||
}
|
||||
|
||||
ExplicitSwiftModuleLoader::ExplicitSwiftModuleLoader(
|
||||
ASTContext &ctx,
|
||||
DependencyTracker *tracker,
|
||||
|
||||
Reference in New Issue
Block a user