1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
//===--- ProjectAware.h ------------------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "ProjectAware.h"
#include "Config.h"
#include "index/Index.h"
#include "index/MemIndex.h"
#include "index/Merge.h"
#include "index/Ref.h"
#include "index/Serialization.h"
#include "index/Symbol.h"
#include "index/SymbolID.h"
#include "support/Logger.h"
#include "support/Threading.h"
#include "support/Trace.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <map>
#include <memory>
#include <mutex>
#include <tuple>
namespace clang {
namespace clangd {
namespace {
class ProjectAwareIndex : public SymbolIndex {
public:
size_t estimateMemoryUsage() const override;
/// Only queries the associated index with the current context.
void lookup(const LookupRequest &Req,
llvm::function_ref<void(const Symbol &)> Callback) const override;
/// Query all indexes while prioritizing the associated one (if any).
bool refs(const RefsRequest &Req,
llvm::function_ref<void(const Ref &)> Callback) const override;
/// Queries only the associates index when Req.RestrictForCodeCompletion is
/// set, otherwise queries all.
bool
fuzzyFind(const FuzzyFindRequest &Req,
llvm::function_ref<void(const Symbol &)> Callback) const override;
/// Query all indexes while prioritizing the associated one (if any).
void relations(const RelationsRequest &Req,
llvm::function_ref<void(const SymbolID &, const Symbol &)>
Callback) const override;
llvm::unique_function<IndexContents(llvm::StringRef) const>
indexedFiles() const override;
ProjectAwareIndex(IndexFactory Gen, bool Sync) : Gen(std::move(Gen)) {
if (!Sync)
Tasks = std::make_unique<AsyncTaskRunner>();
}
private:
// Returns the index associated with current context, if any.
SymbolIndex *getIndex() const;
// Storage for all the external indexes.
mutable std::mutex Mu;
mutable llvm::DenseMap<Config::ExternalIndexSpec,
std::unique_ptr<SymbolIndex>>
IndexForSpec;
mutable std::unique_ptr<AsyncTaskRunner> Tasks;
const IndexFactory Gen;
};
size_t ProjectAwareIndex::estimateMemoryUsage() const {
size_t Total = 0;
std::lock_guard<std::mutex> Lock(Mu);
for (auto &Entry : IndexForSpec)
Total += Entry.second->estimateMemoryUsage();
return Total;
}
void ProjectAwareIndex::lookup(
const LookupRequest &Req,
llvm::function_ref<void(const Symbol &)> Callback) const {
trace::Span Tracer("ProjectAwareIndex::lookup");
if (auto *Idx = getIndex())
Idx->lookup(Req, Callback);
}
bool ProjectAwareIndex::refs(
const RefsRequest &Req,
llvm::function_ref<void(const Ref &)> Callback) const {
trace::Span Tracer("ProjectAwareIndex::refs");
if (auto *Idx = getIndex())
return Idx->refs(Req, Callback);
return false;
}
bool ProjectAwareIndex::fuzzyFind(
const FuzzyFindRequest &Req,
llvm::function_ref<void(const Symbol &)> Callback) const {
trace::Span Tracer("ProjectAwareIndex::fuzzyFind");
if (auto *Idx = getIndex())
return Idx->fuzzyFind(Req, Callback);
return false;
}
void ProjectAwareIndex::relations(
const RelationsRequest &Req,
llvm::function_ref<void(const SymbolID &, const Symbol &)> Callback) const {
trace::Span Tracer("ProjectAwareIndex::relations");
if (auto *Idx = getIndex())
return Idx->relations(Req, Callback);
}
llvm::unique_function<IndexContents(llvm::StringRef) const>
ProjectAwareIndex::indexedFiles() const {
trace::Span Tracer("ProjectAwareIndex::indexedFiles");
if (auto *Idx = getIndex())
return Idx->indexedFiles();
return [](llvm::StringRef) { return IndexContents::None; };
}
SymbolIndex *ProjectAwareIndex::getIndex() const {
const auto &C = Config::current();
if (C.Index.External.Kind == Config::ExternalIndexSpec::None)
return nullptr;
const auto &External = C.Index.External;
std::lock_guard<std::mutex> Lock(Mu);
auto Entry = IndexForSpec.try_emplace(External, nullptr);
if (Entry.second)
Entry.first->getSecond() = Gen(External, Tasks.get());
return Entry.first->second.get();
}
} // namespace
std::unique_ptr<SymbolIndex> createProjectAwareIndex(IndexFactory Gen,
bool Sync) {
assert(Gen);
return std::make_unique<ProjectAwareIndex>(std::move(Gen), Sync);
}
} // namespace clangd
} // namespace clang
|