xref: /llvm-project/clang-tools-extra/clangd/index/MemIndex.h (revision 44433147d62ef0b918c8925874a407ecec15193f)
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