forked from OSchip/llvm-project
149 lines
4.7 KiB
C++
149 lines
4.7 KiB
C++
//===--- 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
|