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:
29 size_t estimateMemoryUsage() const override;
30
31 /// Only queries the associated index with the current context.
32 void lookup(const LookupRequest &Req,
33 llvm::function_ref<void(const Symbol &)> Callback) const override;
34
35 /// Query all indexes while prioritizing the associated one (if any).
36 bool refs(const RefsRequest &Req,
37 llvm::function_ref<void(const Ref &)> Callback) const override;
38
39 /// Queries only the associates index when Req.RestrictForCodeCompletion is
40 /// set, otherwise queries all.
41 bool
42 fuzzyFind(const FuzzyFindRequest &Req,
43 llvm::function_ref<void(const Symbol &)> Callback) const override;
44
45 /// Query all indexes while prioritizing the associated one (if any).
46 void relations(const RelationsRequest &Req,
47 llvm::function_ref<void(const SymbolID &, const Symbol &)>
48 Callback) const override;
49
50 llvm::unique_function<IndexContents(llvm::StringRef) const>
51 indexedFiles() const override;
52
53 ProjectAwareIndex(IndexFactory Gen, bool Sync) : Gen(std::move(Gen)) {
54 if (!Sync)
55 Tasks = std::make_unique<AsyncTaskRunner>();
56 }
57
58private:
59 // Returns the index associated with current context, if any.
60 SymbolIndex *getIndex() const;
61
62 // Storage for all the external indexes.
63 mutable std::mutex Mu;
64 mutable llvm::DenseMap<Config::ExternalIndexSpec,
65 std::unique_ptr<SymbolIndex>>
66 IndexForSpec;
67 mutable std::unique_ptr<AsyncTaskRunner> Tasks;
68
69 const IndexFactory Gen;
70};
71
72size_t ProjectAwareIndex::estimateMemoryUsage() const {
73 size_t Total = 0;
74 std::lock_guard<std::mutex> Lock(Mu);
75 for (auto &Entry : IndexForSpec)
76 Total += Entry.second->estimateMemoryUsage();
77 return Total;
78}
79
80void ProjectAwareIndex::lookup(
81 const LookupRequest &Req,
82 llvm::function_ref<void(const Symbol &)> Callback) const {
83 trace::Span Tracer("ProjectAwareIndex::lookup");
84 if (auto *Idx = getIndex())
85 Idx->lookup(Req, Callback);
86}
87
88bool ProjectAwareIndex::refs(
89 const RefsRequest &Req,
90 llvm::function_ref<void(const Ref &)> Callback) const {
91 trace::Span Tracer("ProjectAwareIndex::refs");
92 if (auto *Idx = getIndex())
93 return Idx->refs(Req, Callback);
94 return false;
95}
96
97bool ProjectAwareIndex::fuzzyFind(
98 const FuzzyFindRequest &Req,
99 llvm::function_ref<void(const Symbol &)> Callback) const {
100 trace::Span Tracer("ProjectAwareIndex::fuzzyFind");
101 if (auto *Idx = getIndex())
102 return Idx->fuzzyFind(Req, Callback);
103 return false;
104}
105
106void ProjectAwareIndex::relations(
107 const RelationsRequest &Req,
108 llvm::function_ref<void(const SymbolID &, const Symbol &)> Callback) const {
109 trace::Span Tracer("ProjectAwareIndex::relations");
110 if (auto *Idx = getIndex())
111 return Idx->relations(Req, Callback);
112}
113
114llvm::unique_function<IndexContents(llvm::StringRef) const>
115ProjectAwareIndex::indexedFiles() const {
116 trace::Span Tracer("ProjectAwareIndex::indexedFiles");
117 if (auto *Idx = getIndex())
118 return Idx->indexedFiles();
119 return [](llvm::StringRef) { return IndexContents::None; };
120}
121
122SymbolIndex *ProjectAwareIndex::getIndex() const {
123 const auto &C = Config::current();
124 if (C.Index.External.Kind == Config::ExternalIndexSpec::None)
125 return nullptr;
126 const auto &External = C.Index.External;
127 std::lock_guard<std::mutex> Lock(Mu);
128 auto Entry = IndexForSpec.try_emplace(Key: External, Args: nullptr);
129 if (Entry.second)
130 Entry.first->getSecond() = Gen(External, Tasks.get());
131 return Entry.first->second.get();
132}
133} // namespace
134
135std::unique_ptr<SymbolIndex> createProjectAwareIndex(IndexFactory Gen,
136 bool Sync) {
137 assert(Gen);
138 return std::make_unique<ProjectAwareIndex>(args: std::move(Gen), args&: Sync);
139}
140} // namespace clangd
141} // namespace clang
142

source code of clang-tools-extra/clangd/index/ProjectAware.cpp