mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
118 lines
3.9 KiB
C++
118 lines
3.9 KiB
C++
//===--- ImportedModules.cpp -- generates the list of imported modules ----===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ImportedModules.h"
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Decl.h"
|
|
#include "swift/AST/DiagnosticEngine.h"
|
|
#include "swift/AST/DiagnosticsFrontend.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/Basic/STLExtras.h"
|
|
#include "swift/ClangImporter/ClangImporter.h"
|
|
#include "swift/Frontend/FrontendOptions.h"
|
|
#include "clang/Basic/Module.h"
|
|
#include "llvm/ADT/SetVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
|
|
using namespace swift;
|
|
|
|
static StringRef getTopLevelName(const clang::Module *module) {
|
|
return module->getTopLevelModule()->Name;
|
|
}
|
|
|
|
static void findAllClangImports(const clang::Module *module,
|
|
llvm::SetVector<StringRef> &modules) {
|
|
for (auto imported : module->Imports) {
|
|
modules.insert(getTopLevelName(imported));
|
|
}
|
|
|
|
for (auto sub : module->submodules()) {
|
|
findAllClangImports(sub, modules);
|
|
}
|
|
}
|
|
|
|
bool swift::emitImportedModules(ModuleDecl *mainModule,
|
|
const FrontendOptions &opts) {
|
|
auto &Context = mainModule->getASTContext();
|
|
std::string path = opts.InputsAndOutputs.getSingleOutputFilename();
|
|
std::error_code EC;
|
|
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);
|
|
|
|
if (out.has_error() || EC) {
|
|
Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path,
|
|
EC.message());
|
|
out.clear_error();
|
|
return true;
|
|
}
|
|
|
|
llvm::SetVector<StringRef> Modules;
|
|
|
|
// Find the imports in the main Swift code.
|
|
llvm::SmallVector<Decl *, 32> Decls;
|
|
mainModule->getDisplayDecls(Decls);
|
|
for (auto D : Decls) {
|
|
auto ID = dyn_cast<ImportDecl>(D);
|
|
if (!ID)
|
|
continue;
|
|
|
|
auto modulePath = ID->getModulePath();
|
|
// only the top-level name is needed (i.e. A in A.B.C)
|
|
Modules.insert(modulePath[0].Item.str());
|
|
}
|
|
|
|
// And now look in the C code we're possibly using.
|
|
auto clangImporter =
|
|
static_cast<ClangImporter *>(Context.getClangModuleLoader());
|
|
|
|
StringRef implicitHeaderPath = opts.ImplicitObjCHeaderPath;
|
|
if (!implicitHeaderPath.empty()) {
|
|
if (!clangImporter->importBridgingHeader(implicitHeaderPath, mainModule)) {
|
|
SmallVector<ModuleDecl::ImportedModule, 16> imported;
|
|
clangImporter->getImportedHeaderModule()->getImportedModules(
|
|
imported, {ModuleDecl::ImportFilterKind::Public,
|
|
ModuleDecl::ImportFilterKind::Private,
|
|
ModuleDecl::ImportFilterKind::ImplementationOnly,
|
|
ModuleDecl::ImportFilterKind::SPIAccessControl});
|
|
|
|
for (auto IM : imported) {
|
|
if (auto clangModule = IM.importedModule->findUnderlyingClangModule())
|
|
Modules.insert(getTopLevelName(clangModule));
|
|
else
|
|
assert(IM.importedModule->isStdlibModule() &&
|
|
"unexpected non-stdlib swift module");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (opts.ImportUnderlyingModule) {
|
|
auto underlyingModule = clangImporter->loadModule(SourceLoc(),
|
|
ImportPath::Module::Builder(mainModule->getName()).get());
|
|
if (!underlyingModule) {
|
|
Context.Diags.diagnose(SourceLoc(),
|
|
diag::error_underlying_module_not_found,
|
|
mainModule->getName());
|
|
return true;
|
|
}
|
|
auto clangModule = underlyingModule->findUnderlyingClangModule();
|
|
|
|
findAllClangImports(clangModule, Modules);
|
|
}
|
|
|
|
for (auto name : Modules) {
|
|
out << name << "\n";
|
|
}
|
|
|
|
return false;
|
|
}
|