1067ffbfeSKadir Cetinkaya //===--- ProjectAware.h ------------------------------------------*- C++-*-===// 2067ffbfeSKadir Cetinkaya // 3067ffbfeSKadir Cetinkaya // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4067ffbfeSKadir Cetinkaya // See https://llvm.org/LICENSE.txt for license information. 5067ffbfeSKadir Cetinkaya // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6067ffbfeSKadir Cetinkaya // 7067ffbfeSKadir Cetinkaya //===----------------------------------------------------------------------===// 8067ffbfeSKadir Cetinkaya 9067ffbfeSKadir Cetinkaya #include "ProjectAware.h" 10067ffbfeSKadir Cetinkaya #include "Config.h" 11067ffbfeSKadir Cetinkaya #include "index/Index.h" 12067ffbfeSKadir Cetinkaya #include "index/Ref.h" 13067ffbfeSKadir Cetinkaya #include "index/Symbol.h" 14067ffbfeSKadir Cetinkaya #include "index/SymbolID.h" 15067ffbfeSKadir Cetinkaya #include "support/Threading.h" 16067ffbfeSKadir Cetinkaya #include "support/Trace.h" 17067ffbfeSKadir Cetinkaya #include "llvm/ADT/DenseMap.h" 18067ffbfeSKadir Cetinkaya #include "llvm/ADT/StringRef.h" 19067ffbfeSKadir Cetinkaya #include <map> 20067ffbfeSKadir Cetinkaya #include <memory> 21067ffbfeSKadir Cetinkaya #include <mutex> 22067ffbfeSKadir Cetinkaya #include <tuple> 23067ffbfeSKadir Cetinkaya 24067ffbfeSKadir Cetinkaya namespace clang { 25067ffbfeSKadir Cetinkaya namespace clangd { 26067ffbfeSKadir Cetinkaya namespace { 27067ffbfeSKadir Cetinkaya class ProjectAwareIndex : public SymbolIndex { 28067ffbfeSKadir Cetinkaya public: 29067ffbfeSKadir Cetinkaya size_t estimateMemoryUsage() const override; 30067ffbfeSKadir Cetinkaya 31067ffbfeSKadir Cetinkaya /// Only queries the associated index with the current context. 32067ffbfeSKadir Cetinkaya void lookup(const LookupRequest &Req, 33067ffbfeSKadir Cetinkaya llvm::function_ref<void(const Symbol &)> Callback) const override; 34067ffbfeSKadir Cetinkaya 35067ffbfeSKadir Cetinkaya /// Query all indexes while prioritizing the associated one (if any). 36067ffbfeSKadir Cetinkaya bool refs(const RefsRequest &Req, 37067ffbfeSKadir Cetinkaya llvm::function_ref<void(const Ref &)> Callback) const override; 38*61fe67a4SNathan Ridge /// Query all indexes while prioritizing the associated one (if any). 39*61fe67a4SNathan Ridge bool containedRefs(const ContainedRefsRequest &Req, 40*61fe67a4SNathan Ridge llvm::function_ref<void(const ContainedRefsResult &)> 41*61fe67a4SNathan Ridge Callback) const override; 42067ffbfeSKadir Cetinkaya 43067ffbfeSKadir Cetinkaya /// Queries only the associates index when Req.RestrictForCodeCompletion is 44067ffbfeSKadir Cetinkaya /// set, otherwise queries all. 45067ffbfeSKadir Cetinkaya bool 46067ffbfeSKadir Cetinkaya fuzzyFind(const FuzzyFindRequest &Req, 47067ffbfeSKadir Cetinkaya llvm::function_ref<void(const Symbol &)> Callback) const override; 48067ffbfeSKadir Cetinkaya 49067ffbfeSKadir Cetinkaya /// Query all indexes while prioritizing the associated one (if any). 50067ffbfeSKadir Cetinkaya void relations(const RelationsRequest &Req, 51067ffbfeSKadir Cetinkaya llvm::function_ref<void(const SymbolID &, const Symbol &)> 52067ffbfeSKadir Cetinkaya Callback) const override; 53067ffbfeSKadir Cetinkaya 5491698fe4SAleksandr Platonov llvm::unique_function<IndexContents(llvm::StringRef) const> 55e35f9229SAleksandr Platonov indexedFiles() const override; 56e35f9229SAleksandr Platonov 57dc9c0963SKadir Cetinkaya ProjectAwareIndex(IndexFactory Gen, bool Sync) : Gen(std::move(Gen)) { 58dc9c0963SKadir Cetinkaya if (!Sync) 59dc9c0963SKadir Cetinkaya Tasks = std::make_unique<AsyncTaskRunner>(); 60dc9c0963SKadir Cetinkaya } 61067ffbfeSKadir Cetinkaya 62067ffbfeSKadir Cetinkaya private: 63067ffbfeSKadir Cetinkaya // Returns the index associated with current context, if any. 64067ffbfeSKadir Cetinkaya SymbolIndex *getIndex() const; 65067ffbfeSKadir Cetinkaya 66067ffbfeSKadir Cetinkaya // Storage for all the external indexes. 67067ffbfeSKadir Cetinkaya mutable std::mutex Mu; 68067ffbfeSKadir Cetinkaya mutable llvm::DenseMap<Config::ExternalIndexSpec, 69067ffbfeSKadir Cetinkaya std::unique_ptr<SymbolIndex>> 70067ffbfeSKadir Cetinkaya IndexForSpec; 71dc9c0963SKadir Cetinkaya mutable std::unique_ptr<AsyncTaskRunner> Tasks; 72067ffbfeSKadir Cetinkaya 73067ffbfeSKadir Cetinkaya const IndexFactory Gen; 74067ffbfeSKadir Cetinkaya }; 75067ffbfeSKadir Cetinkaya 76067ffbfeSKadir Cetinkaya size_t ProjectAwareIndex::estimateMemoryUsage() const { 77067ffbfeSKadir Cetinkaya size_t Total = 0; 78067ffbfeSKadir Cetinkaya std::lock_guard<std::mutex> Lock(Mu); 79067ffbfeSKadir Cetinkaya for (auto &Entry : IndexForSpec) 80067ffbfeSKadir Cetinkaya Total += Entry.second->estimateMemoryUsage(); 81067ffbfeSKadir Cetinkaya return Total; 82067ffbfeSKadir Cetinkaya } 83067ffbfeSKadir Cetinkaya 84067ffbfeSKadir Cetinkaya void ProjectAwareIndex::lookup( 85067ffbfeSKadir Cetinkaya const LookupRequest &Req, 86067ffbfeSKadir Cetinkaya llvm::function_ref<void(const Symbol &)> Callback) const { 87067ffbfeSKadir Cetinkaya trace::Span Tracer("ProjectAwareIndex::lookup"); 88067ffbfeSKadir Cetinkaya if (auto *Idx = getIndex()) 89067ffbfeSKadir Cetinkaya Idx->lookup(Req, Callback); 90067ffbfeSKadir Cetinkaya } 91067ffbfeSKadir Cetinkaya 92067ffbfeSKadir Cetinkaya bool ProjectAwareIndex::refs( 93067ffbfeSKadir Cetinkaya const RefsRequest &Req, 94067ffbfeSKadir Cetinkaya llvm::function_ref<void(const Ref &)> Callback) const { 95067ffbfeSKadir Cetinkaya trace::Span Tracer("ProjectAwareIndex::refs"); 96067ffbfeSKadir Cetinkaya if (auto *Idx = getIndex()) 97067ffbfeSKadir Cetinkaya return Idx->refs(Req, Callback); 98067ffbfeSKadir Cetinkaya return false; 99067ffbfeSKadir Cetinkaya } 100067ffbfeSKadir Cetinkaya 101*61fe67a4SNathan Ridge bool ProjectAwareIndex::containedRefs( 102*61fe67a4SNathan Ridge const ContainedRefsRequest &Req, 103*61fe67a4SNathan Ridge llvm::function_ref<void(const ContainedRefsResult &)> Callback) const { 104*61fe67a4SNathan Ridge trace::Span Tracer("ProjectAwareIndex::refersTo"); 105*61fe67a4SNathan Ridge if (auto *Idx = getIndex()) 106*61fe67a4SNathan Ridge return Idx->containedRefs(Req, Callback); 107*61fe67a4SNathan Ridge return false; 108*61fe67a4SNathan Ridge } 109*61fe67a4SNathan Ridge 110067ffbfeSKadir Cetinkaya bool ProjectAwareIndex::fuzzyFind( 111067ffbfeSKadir Cetinkaya const FuzzyFindRequest &Req, 112067ffbfeSKadir Cetinkaya llvm::function_ref<void(const Symbol &)> Callback) const { 113067ffbfeSKadir Cetinkaya trace::Span Tracer("ProjectAwareIndex::fuzzyFind"); 114067ffbfeSKadir Cetinkaya if (auto *Idx = getIndex()) 115067ffbfeSKadir Cetinkaya return Idx->fuzzyFind(Req, Callback); 116067ffbfeSKadir Cetinkaya return false; 117067ffbfeSKadir Cetinkaya } 118067ffbfeSKadir Cetinkaya 119067ffbfeSKadir Cetinkaya void ProjectAwareIndex::relations( 120067ffbfeSKadir Cetinkaya const RelationsRequest &Req, 121067ffbfeSKadir Cetinkaya llvm::function_ref<void(const SymbolID &, const Symbol &)> Callback) const { 122067ffbfeSKadir Cetinkaya trace::Span Tracer("ProjectAwareIndex::relations"); 123067ffbfeSKadir Cetinkaya if (auto *Idx = getIndex()) 124067ffbfeSKadir Cetinkaya return Idx->relations(Req, Callback); 125067ffbfeSKadir Cetinkaya } 126067ffbfeSKadir Cetinkaya 12791698fe4SAleksandr Platonov llvm::unique_function<IndexContents(llvm::StringRef) const> 128e35f9229SAleksandr Platonov ProjectAwareIndex::indexedFiles() const { 129e35f9229SAleksandr Platonov trace::Span Tracer("ProjectAwareIndex::indexedFiles"); 130e35f9229SAleksandr Platonov if (auto *Idx = getIndex()) 131e35f9229SAleksandr Platonov return Idx->indexedFiles(); 13291698fe4SAleksandr Platonov return [](llvm::StringRef) { return IndexContents::None; }; 133e35f9229SAleksandr Platonov } 134e35f9229SAleksandr Platonov 135067ffbfeSKadir Cetinkaya SymbolIndex *ProjectAwareIndex::getIndex() const { 136067ffbfeSKadir Cetinkaya const auto &C = Config::current(); 1379e9ac413SKadir Cetinkaya if (C.Index.External.Kind == Config::ExternalIndexSpec::None) 138067ffbfeSKadir Cetinkaya return nullptr; 1399e9ac413SKadir Cetinkaya const auto &External = C.Index.External; 140067ffbfeSKadir Cetinkaya std::lock_guard<std::mutex> Lock(Mu); 141067ffbfeSKadir Cetinkaya auto Entry = IndexForSpec.try_emplace(External, nullptr); 142067ffbfeSKadir Cetinkaya if (Entry.second) 143dc9c0963SKadir Cetinkaya Entry.first->getSecond() = Gen(External, Tasks.get()); 144067ffbfeSKadir Cetinkaya return Entry.first->second.get(); 145067ffbfeSKadir Cetinkaya } 146067ffbfeSKadir Cetinkaya } // namespace 147067ffbfeSKadir Cetinkaya 148dc9c0963SKadir Cetinkaya std::unique_ptr<SymbolIndex> createProjectAwareIndex(IndexFactory Gen, 149dc9c0963SKadir Cetinkaya bool Sync) { 150cab31368SKadir Cetinkaya assert(Gen); 151dc9c0963SKadir Cetinkaya return std::make_unique<ProjectAwareIndex>(std::move(Gen), Sync); 152067ffbfeSKadir Cetinkaya } 153067ffbfeSKadir Cetinkaya } // namespace clangd 154067ffbfeSKadir Cetinkaya } // namespace clang 155