13#include "llvm/ADT/SmallString.h"
14#include "llvm/ADT/StringRef.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/FileSystem.h"
17#include "llvm/Support/MemoryBuffer.h"
18#include "llvm/Support/Path.h"
19#include "llvm/Support/raw_ostream.h"
27std::string getShardPathFromFilePath(llvm::StringRef ShardRoot,
28 llvm::StringRef FilePath) {
29 llvm::SmallString<128> ShardRootSS(ShardRoot);
30 llvm::sys::path::append(ShardRootSS, llvm::sys::path::filename(FilePath) +
31 "." + llvm::toHex(
digest(FilePath)) +
33 return std::string(ShardRootSS);
37class DiskBackedIndexStorage :
public BackgroundIndexStorage {
38 std::string DiskShardRoot;
44 std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot);
46 elog(
"Failed to create directory {0} for index storage: {1}",
47 DiskShardRoot, EC.message());
51 std::unique_ptr<IndexFileIn>
52 loadShard(llvm::StringRef ShardIdentifier)
const override {
53 const std::string ShardPath =
54 getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
55 auto Buffer = llvm::MemoryBuffer::getFile(ShardPath);
60 return std::make_unique<IndexFileIn>(std::move(*I));
62 elog(
"Error while reading shard {0}: {1}", ShardIdentifier,
67 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
68 IndexFileOut Shard)
const override {
69 auto ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
70 return llvm::writeToOutput(ShardPath, [&Shard](llvm::raw_ostream &
OS) {
72 return llvm::Error::success();
79class NullStorage :
public BackgroundIndexStorage {
81 std::unique_ptr<IndexFileIn>
82 loadShard(llvm::StringRef ShardIdentifier)
const override {
86 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
87 IndexFileOut Shard)
const override {
88 vlog(
"Couldn't find project for {0}, indexing in-memory only",
90 return llvm::Error::success();
97class DiskBackedIndexStorageManager {
99 DiskBackedIndexStorageManager(
100 std::function<std::optional<ProjectInfo>(
PathRef)> GetProjectInfo)
101 : IndexStorageMapMu(std::make_unique<std::mutex>()),
102 GetProjectInfo(std::move(GetProjectInfo)) {
103 llvm::SmallString<128> FallbackDir;
104 if (llvm::sys::path::cache_directory(FallbackDir))
105 llvm::sys::path::append(FallbackDir,
"clangd",
"index");
106 this->FallbackDir = FallbackDir.str().str();
111 std::lock_guard<std::mutex> Lock(*IndexStorageMapMu);
112 llvm::SmallString<128> StorageDir(FallbackDir);
113 if (
auto PI = GetProjectInfo(
File)) {
114 StorageDir = PI->SourceRoot;
115 llvm::sys::path::append(StorageDir,
".cache",
"clangd",
"index");
117 auto &IndexStorage = IndexStorageMap[StorageDir];
119 IndexStorage = create(StorageDir);
120 return IndexStorage.get();
124 std::unique_ptr<BackgroundIndexStorage> create(
PathRef CDBDirectory) {
125 if (CDBDirectory.empty()) {
126 elog(
"Tried to create storage for empty directory!");
127 return std::make_unique<NullStorage>();
129 return std::make_unique<DiskBackedIndexStorage>(CDBDirectory);
134 llvm::StringMap<std::unique_ptr<BackgroundIndexStorage>> IndexStorageMap;
135 std::unique_ptr<std::mutex> IndexStorageMapMu;
137 std::function<std::optional<ProjectInfo>(
PathRef)> GetProjectInfo;
144 std::function<std::optional<ProjectInfo>(
PathRef)> GetProjectInfo) {
145 return DiskBackedIndexStorageManager(std::move(GetProjectInfo));
llvm::StringRef Directory
llvm::unique_function< BackgroundIndexStorage *(PathRef)> Factory
static Factory createDiskBackedStorageFactory(std::function< std::optional< ProjectInfo >(PathRef)> GetProjectInfo)
llvm::Expected< IndexFileIn > readIndexFile(llvm::StringRef Data, SymbolOrigin Origin)
std::string Path
A typedef to represent a file path.
FileDigest digest(llvm::StringRef Content)
void vlog(const char *Fmt, Ts &&... Vals)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
void elog(const char *Fmt, Ts &&... Vals)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//