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);
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 llvm::SmallString<128> GitignorePath(DiskShardRoot);
52 llvm::sys::path::append(GitignorePath,
".gitignore");
53 auto Error = llvm::writeToOutput(GitignorePath, [](llvm::raw_ostream &OS) {
54 OS <<
"# This file is autogenerated by clangd.\n*\n";
55 return llvm::Error::success();
57 llvm::consumeError(std::move(
Error));
60 std::unique_ptr<IndexFileIn>
61 loadShard(llvm::StringRef ShardIdentifier)
const override {
62 const std::string ShardPath =
63 getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
64 auto Buffer = llvm::MemoryBuffer::getFile(ShardPath);
69 return std::make_unique<IndexFileIn>(std::move(*I));
71 elog(
"Error while reading shard {0}: {1}", ShardIdentifier,
76 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
77 IndexFileOut Shard)
const override {
78 auto ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
79 return llvm::writeToOutput(ShardPath, [&Shard](llvm::raw_ostream &OS) {
81 return llvm::Error::success();
90 std::unique_ptr<IndexFileIn>
91 loadShard(llvm::StringRef ShardIdentifier)
const override {
95 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
96 IndexFileOut Shard)
const override {
97 vlog(
"Couldn't find project for {0}, indexing in-memory only",
99 return llvm::Error::success();
106class DiskBackedIndexStorageManager {
108 DiskBackedIndexStorageManager(
109 std::function<std::optional<ProjectInfo>(
PathRef)> GetProjectInfo)
110 : IndexStorageMapMu(std::make_unique<std::mutex>()),
111 GetProjectInfo(std::move(GetProjectInfo)) {
112 llvm::SmallString<128> FallbackDir;
113 if (llvm::sys::path::cache_directory(FallbackDir))
114 llvm::sys::path::append(FallbackDir,
"clangd",
"index");
115 this->FallbackDir = FallbackDir.str().str();
120 std::lock_guard<std::mutex> Lock(*IndexStorageMapMu);
121 llvm::SmallString<128> StorageDir(FallbackDir);
122 if (
auto PI = GetProjectInfo(
File)) {
123 StorageDir = PI->SourceRoot;
124 llvm::sys::path::append(StorageDir,
".cache",
"clangd",
"index");
126 auto &IndexStorage = IndexStorageMap[StorageDir];
128 IndexStorage = create(StorageDir);
129 return IndexStorage.get();
133 std::unique_ptr<BackgroundIndexStorage> create(
PathRef CDBDirectory) {
134 if (CDBDirectory.empty()) {
135 elog(
"Tried to create storage for empty directory!");
136 return std::make_unique<NullStorage>();
138 return std::make_unique<DiskBackedIndexStorage>(CDBDirectory);
143 llvm::StringMap<std::unique_ptr<BackgroundIndexStorage>> IndexStorageMap;
144 std::unique_ptr<std::mutex> IndexStorageMapMu;
146 std::function<std::optional<ProjectInfo>(
PathRef)> GetProjectInfo;
153 std::function<std::optional<ProjectInfo>(
PathRef)> GetProjectInfo) {
154 return DiskBackedIndexStorageManager(std::move(GetProjectInfo));
static cl::opt< std::string > Directory(cl::Positional, cl::Required, cl::desc("<Search Root Directory>"))
llvm::unique_function< BackgroundIndexStorage *(PathRef)> Factory
static Factory createDiskBackedStorageFactory(std::function< std::optional< ProjectInfo >(PathRef)> GetProjectInfo)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
llvm::Expected< IndexFileIn > readIndexFile(llvm::StringRef Data, SymbolOrigin Origin)
FileDigest digest(llvm::StringRef Content)
void vlog(const char *Fmt, Ts &&... Vals)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
std::string Path
A typedef to represent a file path.
void elog(const char *Fmt, Ts &&... Vals)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//