clang-tools  15.0.0git
BackgroundIndexLoader.cpp
Go to the documentation of this file.
1 //===-- BackgroundIndexLoader.cpp - ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include "index/Background.h"
12 #include "support/Logger.h"
13 #include "support/Path.h"
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/Support/Path.h"
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 namespace clang {
21 namespace clangd {
22 namespace {
23 
24 /// A helper class to cache BackgroundIndexStorage operations and keep the
25 /// inverse dependency mapping.
26 class BackgroundIndexLoader {
27 public:
28  BackgroundIndexLoader(BackgroundIndexStorage::Factory &IndexStorageFactory)
29  : IndexStorageFactory(IndexStorageFactory) {}
30  /// Load the shards for \p MainFile and all of its dependencies.
31  void load(PathRef MainFile);
32 
33  /// Consumes the loader and returns all shards.
34  std::vector<LoadedShard> takeResult() &&;
35 
36 private:
37  /// Returns the Shard for \p StartSourceFile from cache or loads it from \p
38  /// Storage. Also returns paths for dependencies of \p StartSourceFile if it
39  /// wasn't cached yet.
40  std::pair<const LoadedShard &, std::vector<Path>>
41  loadShard(PathRef StartSourceFile, PathRef DependentTU);
42 
43  /// Cache for Storage lookups.
44  llvm::StringMap<LoadedShard> LoadedShards;
45 
46  BackgroundIndexStorage::Factory &IndexStorageFactory;
47 };
48 
49 std::pair<const LoadedShard &, std::vector<Path>>
50 BackgroundIndexLoader::loadShard(PathRef StartSourceFile, PathRef DependentTU) {
51  auto It = LoadedShards.try_emplace(StartSourceFile);
52  LoadedShard &LS = It.first->getValue();
53  std::vector<Path> Edges = {};
54  // Return the cached shard.
55  if (!It.second)
56  return {LS, Edges};
57 
58  LS.AbsolutePath = StartSourceFile.str();
59  LS.DependentTU = std::string(DependentTU);
60  BackgroundIndexStorage *Storage = IndexStorageFactory(LS.AbsolutePath);
61  auto Shard = Storage->loadShard(StartSourceFile);
62  if (!Shard || !Shard->Sources) {
63  vlog("Failed to load shard: {0}", StartSourceFile);
64  return {LS, Edges};
65  }
66 
67  LS.Shard = std::move(Shard);
68  for (const auto &It : *LS.Shard->Sources) {
69  auto AbsPath = URI::resolve(It.getKey(), StartSourceFile);
70  if (!AbsPath) {
71  elog("Failed to resolve URI: {0}", AbsPath.takeError());
72  continue;
73  }
74  // A shard contains only edges for non main-file sources.
75  if (*AbsPath != StartSourceFile) {
76  Edges.push_back(*AbsPath);
77  continue;
78  }
79 
80  // Fill in shard metadata.
81  const IncludeGraphNode &IGN = It.getValue();
82  LS.Digest = IGN.Digest;
83  LS.CountReferences = IGN.Flags & IncludeGraphNode::SourceFlag::IsTU;
84  LS.HadErrors = IGN.Flags & IncludeGraphNode::SourceFlag::HadErrors;
85  }
86  assert(LS.Digest != FileDigest{{0}} && "Digest is empty?");
87  return {LS, Edges};
88 }
89 
90 void BackgroundIndexLoader::load(PathRef MainFile) {
91  llvm::StringSet<> InQueue;
92  // Following containers points to strings inside InQueue.
93  std::queue<PathRef> ToVisit;
94  InQueue.insert(MainFile);
95  ToVisit.push(MainFile);
96 
97  while (!ToVisit.empty()) {
98  PathRef SourceFile = ToVisit.front();
99  ToVisit.pop();
100 
101  auto ShardAndEdges = loadShard(SourceFile, MainFile);
102  for (PathRef Edge : ShardAndEdges.second) {
103  auto It = InQueue.insert(Edge);
104  if (It.second)
105  ToVisit.push(It.first->getKey());
106  }
107  }
108 }
109 
110 std::vector<LoadedShard> BackgroundIndexLoader::takeResult() && {
111  std::vector<LoadedShard> Result;
112  Result.reserve(LoadedShards.size());
113  for (auto &It : LoadedShards)
114  Result.push_back(std::move(It.getValue()));
115  return Result;
116 }
117 } // namespace
118 
119 std::vector<LoadedShard>
120 loadIndexShards(llvm::ArrayRef<Path> MainFiles,
121  BackgroundIndexStorage::Factory &IndexStorageFactory,
122  const GlobalCompilationDatabase &CDB) {
123  BackgroundIndexLoader Loader(IndexStorageFactory);
124  for (llvm::StringRef MainFile : MainFiles) {
125  assert(llvm::sys::path::is_absolute(MainFile));
126  Loader.load(MainFile);
127  }
128  return std::move(Loader).takeResult();
129 }
130 
131 } // namespace clangd
132 } // namespace clang
Background.h
Path.h
clang::clangd::IncludeGraphNode::SourceFlag::IsTU
@ IsTU
clang::clangd::GlobalCompilationDatabase
Provides compilation arguments used for parsing C and C++ files.
Definition: GlobalCompilationDatabase.h:34
clang::clangd::loadIndexShards
std::vector< LoadedShard > loadIndexShards(llvm::ArrayRef< Path > MainFiles, BackgroundIndexStorage::Factory &IndexStorageFactory, const GlobalCompilationDatabase &CDB)
Loads all shards for the TU MainFile from Storage.
Definition: BackgroundIndexLoader.cpp:120
clang::clangd::URI::resolve
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
Definition: URI.cpp:245
GlobalCompilationDatabase.h
Logger.h
clang::clangd::vlog
void vlog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:72
clang::clangd::BackgroundIndexStorage::Factory
llvm::unique_function< BackgroundIndexStorage *(PathRef)> Factory
Definition: Background.h:57
clang::clangd::IncludeGraphNode::SourceFlag::HadErrors
@ HadErrors
BackgroundIndexLoader.h
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
clang::clangd::FileDigest
std::array< uint8_t, 8 > FileDigest
Definition: SourceCode.h:41
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
MainFile
std::string MainFile
Definition: HeadersTests.cpp:134
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:61