Line data Source code
1 : //===--- Index.h -------------------------------------------------*- C++-*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
11 : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
12 :
13 : #include "clang/Index/IndexSymbol.h"
14 : #include "clang/Lex/Lexer.h"
15 : #include "llvm/ADT/DenseMap.h"
16 : #include "llvm/ADT/DenseSet.h"
17 : #include "llvm/ADT/Hashing.h"
18 : #include "llvm/ADT/Optional.h"
19 : #include "llvm/ADT/SmallVector.h"
20 : #include "llvm/ADT/StringExtras.h"
21 : #include "llvm/ADT/StringRef.h"
22 : #include "llvm/Support/JSON.h"
23 : #include "llvm/Support/StringSaver.h"
24 : #include <array>
25 : #include <limits>
26 : #include <mutex>
27 : #include <string>
28 : #include <tuple>
29 :
30 : namespace clang {
31 : namespace clangd {
32 :
33 : struct SymbolLocation {
34 : // Specify a position (Line, Column) of symbol. Using Line/Column allows us to
35 : // build LSP responses without reading the file content.
36 : //
37 : // Position is encoded into 32 bits to save space.
38 : // If Line/Column overflow, the value will be their maximum value.
39 : struct Position {
40 : void setLine(uint32_t Line);
41 0 : uint32_t line() const { return Line; }
42 : void setColumn(uint32_t Column);
43 0 : uint32_t column() const { return Column; }
44 :
45 : static constexpr uint32_t MaxLine = (1 << 20) - 1;
46 : static constexpr uint32_t MaxColumn = (1 << 12) - 1;
47 :
48 : // Clients should use getters and setters to access these members.
49 : // FIXME: hide these members.
50 : uint32_t Line : 20; // 0-based
51 : // Using UTF-16 code units.
52 : uint32_t Column : 12; // 0-based
53 : };
54 :
55 : // The URI of the source file where a symbol occurs.
56 : llvm::StringRef FileURI;
57 :
58 : /// The symbol range, using half-open range [Start, End).
59 : Position Start;
60 : Position End;
61 :
62 : explicit operator bool() const { return !FileURI.empty(); }
63 : };
64 : inline bool operator==(const SymbolLocation::Position &L,
65 : const SymbolLocation::Position &R) {
66 : return std::make_tuple(L.line(), L.column()) ==
67 : std::make_tuple(R.line(), R.column());
68 : }
69 : inline bool operator<(const SymbolLocation::Position &L,
70 : const SymbolLocation::Position &R) {
71 : return std::make_tuple(L.line(), L.column()) <
72 : std::make_tuple(R.line(), R.column());
73 : }
74 : inline bool operator==(const SymbolLocation &L, const SymbolLocation &R) {
75 : return std::tie(L.FileURI, L.Start, L.End) ==
76 : std::tie(R.FileURI, R.Start, R.End);
77 : }
78 : inline bool operator<(const SymbolLocation &L, const SymbolLocation &R) {
79 : return std::tie(L.FileURI, L.Start, L.End) <
80 : std::tie(R.FileURI, R.Start, R.End);
81 : }
82 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SymbolLocation &);
83 :
84 : // The class identifies a particular C++ symbol (class, function, method, etc).
85 : //
86 : // As USRs (Unified Symbol Resolution) could be large, especially for functions
87 : // with long type arguments, SymbolID is using 160-bits SHA1(USR) values to
88 : // guarantee the uniqueness of symbols while using a relatively small amount of
89 : // memory (vs storing USRs directly).
90 : //
91 : // SymbolID can be used as key in the symbol indexes to lookup the symbol.
92 : class SymbolID {
93 : public:
94 : SymbolID() = default;
95 : explicit SymbolID(llvm::StringRef USR);
96 :
97 : bool operator==(const SymbolID &Sym) const {
98 : return HashValue == Sym.HashValue;
99 : }
100 : bool operator<(const SymbolID &Sym) const {
101 : return HashValue < Sym.HashValue;
102 : }
103 :
104 : constexpr static size_t RawSize = 20;
105 : llvm::StringRef raw() const {
106 : return StringRef(reinterpret_cast<const char *>(HashValue.data()), RawSize);
107 : }
108 : static SymbolID fromRaw(llvm::StringRef);
109 :
110 : // Returns a 40-bytes hex encoded string.
111 : std::string str() const;
112 : static llvm::Expected<SymbolID> fromStr(llvm::StringRef);
113 :
114 : private:
115 : std::array<uint8_t, RawSize> HashValue;
116 : };
117 :
118 : inline llvm::hash_code hash_value(const SymbolID &ID) {
119 : // We already have a good hash, just return the first bytes.
120 : assert(sizeof(size_t) <= SymbolID::RawSize && "size_t longer than SHA1!");
121 : size_t Result;
122 0 : memcpy(&Result, ID.raw().data(), sizeof(size_t));
123 : return llvm::hash_code(Result);
124 : }
125 :
126 : // Write SymbolID into the given stream. SymbolID is encoded as ID.str().
127 : llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID);
128 :
129 : } // namespace clangd
130 : } // namespace clang
131 : namespace llvm {
132 : // Support SymbolIDs as DenseMap keys.
133 : template <> struct DenseMapInfo<clang::clangd::SymbolID> {
134 0 : static inline clang::clangd::SymbolID getEmptyKey() {
135 0 : static clang::clangd::SymbolID EmptyKey("EMPTYKEY");
136 0 : return EmptyKey;
137 : }
138 0 : static inline clang::clangd::SymbolID getTombstoneKey() {
139 0 : static clang::clangd::SymbolID TombstoneKey("TOMBSTONEKEY");
140 0 : return TombstoneKey;
141 : }
142 : static unsigned getHashValue(const clang::clangd::SymbolID &Sym) {
143 0 : return hash_value(Sym);
144 : }
145 : static bool isEqual(const clang::clangd::SymbolID &LHS,
146 : const clang::clangd::SymbolID &RHS) {
147 : return LHS == RHS;
148 : }
149 : };
150 : } // namespace llvm
151 : namespace clang {
152 : namespace clangd {
153 :
154 : // Describes the source of information about a symbol.
155 : // Mainly useful for debugging, e.g. understanding code completion reuslts.
156 : // This is a bitfield as information can be combined from several sources.
157 : enum class SymbolOrigin : uint8_t {
158 : Unknown = 0,
159 : AST = 1 << 0, // Directly from the AST (indexes should not set this).
160 : Dynamic = 1 << 1, // From the dynamic index of opened files.
161 : Static = 1 << 2, // From the static, externally-built index.
162 : Merge = 1 << 3, // A non-trivial index merge was performed.
163 : // Remaining bits reserved for index implementations.
164 : };
165 : inline SymbolOrigin operator|(SymbolOrigin A, SymbolOrigin B) {
166 : return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) |
167 : static_cast<uint8_t>(B));
168 : }
169 : inline SymbolOrigin &operator|=(SymbolOrigin &A, SymbolOrigin B) {
170 : return A = A | B;
171 : }
172 : inline SymbolOrigin operator&(SymbolOrigin A, SymbolOrigin B) {
173 : return static_cast<SymbolOrigin>(static_cast<uint8_t>(A) &
174 : static_cast<uint8_t>(B));
175 : }
176 : raw_ostream &operator<<(raw_ostream &, SymbolOrigin);
177 :
178 : // The class presents a C++ symbol, e.g. class, function.
179 : //
180 : // WARNING: Symbols do not own much of their underlying data - typically strings
181 : // are owned by a SymbolSlab. They should be treated as non-owning references.
182 : // Copies are shallow.
183 : // When adding new unowned data fields to Symbol, remember to update:
184 : // - SymbolSlab::Builder in Index.cpp, to copy them to the slab's storage.
185 : // - mergeSymbol in Merge.cpp, to properly combine two Symbols.
186 : //
187 : // A fully documented symbol can be split as:
188 : // size_type std::map<k, t>::count(const K& key) const
189 : // | Return | Scope |Name| Signature |
190 : // We split up these components to allow display flexibility later.
191 0 : struct Symbol {
192 : // The ID of the symbol.
193 : SymbolID ID;
194 : // The symbol information, like symbol kind.
195 : index::SymbolInfo SymInfo;
196 : // The unqualified name of the symbol, e.g. "bar" (for ns::bar).
197 : llvm::StringRef Name;
198 : // The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
199 : llvm::StringRef Scope;
200 : // The location of the symbol's definition, if one was found.
201 : // This just covers the symbol name (e.g. without class/function body).
202 : SymbolLocation Definition;
203 : // The location of the preferred declaration of the symbol.
204 : // This just covers the symbol name.
205 : // This may be the same as Definition.
206 : //
207 : // A C++ symbol may have multiple declarations, and we pick one to prefer.
208 : // * For classes, the canonical declaration should be the definition.
209 : // * For non-inline functions, the canonical declaration typically appears
210 : // in the ".h" file corresponding to the definition.
211 : SymbolLocation CanonicalDeclaration;
212 : // The number of translation units that reference this symbol from their main
213 : // file. This number is only meaningful if aggregated in an index.
214 : unsigned References = 0;
215 : /// Where this symbol came from. Usually an index provides a constant value.
216 : SymbolOrigin Origin = SymbolOrigin::Unknown;
217 : /// A brief description of the symbol that can be appended in the completion
218 : /// candidate list. For example, "(X x, Y y) const" is a function signature.
219 : llvm::StringRef Signature;
220 : /// What to insert when completing this symbol, after the symbol name.
221 : /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function).
222 : /// (When snippets are disabled, the symbol name alone is used).
223 : llvm::StringRef CompletionSnippetSuffix;
224 : /// Documentation including comment for the symbol declaration.
225 : llvm::StringRef Documentation;
226 : /// Type when this symbol is used in an expression. (Short display form).
227 : /// e.g. return type of a function, or type of a variable.
228 : llvm::StringRef ReturnType;
229 :
230 : struct IncludeHeaderWithReferences {
231 : IncludeHeaderWithReferences() = default;
232 :
233 : IncludeHeaderWithReferences(llvm::StringRef IncludeHeader,
234 : unsigned References)
235 0 : : IncludeHeader(IncludeHeader), References(References) {}
236 :
237 : /// This can be either a URI of the header to be #include'd
238 : /// for this symbol, or a literal header quoted with <> or "" that is
239 : /// suitable to be included directly. When it is a URI, the exact #include
240 : /// path needs to be calculated according to the URI scheme.
241 : ///
242 : /// Note that the include header is a canonical include for the symbol and
243 : /// can be different from FileURI in the CanonicalDeclaration.
244 : llvm::StringRef IncludeHeader = "";
245 : /// The number of translation units that reference this symbol and include
246 : /// this header. This number is only meaningful if aggregated in an index.
247 : unsigned References = 0;
248 : };
249 : /// One Symbol can potentially be incuded via different headers.
250 : /// - If we haven't seen a definition, this covers all declarations.
251 : /// - If we have seen a definition, this covers declarations visible from
252 : /// any definition.
253 : llvm::SmallVector<IncludeHeaderWithReferences, 1> IncludeHeaders;
254 :
255 : enum SymbolFlag : uint8_t {
256 : None = 0,
257 : /// Whether or not this symbol is meant to be used for the code completion.
258 : /// See also isIndexedForCodeCompletion().
259 : IndexedForCodeCompletion = 1 << 0,
260 : /// Indicates if the symbol is deprecated.
261 : Deprecated = 1 << 1,
262 : // Symbol is an implementation detail.
263 : ImplementationDetail = 1 << 2,
264 : };
265 :
266 : SymbolFlag Flags = SymbolFlag::None;
267 : /// FIXME: also add deprecation message and fixit?
268 : };
269 : inline Symbol::SymbolFlag operator|(Symbol::SymbolFlag A, Symbol::SymbolFlag B) {
270 : return static_cast<Symbol::SymbolFlag>(static_cast<uint8_t>(A) |
271 0 : static_cast<uint8_t>(B));
272 : }
273 : inline Symbol::SymbolFlag &operator|=(Symbol::SymbolFlag &A, Symbol::SymbolFlag B) {
274 0 : return A = A | B;
275 : }
276 : llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
277 : raw_ostream &operator<<(raw_ostream &, Symbol::SymbolFlag);
278 :
279 : // Invokes Callback with each StringRef& contained in the Symbol.
280 : // Useful for deduplicating backing strings.
281 : template <typename Callback> void visitStrings(Symbol &S, const Callback &CB) {
282 : CB(S.Name);
283 : CB(S.Scope);
284 : CB(S.CanonicalDeclaration.FileURI);
285 : CB(S.Definition.FileURI);
286 : CB(S.Signature);
287 : CB(S.CompletionSnippetSuffix);
288 : CB(S.Documentation);
289 : CB(S.ReturnType);
290 : for (auto &Include : S.IncludeHeaders)
291 : CB(Include.IncludeHeader);
292 : }
293 :
294 : // Computes query-independent quality score for a Symbol.
295 : // This currently falls in the range [1, ln(#indexed documents)].
296 : // FIXME: this should probably be split into symbol -> signals
297 : // and signals -> score, so it can be reused for Sema completions.
298 : float quality(const Symbol &S);
299 :
300 : // An immutable symbol container that stores a set of symbols.
301 : // The container will maintain the lifetime of the symbols.
302 0 : class SymbolSlab {
303 : public:
304 : using const_iterator = std::vector<Symbol>::const_iterator;
305 : using iterator = const_iterator;
306 : using value_type = Symbol;
307 :
308 : SymbolSlab() = default;
309 :
310 0 : const_iterator begin() const { return Symbols.begin(); }
311 0 : const_iterator end() const { return Symbols.end(); }
312 : const_iterator find(const SymbolID &SymID) const;
313 :
314 0 : size_t size() const { return Symbols.size(); }
315 : bool empty() const { return Symbols.empty(); }
316 : // Estimates the total memory usage.
317 : size_t bytes() const {
318 : return sizeof(*this) + Arena.getTotalMemory() +
319 : Symbols.capacity() * sizeof(Symbol);
320 : }
321 :
322 : // SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
323 : // The frozen SymbolSlab will use less memory.
324 : class Builder {
325 : public:
326 0 : Builder() : UniqueStrings(Arena) {}
327 :
328 : // Adds a symbol, overwriting any existing one with the same ID.
329 : // This is a deep copy: underlying strings will be owned by the slab.
330 : void insert(const Symbol &S);
331 :
332 : // Returns the symbol with an ID, if it exists. Valid until next insert().
333 0 : const Symbol *find(const SymbolID &ID) {
334 0 : auto I = SymbolIndex.find(ID);
335 0 : return I == SymbolIndex.end() ? nullptr : &Symbols[I->second];
336 : }
337 :
338 : // Consumes the builder to finalize the slab.
339 : SymbolSlab build() &&;
340 :
341 : private:
342 : llvm::BumpPtrAllocator Arena;
343 : // Intern table for strings. Contents are on the arena.
344 : llvm::UniqueStringSaver UniqueStrings;
345 : std::vector<Symbol> Symbols;
346 : // Values are indices into Symbols vector.
347 : llvm::DenseMap<SymbolID, size_t> SymbolIndex;
348 : };
349 :
350 : private:
351 : SymbolSlab(llvm::BumpPtrAllocator Arena, std::vector<Symbol> Symbols)
352 : : Arena(std::move(Arena)), Symbols(std::move(Symbols)) {}
353 :
354 : llvm::BumpPtrAllocator Arena; // Owns Symbol data that the Symbols do not.
355 : std::vector<Symbol> Symbols; // Sorted by SymbolID to allow lookup.
356 : };
357 :
358 : // Describes the kind of a cross-reference.
359 : //
360 : // This is a bitfield which can be combined from different kinds.
361 : enum class RefKind : uint8_t {
362 : Unknown = 0,
363 : Declaration = static_cast<uint8_t>(index::SymbolRole::Declaration),
364 : Definition = static_cast<uint8_t>(index::SymbolRole::Definition),
365 : Reference = static_cast<uint8_t>(index::SymbolRole::Reference),
366 : All = Declaration | Definition | Reference,
367 : };
368 : inline RefKind operator|(RefKind L, RefKind R) {
369 : return static_cast<RefKind>(static_cast<uint8_t>(L) |
370 : static_cast<uint8_t>(R));
371 : }
372 : inline RefKind &operator|=(RefKind &L, RefKind R) { return L = L | R; }
373 : inline RefKind operator&(RefKind A, RefKind B) {
374 : return static_cast<RefKind>(static_cast<uint8_t>(A) &
375 : static_cast<uint8_t>(B));
376 : }
377 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, RefKind);
378 :
379 : // Represents a symbol occurrence in the source file.
380 : // Despite the name, it could be a declaration/definition/reference.
381 : //
382 : // WARNING: Location does not own the underlying data - Copies are shallow.
383 : struct Ref {
384 : // The source location where the symbol is named.
385 : SymbolLocation Location;
386 : RefKind Kind = RefKind::Unknown;
387 : };
388 : inline bool operator<(const Ref &L, const Ref &R) {
389 : return std::tie(L.Location, L.Kind) < std::tie(R.Location, R.Kind);
390 : }
391 : inline bool operator==(const Ref &L, const Ref &R) {
392 : return std::tie(L.Location, L.Kind) == std::tie(R.Location, R.Kind);
393 : }
394 : llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Ref &);
395 :
396 : // An efficient structure of storing large set of symbol references in memory.
397 : // Filenames are deduplicated.
398 0 : class RefSlab {
399 : public:
400 : using value_type = std::pair<SymbolID, llvm::ArrayRef<Ref>>;
401 : using const_iterator = std::vector<value_type>::const_iterator;
402 : using iterator = const_iterator;
403 :
404 0 : RefSlab() = default;
405 0 : RefSlab(RefSlab &&Slab) = default;
406 : RefSlab &operator=(RefSlab &&RHS) = default;
407 :
408 0 : const_iterator begin() const { return Refs.begin(); }
409 0 : const_iterator end() const { return Refs.end(); }
410 : /// Gets the number of symbols.
411 : size_t size() const { return Refs.size(); }
412 : size_t numRefs() const { return NumRefs; }
413 : bool empty() const { return Refs.empty(); }
414 :
415 : size_t bytes() const {
416 : return sizeof(*this) + Arena.getTotalMemory() +
417 : sizeof(value_type) * Refs.size();
418 : }
419 :
420 : // RefSlab::Builder is a mutable container that can 'freeze' to RefSlab.
421 : class Builder {
422 : public:
423 0 : Builder() : UniqueStrings(Arena) {}
424 : // Adds a ref to the slab. Deep copy: Strings will be owned by the slab.
425 : void insert(const SymbolID &ID, const Ref &S);
426 : // Consumes the builder to finalize the slab.
427 : RefSlab build() &&;
428 :
429 : private:
430 : llvm::BumpPtrAllocator Arena;
431 : llvm::UniqueStringSaver UniqueStrings; // Contents on the arena.
432 : llvm::DenseMap<SymbolID, std::vector<Ref>> Refs;
433 : };
434 :
435 : private:
436 : RefSlab(std::vector<value_type> Refs, llvm::BumpPtrAllocator Arena,
437 : size_t NumRefs)
438 : : Arena(std::move(Arena)), Refs(std::move(Refs)), NumRefs(NumRefs) {}
439 :
440 : llvm::BumpPtrAllocator Arena;
441 : std::vector<value_type> Refs;
442 : // Number of all references.
443 : size_t NumRefs = 0;
444 : };
445 :
446 0 : struct FuzzyFindRequest {
447 : /// \brief A query string for the fuzzy find. This is matched against symbols'
448 : /// un-qualified identifiers and should not contain qualifiers like "::".
449 : std::string Query;
450 : /// \brief If this is non-empty, symbols must be in at least one of the scopes
451 : /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::"
452 : /// is provided, the matched symbols must be defined in namespace xyz but not
453 : /// namespace xyz::abc.
454 : ///
455 : /// The global scope is "", a top level scope is "foo::", etc.
456 : /// FIXME: drop the special case for empty list, which is the same as
457 : /// `AnyScope = true`.
458 : /// FIXME: support scope proximity.
459 : std::vector<std::string> Scopes;
460 : /// If set to true, allow symbols from any scope. Scopes explicitly listed
461 : /// above will be ranked higher.
462 : bool AnyScope = false;
463 : /// \brief The number of top candidates to return. The index may choose to
464 : /// return more than this, e.g. if it doesn't know which candidates are best.
465 : llvm::Optional<uint32_t> Limit;
466 : /// If set to true, only symbols for completion support will be considered.
467 : bool RestrictForCodeCompletion = false;
468 : /// Contextually relevant files (e.g. the file we're code-completing in).
469 : /// Paths should be absolute.
470 : std::vector<std::string> ProximityPaths;
471 :
472 0 : bool operator==(const FuzzyFindRequest &Req) const {
473 0 : return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion,
474 0 : ProximityPaths) ==
475 0 : std::tie(Req.Query, Req.Scopes, Req.Limit,
476 0 : Req.RestrictForCodeCompletion, Req.ProximityPaths);
477 : }
478 : bool operator!=(const FuzzyFindRequest &Req) const { return !(*this == Req); }
479 : };
480 : bool fromJSON(const llvm::json::Value &Value, FuzzyFindRequest &Request);
481 : llvm::json::Value toJSON(const FuzzyFindRequest &Request);
482 :
483 : struct LookupRequest {
484 : llvm::DenseSet<SymbolID> IDs;
485 : };
486 :
487 0 : struct RefsRequest {
488 : llvm::DenseSet<SymbolID> IDs;
489 : RefKind Filter = RefKind::All;
490 : };
491 :
492 : /// Interface for symbol indexes that can be used for searching or
493 : /// matching symbols among a set of symbols based on names or unique IDs.
494 : class SymbolIndex {
495 : public:
496 0 : virtual ~SymbolIndex() = default;
497 :
498 : /// \brief Matches symbols in the index fuzzily and applies \p Callback on
499 : /// each matched symbol before returning.
500 : /// If returned Symbols are used outside Callback, they must be deep-copied!
501 : ///
502 : /// Returns true if there may be more results (limited by Req.Limit).
503 : virtual bool
504 : fuzzyFind(const FuzzyFindRequest &Req,
505 : llvm::function_ref<void(const Symbol &)> Callback) const = 0;
506 :
507 : /// Looks up symbols with any of the given symbol IDs and applies \p Callback
508 : /// on each matched symbol.
509 : /// The returned symbol must be deep-copied if it's used outside Callback.
510 : virtual void
511 : lookup(const LookupRequest &Req,
512 : llvm::function_ref<void(const Symbol &)> Callback) const = 0;
513 :
514 : /// Finds all occurrences (e.g. references, declarations, definitions) of a
515 : /// symbol and applies \p Callback on each result.
516 : ///
517 : /// Results should be returned in arbitrary order.
518 : /// The returned result must be deep-copied if it's used outside Callback.
519 : virtual void refs(const RefsRequest &Req,
520 : llvm::function_ref<void(const Ref &)> Callback) const = 0;
521 :
522 : /// Returns estimated size of index (in bytes).
523 : // FIXME(kbobyrev): Currently, this only returns the size of index itself
524 : // excluding the size of actual symbol slab index refers to. We should include
525 : // both.
526 : virtual size_t estimateMemoryUsage() const = 0;
527 : };
528 :
529 : // Delegating implementation of SymbolIndex whose delegate can be swapped out.
530 0 : class SwapIndex : public SymbolIndex {
531 : public:
532 : // If an index is not provided, reset() must be called.
533 : SwapIndex(std::unique_ptr<SymbolIndex> Index = nullptr)
534 0 : : Index(std::move(Index)) {}
535 : void reset(std::unique_ptr<SymbolIndex>);
536 :
537 : // SymbolIndex methods delegate to the current index, which is kept alive
538 : // until the call returns (even if reset() is called).
539 : bool fuzzyFind(const FuzzyFindRequest &,
540 : llvm::function_ref<void(const Symbol &)>) const override;
541 : void lookup(const LookupRequest &,
542 : llvm::function_ref<void(const Symbol &)>) const override;
543 : void refs(const RefsRequest &,
544 : llvm::function_ref<void(const Ref &)>) const override;
545 : size_t estimateMemoryUsage() const override;
546 :
547 : private:
548 : std::shared_ptr<SymbolIndex> snapshot() const;
549 : mutable std::mutex Mutex;
550 : std::shared_ptr<SymbolIndex> Index;
551 : };
552 :
553 : } // namespace clangd
554 : } // namespace clang
555 :
556 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
|