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