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