1 //===--- Index.h -------------------------------------------------*- 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_INDEX_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H 11 12 #include "Ref.h" 13 #include "Relation.h" 14 #include "Symbol.h" 15 #include "SymbolID.h" 16 #include "llvm/ADT/DenseSet.h" 17 #include "llvm/ADT/Optional.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/Support/JSON.h" 20 #include <mutex> 21 #include <string> 22 23 namespace clang { 24 namespace clangd { 25 26 struct FuzzyFindRequest { 27 /// A query string for the fuzzy find. This is matched against symbols' 28 /// un-qualified identifiers and should not contain qualifiers like "::". 29 std::string Query; 30 /// If this is non-empty, symbols must be in at least one of the scopes 31 /// (e.g. namespaces) excluding nested scopes. For example, if a scope "xyz::" 32 /// is provided, the matched symbols must be defined in namespace xyz but not 33 /// namespace xyz::abc. 34 /// 35 /// The global scope is "", a top level scope is "foo::", etc. 36 std::vector<std::string> Scopes; 37 /// If set to true, allow symbols from any scope. Scopes explicitly listed 38 /// above will be ranked higher. 39 bool AnyScope = false; 40 /// The number of top candidates to return. The index may choose to 41 /// return more than this, e.g. if it doesn't know which candidates are best. 42 llvm::Optional<uint32_t> Limit; 43 /// If set to true, only symbols for completion support will be considered. 44 bool RestrictForCodeCompletion = false; 45 /// Contextually relevant files (e.g. the file we're code-completing in). 46 /// Paths should be absolute. 47 std::vector<std::string> ProximityPaths; 48 /// Preferred types of symbols. These are raw representation of `OpaqueType`. 49 std::vector<std::string> PreferredTypes; 50 51 bool operator==(const FuzzyFindRequest &Req) const { 52 return std::tie(Query, Scopes, Limit, RestrictForCodeCompletion, 53 ProximityPaths, PreferredTypes) == 54 std::tie(Req.Query, Req.Scopes, Req.Limit, 55 Req.RestrictForCodeCompletion, Req.ProximityPaths, 56 Req.PreferredTypes); 57 } 58 bool operator!=(const FuzzyFindRequest &Req) const { return !(*this == Req); } 59 }; 60 bool fromJSON(const llvm::json::Value &Value, FuzzyFindRequest &Request); 61 llvm::json::Value toJSON(const FuzzyFindRequest &Request); 62 63 struct LookupRequest { 64 llvm::DenseSet<SymbolID> IDs; 65 }; 66 67 struct RefsRequest { 68 llvm::DenseSet<SymbolID> IDs; 69 RefKind Filter = RefKind::All; 70 /// If set, limit the number of refers returned from the index. The index may 71 /// choose to return less than this, e.g. it tries to avoid returning stale 72 /// results. 73 llvm::Optional<uint32_t> Limit; 74 }; 75 76 struct RelationsRequest { 77 llvm::DenseSet<SymbolID> Subjects; 78 RelationKind Predicate; 79 /// If set, limit the number of relations returned from the index. 80 llvm::Optional<uint32_t> Limit; 81 }; 82 83 /// Interface for symbol indexes that can be used for searching or 84 /// matching symbols among a set of symbols based on names or unique IDs. 85 class SymbolIndex { 86 public: 87 virtual ~SymbolIndex() = default; 88 89 /// Matches symbols in the index fuzzily and applies \p Callback on 90 /// each matched symbol before returning. 91 /// If returned Symbols are used outside Callback, they must be deep-copied! 92 /// 93 /// Returns true if there may be more results (limited by Req.Limit). 94 virtual bool 95 fuzzyFind(const FuzzyFindRequest &Req, 96 llvm::function_ref<void(const Symbol &)> Callback) const = 0; 97 98 /// Looks up symbols with any of the given symbol IDs and applies \p Callback 99 /// on each matched symbol. 100 /// The returned symbol must be deep-copied if it's used outside Callback. 101 virtual void 102 lookup(const LookupRequest &Req, 103 llvm::function_ref<void(const Symbol &)> Callback) const = 0; 104 105 /// Finds all occurrences (e.g. references, declarations, definitions) of a 106 /// symbol and applies \p Callback on each result. 107 /// 108 /// Results should be returned in arbitrary order. 109 /// The returned result must be deep-copied if it's used outside Callback. 110 /// 111 /// Returns true if there will be more results (limited by Req.Limit); 112 virtual bool refs(const RefsRequest &Req, 113 llvm::function_ref<void(const Ref &)> Callback) const = 0; 114 115 /// Finds all relations (S, P, O) stored in the index such that S is among 116 /// Req.Subjects and P is Req.Predicate, and invokes \p Callback for (S, O) in 117 /// each. 118 virtual void relations( 119 const RelationsRequest &Req, 120 llvm::function_ref<void(const SymbolID &Subject, const Symbol &Object)> 121 Callback) const = 0; 122 123 /// Returns estimated size of index (in bytes). 124 virtual size_t estimateMemoryUsage() const = 0; 125 }; 126 127 // Delegating implementation of SymbolIndex whose delegate can be swapped out. 128 class SwapIndex : public SymbolIndex { 129 public: 130 // If an index is not provided, reset() must be called. 131 SwapIndex(std::unique_ptr<SymbolIndex> Index = nullptr) Index(std::move (Index))132 : Index(std::move(Index)) {} 133 void reset(std::unique_ptr<SymbolIndex>); 134 135 // SymbolIndex methods delegate to the current index, which is kept alive 136 // until the call returns (even if reset() is called). 137 bool fuzzyFind(const FuzzyFindRequest &, 138 llvm::function_ref<void(const Symbol &)>) const override; 139 void lookup(const LookupRequest &, 140 llvm::function_ref<void(const Symbol &)>) const override; 141 bool refs(const RefsRequest &, 142 llvm::function_ref<void(const Ref &)>) const override; 143 void relations(const RelationsRequest &, 144 llvm::function_ref<void(const SymbolID &, const Symbol &)>) 145 const override; 146 147 size_t estimateMemoryUsage() const override; 148 149 private: 150 std::shared_ptr<SymbolIndex> snapshot() const; 151 mutable std::mutex Mutex; 152 std::shared_ptr<SymbolIndex> Index; 153 }; 154 155 } // namespace clangd 156 } // namespace clang 157 158 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H 159