xref: /llvm-project/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp (revision 4d006520b8c0cc3a52913b4665bf741c737e5592)
191e5f4b4SKadir Cetinkaya //===-- BackgroundIndexLoader.cpp - ---------------------------------------===//
291e5f4b4SKadir Cetinkaya //
391e5f4b4SKadir Cetinkaya // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
491e5f4b4SKadir Cetinkaya // See https://llvm.org/LICENSE.txt for license information.
591e5f4b4SKadir Cetinkaya // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
691e5f4b4SKadir Cetinkaya //
791e5f4b4SKadir Cetinkaya //===----------------------------------------------------------------------===//
891e5f4b4SKadir Cetinkaya 
991e5f4b4SKadir Cetinkaya #include "index/BackgroundIndexLoader.h"
1091e5f4b4SKadir Cetinkaya #include "GlobalCompilationDatabase.h"
1191e5f4b4SKadir Cetinkaya #include "index/Background.h"
12*ad97ccf6SSam McCall #include "support/Logger.h"
13*ad97ccf6SSam McCall #include "support/Path.h"
1491e5f4b4SKadir Cetinkaya #include "llvm/ADT/StringMap.h"
1591e5f4b4SKadir Cetinkaya #include "llvm/Support/Path.h"
1691e5f4b4SKadir Cetinkaya #include <string>
1791e5f4b4SKadir Cetinkaya #include <utility>
1891e5f4b4SKadir Cetinkaya #include <vector>
1991e5f4b4SKadir Cetinkaya 
2091e5f4b4SKadir Cetinkaya namespace clang {
2191e5f4b4SKadir Cetinkaya namespace clangd {
2291e5f4b4SKadir Cetinkaya namespace {
2391e5f4b4SKadir Cetinkaya 
2491e5f4b4SKadir Cetinkaya /// A helper class to cache BackgroundIndexStorage operations and keep the
2591e5f4b4SKadir Cetinkaya /// inverse dependency mapping.
2691e5f4b4SKadir Cetinkaya class BackgroundIndexLoader {
2791e5f4b4SKadir Cetinkaya public:
BackgroundIndexLoader(BackgroundIndexStorage::Factory & IndexStorageFactory)2891e5f4b4SKadir Cetinkaya   BackgroundIndexLoader(BackgroundIndexStorage::Factory &IndexStorageFactory)
2991e5f4b4SKadir Cetinkaya       : IndexStorageFactory(IndexStorageFactory) {}
3091e5f4b4SKadir Cetinkaya   /// Load the shards for \p MainFile and all of its dependencies.
3191e5f4b4SKadir Cetinkaya   void load(PathRef MainFile);
3291e5f4b4SKadir Cetinkaya 
3391e5f4b4SKadir Cetinkaya   /// Consumes the loader and returns all shards.
3491e5f4b4SKadir Cetinkaya   std::vector<LoadedShard> takeResult() &&;
3591e5f4b4SKadir Cetinkaya 
3691e5f4b4SKadir Cetinkaya private:
3791e5f4b4SKadir Cetinkaya   /// Returns the Shard for \p StartSourceFile from cache or loads it from \p
3891e5f4b4SKadir Cetinkaya   /// Storage. Also returns paths for dependencies of \p StartSourceFile if it
3991e5f4b4SKadir Cetinkaya   /// wasn't cached yet.
4091e5f4b4SKadir Cetinkaya   std::pair<const LoadedShard &, std::vector<Path>>
4191e5f4b4SKadir Cetinkaya   loadShard(PathRef StartSourceFile, PathRef DependentTU);
4291e5f4b4SKadir Cetinkaya 
4391e5f4b4SKadir Cetinkaya   /// Cache for Storage lookups.
4491e5f4b4SKadir Cetinkaya   llvm::StringMap<LoadedShard> LoadedShards;
4591e5f4b4SKadir Cetinkaya 
4691e5f4b4SKadir Cetinkaya   BackgroundIndexStorage::Factory &IndexStorageFactory;
4791e5f4b4SKadir Cetinkaya };
4891e5f4b4SKadir Cetinkaya 
4991e5f4b4SKadir Cetinkaya std::pair<const LoadedShard &, std::vector<Path>>
loadShard(PathRef StartSourceFile,PathRef DependentTU)5091e5f4b4SKadir Cetinkaya BackgroundIndexLoader::loadShard(PathRef StartSourceFile, PathRef DependentTU) {
5191e5f4b4SKadir Cetinkaya   auto It = LoadedShards.try_emplace(StartSourceFile);
5291e5f4b4SKadir Cetinkaya   LoadedShard &LS = It.first->getValue();
5391e5f4b4SKadir Cetinkaya   std::vector<Path> Edges = {};
5491e5f4b4SKadir Cetinkaya   // Return the cached shard.
5591e5f4b4SKadir Cetinkaya   if (!It.second)
5691e5f4b4SKadir Cetinkaya     return {LS, Edges};
5791e5f4b4SKadir Cetinkaya 
5891e5f4b4SKadir Cetinkaya   LS.AbsolutePath = StartSourceFile.str();
59adcd0268SBenjamin Kramer   LS.DependentTU = std::string(DependentTU);
6091e5f4b4SKadir Cetinkaya   BackgroundIndexStorage *Storage = IndexStorageFactory(LS.AbsolutePath);
6191e5f4b4SKadir Cetinkaya   auto Shard = Storage->loadShard(StartSourceFile);
6291e5f4b4SKadir Cetinkaya   if (!Shard || !Shard->Sources) {
6391e5f4b4SKadir Cetinkaya     vlog("Failed to load shard: {0}", StartSourceFile);
6491e5f4b4SKadir Cetinkaya     return {LS, Edges};
6591e5f4b4SKadir Cetinkaya   }
6691e5f4b4SKadir Cetinkaya 
6791e5f4b4SKadir Cetinkaya   LS.Shard = std::move(Shard);
6891e5f4b4SKadir Cetinkaya   for (const auto &It : *LS.Shard->Sources) {
69b70323e5SHaojian Wu     auto AbsPath = URI::resolve(It.getKey(), StartSourceFile);
70b70323e5SHaojian Wu     if (!AbsPath) {
71b70323e5SHaojian Wu       elog("Failed to resolve URI: {0}", AbsPath.takeError());
7291e5f4b4SKadir Cetinkaya       continue;
73b70323e5SHaojian Wu     }
7491e5f4b4SKadir Cetinkaya     // A shard contains only edges for non main-file sources.
7591e5f4b4SKadir Cetinkaya     if (*AbsPath != StartSourceFile) {
7691e5f4b4SKadir Cetinkaya       Edges.push_back(*AbsPath);
7791e5f4b4SKadir Cetinkaya       continue;
7891e5f4b4SKadir Cetinkaya     }
7991e5f4b4SKadir Cetinkaya 
8091e5f4b4SKadir Cetinkaya     // Fill in shard metadata.
8191e5f4b4SKadir Cetinkaya     const IncludeGraphNode &IGN = It.getValue();
8291e5f4b4SKadir Cetinkaya     LS.Digest = IGN.Digest;
8391e5f4b4SKadir Cetinkaya     LS.CountReferences = IGN.Flags & IncludeGraphNode::SourceFlag::IsTU;
8491e5f4b4SKadir Cetinkaya     LS.HadErrors = IGN.Flags & IncludeGraphNode::SourceFlag::HadErrors;
8591e5f4b4SKadir Cetinkaya   }
8691e5f4b4SKadir Cetinkaya   assert(LS.Digest != FileDigest{{0}} && "Digest is empty?");
8791e5f4b4SKadir Cetinkaya   return {LS, Edges};
8891e5f4b4SKadir Cetinkaya }
8991e5f4b4SKadir Cetinkaya 
load(PathRef MainFile)9091e5f4b4SKadir Cetinkaya void BackgroundIndexLoader::load(PathRef MainFile) {
9191e5f4b4SKadir Cetinkaya   llvm::StringSet<> InQueue;
9291e5f4b4SKadir Cetinkaya   // Following containers points to strings inside InQueue.
9391e5f4b4SKadir Cetinkaya   std::queue<PathRef> ToVisit;
9491e5f4b4SKadir Cetinkaya   InQueue.insert(MainFile);
9591e5f4b4SKadir Cetinkaya   ToVisit.push(MainFile);
9691e5f4b4SKadir Cetinkaya 
9791e5f4b4SKadir Cetinkaya   while (!ToVisit.empty()) {
9891e5f4b4SKadir Cetinkaya     PathRef SourceFile = ToVisit.front();
9991e5f4b4SKadir Cetinkaya     ToVisit.pop();
10091e5f4b4SKadir Cetinkaya 
10191e5f4b4SKadir Cetinkaya     auto ShardAndEdges = loadShard(SourceFile, MainFile);
10291e5f4b4SKadir Cetinkaya     for (PathRef Edge : ShardAndEdges.second) {
10391e5f4b4SKadir Cetinkaya       auto It = InQueue.insert(Edge);
10491e5f4b4SKadir Cetinkaya       if (It.second)
10591e5f4b4SKadir Cetinkaya         ToVisit.push(It.first->getKey());
10691e5f4b4SKadir Cetinkaya     }
10791e5f4b4SKadir Cetinkaya   }
10891e5f4b4SKadir Cetinkaya }
10991e5f4b4SKadir Cetinkaya 
takeResult()11091e5f4b4SKadir Cetinkaya std::vector<LoadedShard> BackgroundIndexLoader::takeResult() && {
11191e5f4b4SKadir Cetinkaya   std::vector<LoadedShard> Result;
11291e5f4b4SKadir Cetinkaya   Result.reserve(LoadedShards.size());
11391e5f4b4SKadir Cetinkaya   for (auto &It : LoadedShards)
11491e5f4b4SKadir Cetinkaya     Result.push_back(std::move(It.getValue()));
11591e5f4b4SKadir Cetinkaya   return Result;
11691e5f4b4SKadir Cetinkaya }
11791e5f4b4SKadir Cetinkaya } // namespace
11891e5f4b4SKadir Cetinkaya 
11991e5f4b4SKadir Cetinkaya std::vector<LoadedShard>
loadIndexShards(llvm::ArrayRef<Path> MainFiles,BackgroundIndexStorage::Factory & IndexStorageFactory,const GlobalCompilationDatabase & CDB)12091e5f4b4SKadir Cetinkaya loadIndexShards(llvm::ArrayRef<Path> MainFiles,
12191e5f4b4SKadir Cetinkaya                 BackgroundIndexStorage::Factory &IndexStorageFactory,
12291e5f4b4SKadir Cetinkaya                 const GlobalCompilationDatabase &CDB) {
12391e5f4b4SKadir Cetinkaya   BackgroundIndexLoader Loader(IndexStorageFactory);
12491e5f4b4SKadir Cetinkaya   for (llvm::StringRef MainFile : MainFiles) {
12591e5f4b4SKadir Cetinkaya     assert(llvm::sys::path::is_absolute(MainFile));
12691e5f4b4SKadir Cetinkaya     Loader.load(MainFile);
12791e5f4b4SKadir Cetinkaya   }
12891e5f4b4SKadir Cetinkaya   return std::move(Loader).takeResult();
12991e5f4b4SKadir Cetinkaya }
13091e5f4b4SKadir Cetinkaya 
13191e5f4b4SKadir Cetinkaya } // namespace clangd
13291e5f4b4SKadir Cetinkaya } // namespace clang
133