//===--- SourceLoader.cpp - Import .swift files as 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 // //===----------------------------------------------------------------------===// /// /// \file /// A simple module loader that loads .swift source files. /// //===----------------------------------------------------------------------===// #include "swift/Sema/SourceLoader.h" #include "swift/Subsystems.h" #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/FileUnit.h" #include "swift/AST/Module.h" #include "swift/Parse/PersistentParserState.h" #include "swift/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" #include using namespace swift; // FIXME: Basically the same as SerializedModuleLoader. using FileOrError = llvm::ErrorOr>; static FileOrError findModule(ASTContext &ctx, StringRef moduleID, SourceLoc importLoc) { llvm::SmallString<128> inputFilename; for (auto Path : ctx.SearchPathOpts.ImportSearchPaths) { inputFilename = Path; llvm::sys::path::append(inputFilename, moduleID); inputFilename.append(".swift"); llvm::ErrorOr> FileBufOrErr = ctx.SourceMgr.getFileSystem()->getBufferForFile(inputFilename.str()); // Return if we loaded a file if (FileBufOrErr) return FileBufOrErr; // Or if we get any error other than the file not existing auto err = FileBufOrErr.getError(); if (err != std::errc::no_such_file_or_directory) return FileBufOrErr; } return make_error_code(std::errc::no_such_file_or_directory); } void SourceLoader::collectVisibleTopLevelModuleNames( SmallVectorImpl &names) const { // TODO: Implement? } bool SourceLoader::canImportModule(std::pair ID) { // Search the memory buffers to see if we can find this file on disk. FileOrError inputFileOrError = findModule(Ctx, ID.first.str(), ID.second); if (!inputFileOrError) { auto err = inputFileOrError.getError(); if (err != std::errc::no_such_file_or_directory) { Ctx.Diags.diagnose(ID.second, diag::sema_opening_import, ID.first, err.message()); } return false; } return true; } ModuleDecl *SourceLoader::loadModule(SourceLoc importLoc, ArrayRef> path) { // FIXME: Swift submodules? if (path.size() > 1) return nullptr; auto moduleID = path[0]; FileOrError inputFileOrError = findModule(Ctx, moduleID.first.str(), moduleID.second); if (!inputFileOrError) { auto err = inputFileOrError.getError(); if (err != std::errc::no_such_file_or_directory) { Ctx.Diags.diagnose(moduleID.second, diag::sema_opening_import, moduleID.first, err.message()); } return nullptr; } std::unique_ptr inputFile = std::move(inputFileOrError.get()); if (dependencyTracker) dependencyTracker->addDependency(inputFile->getBufferIdentifier(), /*isSystem=*/false); // Turn off debugging while parsing other modules. llvm::SaveAndRestore turnOffDebug(Ctx.LangOpts.DebugConstraintSolver, false); unsigned bufferID; if (auto BufID = Ctx.SourceMgr.getIDForBufferIdentifier(inputFile->getBufferIdentifier())) bufferID = BufID.getValue(); else bufferID = Ctx.SourceMgr.addNewSourceBuffer(std::move(inputFile)); auto *importMod = ModuleDecl::create(moduleID.first, Ctx); if (EnableLibraryEvolution) importMod->setResilienceStrategy(ResilienceStrategy::Resilient); Ctx.LoadedModules[moduleID.first] = importMod; auto implicitImportKind = SourceFile::ImplicitModuleImportKind::Stdlib; if (!Ctx.getStdlibModule()) implicitImportKind = SourceFile::ImplicitModuleImportKind::None; auto *importFile = new (Ctx) SourceFile(*importMod, SourceFileKind::Library, bufferID, implicitImportKind, Ctx.LangOpts.CollectParsedToken, Ctx.LangOpts.BuildSyntaxTree); importMod->addFile(*importFile); bool done; parseIntoSourceFile(*importFile, bufferID, &done, nullptr, nullptr); assert(done && "Parser returned early?"); (void)done; performNameBinding(*importFile); importMod->setHasResolvedImports(); return importMod; } void SourceLoader::loadExtensions(NominalTypeDecl *nominal, unsigned previousGeneration) { // Type-checking the source automatically loads all extensions; there's // nothing to do here. }