LCOV - code coverage report
Current view: top level - clang/tools/extra/clangd/index - Index.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 0 38 0.0 %
Date: 2018-10-20 13:21:21 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.13