//===------------ DependencyScanningTool.cpp - Swift Compiler -------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2020 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 "swift/DependencyScan/DependencyScanningTool.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticsFrontend.h" #include "swift/Basic/LLVMInitialize.h" #include "swift/DependencyScan/DependencyScanImpl.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include namespace swift { namespace dependencies { DependencyScanningTool::DependencyScanningTool() : SharedCache(std::make_unique()), VersionedPCMInstanceCacheCache( std::make_unique()), PDC(), Alloc(), Saver(Alloc) {} llvm::ErrorOr DependencyScanningTool::getDependencies( ArrayRef Command, const llvm::StringSet<> &PlaceholderModules) { // The primary instance used to scan the query Swift source-code auto InstanceOrErr = initCompilerInstanceForScan(Command); if (std::error_code EC = InstanceOrErr.getError()) return EC; auto Instance = std::move(*InstanceOrErr); // Execute the scanning action, retreiving the in-memory result auto DependenciesOrErr = performModuleScan(*Instance.get(), *SharedCache); if (DependenciesOrErr.getError()) return std::make_error_code(std::errc::not_supported); auto Dependencies = std::move(*DependenciesOrErr); return Dependencies; } llvm::ErrorOr DependencyScanningTool::getImports(ArrayRef Command) { // The primary instance used to scan the query Swift source-code auto InstanceOrErr = initCompilerInstanceForScan(Command); if (std::error_code EC = InstanceOrErr.getError()) return EC; auto Instance = std::move(*InstanceOrErr); // Execute the scanning action, retreiving the in-memory result auto DependenciesOrErr = performModulePrescan(*Instance.get()); if (DependenciesOrErr.getError()) return std::make_error_code(std::errc::not_supported); auto Dependencies = std::move(*DependenciesOrErr); return Dependencies; } std::vector> DependencyScanningTool::getDependencies( ArrayRef Command, const std::vector &BatchInput, const llvm::StringSet<> &PlaceholderModules) { // The primary instance used to scan Swift modules auto InstanceOrErr = initCompilerInstanceForScan(Command); if (std::error_code EC = InstanceOrErr.getError()) return std::vector>( BatchInput.size(), std::make_error_code(std::errc::invalid_argument)); auto Instance = std::move(*InstanceOrErr); auto batchScanResults = performBatchModuleScan( *Instance.get(), *SharedCache, VersionedPCMInstanceCacheCache.get(), Saver, BatchInput); return batchScanResults; } llvm::ErrorOr> DependencyScanningTool::initCompilerInstanceForScan( ArrayRef Command) { // State unique to an individual scan auto Instance = std::make_unique(); Instance->addDiagnosticConsumer(&PDC); // Basic error checking on the arguments if (Command.empty()) { Instance->getDiags().diagnose(SourceLoc(), diag::error_no_frontend_args); return std::make_error_code(std::errc::invalid_argument); } CompilerInvocation Invocation; SmallString<128> WorkingDirectory; llvm::sys::fs::current_path(WorkingDirectory); // Parse arguments. std::string CommandString; for (const auto *c : Command) { CommandString.append(c); CommandString.append(" "); } SmallVector Args; llvm::cl::TokenizeGNUCommandLine(CommandString, Saver, Args); if (Invocation.parseArgs(Args, Instance->getDiags())) { return std::make_error_code(std::errc::invalid_argument); } // Setup the instance Instance->setup(Invocation); (void)Instance->getMainModule(); return Instance; } } // namespace dependencies } // namespace swift