Files
swift-mirror/lib/AST/ModuleLoader.cpp
2020-02-18 11:06:12 -08:00

132 lines
4.7 KiB
C++

//===--- ModuleLoader.cpp - Swift Language Module Implementation ----------===//
//
// 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 the ModuleLoader class and/or any helpers.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticsCommon.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/Basic/FileTypes.h"
#include "swift/Basic/Platform.h"
#include "clang/Frontend/Utils.h"
#include "swift/ClangImporter/ClangImporter.h"
namespace llvm {
class FileCollector;
}
namespace swift {
DependencyTracker::DependencyTracker(
bool TrackSystemDeps, std::shared_ptr<llvm::FileCollector> FileCollector)
// NB: The ClangImporter believes it's responsible for the construction of
// this instance, and it static_cast<>s the instance pointer to its own
// subclass based on that belief. If you change this to be some other
// instance, you will need to change ClangImporter's code to handle the
// difference.
: clangCollector(ClangImporter::createDependencyCollector(TrackSystemDeps,
FileCollector)) {}
void
DependencyTracker::addDependency(StringRef File, bool IsSystem) {
// DependencyTracker exposes an interface that (intentionally) does not talk
// about clang at all, nor about missing deps. It does expose an IsSystem
// dimension, which we accept and pass along to the clang DependencyCollector.
clangCollector->maybeAddDependency(File, /*FromModule=*/false,
IsSystem, /*IsModuleFile=*/false,
/*IsMissing=*/false);
}
ArrayRef<std::string>
DependencyTracker::getDependencies() const {
return clangCollector->getDependencies();
}
std::shared_ptr<clang::DependencyCollector>
DependencyTracker::getClangCollector() {
return clangCollector;
}
static bool findOverlayFilesInDirectory(SourceLoc diagLoc, StringRef path,
ModuleDecl *module,
DependencyTracker * const tracker) {
using namespace llvm::sys;
using namespace file_types;
ASTContext &ctx = module->getASTContext();
auto fs = ctx.SourceMgr.getFileSystem();
std::error_code error;
for (auto dir = fs->dir_begin(path, error);
!error && dir != llvm::vfs::directory_iterator();
dir.increment(error)) {
StringRef file = dir->path();
if (lookupTypeForExtension(path::extension(file)) != TY_SwiftOverlayFile)
continue;
module->addCrossImportOverlayFile(file);
// FIXME: Better to add it only if we load it.
if (tracker)
tracker->addDependency(file, module->isSystemModule());
}
if (error && error != std::errc::no_such_file_or_directory) {
ctx.Diags.diagnose(diagLoc, diag::cannot_list_swiftcrossimport_dir,
module->getName(), error.message(), path);
}
return !error;
}
void ModuleLoader::findOverlayFiles(SourceLoc diagLoc, ModuleDecl *module,
FileUnit *file) {
using namespace llvm::sys;
using namespace file_types;
auto &langOpts = module->getASTContext().LangOpts;
SmallString<64> dirPath{file->getModuleDefiningPath()};
if (dirPath.empty())
return;
path::remove_filename(dirPath);
// <parent-dir>/<module-name>.swiftcrossimport
path::append(dirPath, file->getExportedModuleName());
path::replace_extension(dirPath, getExtension(TY_SwiftCrossImportDir));
if (!findOverlayFilesInDirectory(diagLoc, dirPath, module, dependencyTracker))
// If we diagnosed an error, or we didn't find the directory at all, don't
// bother trying the target-specific directories.
return;
// <parent-dir>/<module-name>.swiftcrossimport/<target-module-triple>
auto moduleTriple = getTargetSpecificModuleTriple(langOpts.Target);
path::append(dirPath, moduleTriple.str());
findOverlayFilesInDirectory(diagLoc, dirPath, module, dependencyTracker);
if (!langOpts.TargetVariant)
return;
path::remove_filename(dirPath);
// <parent-dir>/<module-name>.swiftcrossimport/<targetvariant-module-triple>
auto moduleVariantTriple =
getTargetSpecificModuleTriple(*langOpts.TargetVariant);
path::append(dirPath, moduleVariantTriple.str());
findOverlayFilesInDirectory(diagLoc, dirPath, module, dependencyTracker);
}
} // namespace swift