-
Notifications
You must be signed in to change notification settings - Fork 13.2k
/
Copy pathProjectAware.cpp
154 lines (134 loc) · 5.04 KB
/
ProjectAware.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===--- 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/Ref.h"
#include "index/Symbol.h"
#include "index/SymbolID.h"
#include "support/Threading.h"
#include "support/Trace.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.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;
/// Query all indexes while prioritizing the associated one (if any).
bool containedRefs(const ContainedRefsRequest &Req,
llvm::function_ref<void(const ContainedRefsResult &)>
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::containedRefs(
const ContainedRefsRequest &Req,
llvm::function_ref<void(const ContainedRefsResult &)> Callback) const {
trace::Span Tracer("ProjectAwareIndex::refersTo");
if (auto *Idx = getIndex())
return Idx->containedRefs(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