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