[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clangd / index / ProjectAware.cpp
blob2c6f8273b35d0e6651d7c6f2e05a12fe63ec2799
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 //===----------------------------------------------------------------------===//
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>
24 namespace clang {
25 namespace clangd {
26 namespace {
27 class ProjectAwareIndex : public SymbolIndex {
28 public:
29 size_t estimateMemoryUsage() const override;
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;
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;
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;
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;
50 llvm::unique_function<IndexContents(llvm::StringRef) const>
51 indexedFiles() const override;
53 ProjectAwareIndex(IndexFactory Gen, bool Sync) : Gen(std::move(Gen)) {
54 if (!Sync)
55 Tasks = std::make_unique<AsyncTaskRunner>();
58 private:
59 // Returns the index associated with current context, if any.
60 SymbolIndex *getIndex() const;
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;
69 const IndexFactory Gen;
72 size_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;
80 void 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);
88 bool 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;
97 bool 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;
106 void 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);
114 llvm::unique_function<IndexContents(llvm::StringRef) const>
115 ProjectAwareIndex::indexedFiles() const {
116 trace::Span Tracer("ProjectAwareIndex::indexedFiles");
117 if (auto *Idx = getIndex())
118 return Idx->indexedFiles();
119 return [](llvm::StringRef) { return IndexContents::None; };
122 SymbolIndex *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(External, nullptr);
129 if (Entry.second)
130 Entry.first->getSecond() = Gen(External, Tasks.get());
131 return Entry.first->second.get();
133 } // namespace
135 std::unique_ptr<SymbolIndex> createProjectAwareIndex(IndexFactory Gen,
136 bool Sync) {
137 assert(Gen);
138 return std::make_unique<ProjectAwareIndex>(std::move(Gen), Sync);
140 } // namespace clangd
141 } // namespace clang