1 //===-- BackgroundIndexLoader.cpp - ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "index/BackgroundIndexLoader.h"
10 #include "GlobalCompilationDatabase.h"
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"
24 /// A helper class to cache BackgroundIndexStorage operations and keep the
25 /// inverse dependency mapping.
26 class BackgroundIndexLoader
{
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
);
33 /// Consumes the loader and returns all shards.
34 std::vector
<LoadedShard
> takeResult() &&;
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
);
43 /// Cache for Storage lookups.
44 llvm::StringMap
<LoadedShard
> LoadedShards
;
46 BackgroundIndexStorage::Factory
&IndexStorageFactory
;
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.
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
);
67 LS
.Shard
= std::move(Shard
);
68 for (const auto &It
: *LS
.Shard
->Sources
) {
69 auto AbsPath
= URI::resolve(It
.getKey(), StartSourceFile
);
71 elog("Failed to resolve URI: {0}", AbsPath
.takeError());
74 // A shard contains only edges for non main-file sources.
75 if (*AbsPath
!= StartSourceFile
) {
76 Edges
.push_back(*AbsPath
);
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
;
86 assert(LS
.Digest
!= FileDigest
{{0}} && "Digest is empty?");
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
);
97 while (!ToVisit
.empty()) {
98 PathRef SourceFile
= ToVisit
.front();
101 auto ShardAndEdges
= loadShard(SourceFile
, MainFile
);
102 for (PathRef Edge
: ShardAndEdges
.second
) {
103 auto It
= InQueue
.insert(Edge
);
105 ToVisit
.push(It
.first
->getKey());
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()));
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
);
128 return std::move(Loader
).takeResult();
131 } // namespace clangd