1 //===--- MemIndex.h - Dynamic in-memory symbol index. -------------- 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_MEMINDEX_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_MEMINDEX_H 11 12 #include "index/Index.h" 13 #include "llvm/ADT/StringSet.h" 14 #include <mutex> 15 16 namespace clang { 17 namespace clangd { 18 19 /// MemIndex is a naive in-memory index suitable for a small set of symbols. 20 class MemIndex : public SymbolIndex { 21 public: 22 MemIndex() = default; 23 // All symbols and refs must outlive this index. 24 template <typename SymbolRange, typename RefRange, typename RelationRange> 25 MemIndex(SymbolRange &&Symbols, RefRange &&Refs, RelationRange &&Relations) { 26 for (const Symbol &S : Symbols) 27 Index[S.ID] = &S; 28 for (const std::pair<SymbolID, llvm::ArrayRef<Ref>> &R : Refs) 29 this->Refs.try_emplace(R.first, R.second.begin(), R.second.end()); 30 for (const Relation &R : Relations) 31 this->Relations[std::make_pair(R.Subject, 32 static_cast<uint8_t>(R.Predicate))] 33 .push_back(R.Object); 34 } 35 // Symbols are owned by BackingData, Index takes ownership. 36 template <typename SymbolRange, typename RefRange, typename RelationRange, 37 typename Payload> 38 MemIndex(SymbolRange &&Symbols, RefRange &&Refs, RelationRange &&Relations, 39 Payload &&BackingData, size_t BackingDataSize) 40 : MemIndex(std::forward<SymbolRange>(Symbols), 41 std::forward<RefRange>(Refs), 42 std::forward<RelationRange>(Relations)) { 43 KeepAlive = std::shared_ptr<void>( 44 std::make_shared<Payload>(std::move(BackingData)), nullptr); 45 this->BackingDataSize = BackingDataSize; 46 } 47 48 template <typename SymbolRange, typename RefRange, typename RelationRange, 49 typename FileRange, typename Payload> 50 MemIndex(SymbolRange &&Symbols, RefRange &&Refs, RelationRange &&Relations, 51 FileRange &&Files, IndexContents IdxContents, Payload &&BackingData, 52 size_t BackingDataSize) 53 : MemIndex(std::forward<SymbolRange>(Symbols), 54 std::forward<RefRange>(Refs), 55 std::forward<RelationRange>(Relations), 56 std::forward<Payload>(BackingData), BackingDataSize) { 57 this->Files = std::forward<FileRange>(Files); 58 this->IdxContents = IdxContents; 59 } 60 61 /// Builds an index from slabs. The index takes ownership of the data. 62 static std::unique_ptr<SymbolIndex> build(SymbolSlab Symbols, RefSlab Refs, 63 RelationSlab Relations); 64 65 bool 66 fuzzyFind(const FuzzyFindRequest &Req, 67 llvm::function_ref<void(const Symbol &)> Callback) const override; 68 69 void lookup(const LookupRequest &Req, 70 llvm::function_ref<void(const Symbol &)> Callback) const override; 71 72 bool refs(const RefsRequest &Req, 73 llvm::function_ref<void(const Ref &)> Callback) const override; 74 75 bool containedRefs(const ContainedRefsRequest &Req, 76 llvm::function_ref<void(const ContainedRefsResult &)> 77 Callback) const override; 78 79 void relations(const RelationsRequest &Req, 80 llvm::function_ref<void(const SymbolID &, const Symbol &)> 81 Callback) const override; 82 83 llvm::unique_function<IndexContents(llvm::StringRef) const> 84 indexedFiles() const override; 85 86 size_t estimateMemoryUsage() const override; 87 88 private: 89 // Index is a set of symbols that are deduplicated by symbol IDs. 90 llvm::DenseMap<SymbolID, const Symbol *> Index; 91 // A map from symbol ID to symbol refs, support query by IDs. 92 llvm::DenseMap<SymbolID, llvm::ArrayRef<Ref>> Refs; 93 // A map from (subject, predicate) pair to objects. 94 static_assert(sizeof(RelationKind) == sizeof(uint8_t), 95 "RelationKind should be of same size as a uint8_t"); 96 llvm::DenseMap<std::pair<SymbolID, uint8_t>, std::vector<SymbolID>> Relations; 97 // Set of files which were used during this index build. 98 llvm::StringSet<> Files; 99 // Contents of the index (symbols, references, etc.) 100 IndexContents IdxContents = IndexContents::None; 101 std::shared_ptr<void> KeepAlive; // poor man's move-only std::any 102 // Size of memory retained by KeepAlive. 103 size_t BackingDataSize = 0; 104 }; 105 106 } // namespace clangd 107 } // namespace clang 108 109 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_MEMINDEX_H 110