1 //===--- SymbolID.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_SYMBOLID_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H 11 12 #include "llvm/ADT/DenseMap.h" 13 #include "llvm/ADT/Hashing.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/raw_ostream.h" 17 #include <array> 18 #include <cstdint> 19 #include <string> 20 21 namespace clang { 22 namespace clangd { 23 24 // The class identifies a particular C++ symbol (class, function, method, etc). 25 // 26 // As USRs (Unified Symbol Resolution) could be large, especially for functions 27 // with long type arguments, SymbolID is using truncated SHA1(USR) values to 28 // guarantee the uniqueness of symbols while using a relatively small amount of 29 // memory (vs storing USRs directly). 30 // 31 // SymbolID can be used as key in the symbol indexes to lookup the symbol. 32 class SymbolID { 33 public: 34 SymbolID() = default; 35 explicit SymbolID(llvm::StringRef USR); 36 37 bool operator==(const SymbolID &Sym) const { 38 return HashValue == Sym.HashValue; 39 } 40 bool operator!=(const SymbolID &Sym) const { 41 return !(*this == Sym); 42 } 43 bool operator<(const SymbolID &Sym) const { 44 return HashValue < Sym.HashValue; 45 } 46 47 // The stored hash is truncated to RawSize bytes. 48 // This trades off memory against the number of symbols we can handle. 49 constexpr static size_t RawSize = 8; 50 llvm::StringRef raw() const; 51 static SymbolID fromRaw(llvm::StringRef); 52 53 // Returns a hex encoded string. 54 std::string str() const; 55 static llvm::Expected<SymbolID> fromStr(llvm::StringRef); 56 isNull()57 bool isNull() const { return *this == SymbolID(); } 58 explicit operator bool() const { return !isNull(); } 59 60 private: 61 std::array<uint8_t, RawSize> HashValue{}; 62 }; 63 64 llvm::hash_code hash_value(const SymbolID &ID); 65 66 // Write SymbolID into the given stream. SymbolID is encoded as ID.str(). 67 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID); 68 69 } // namespace clangd 70 } // namespace clang 71 72 namespace llvm { 73 // Support SymbolIDs as DenseMap keys. 74 template <> struct DenseMapInfo<clang::clangd::SymbolID> { 75 static inline clang::clangd::SymbolID getEmptyKey() { 76 static clang::clangd::SymbolID EmptyKey("EMPTYKEY"); 77 return EmptyKey; 78 } 79 static inline clang::clangd::SymbolID getTombstoneKey() { 80 static clang::clangd::SymbolID TombstoneKey("TOMBSTONEKEY"); 81 return TombstoneKey; 82 } 83 static unsigned getHashValue(const clang::clangd::SymbolID &Sym) { 84 return hash_value(Sym); 85 } 86 static bool isEqual(const clang::clangd::SymbolID &LHS, 87 const clang::clangd::SymbolID &RHS) { 88 return LHS == RHS; 89 } 90 }; 91 } // namespace llvm 92 93 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOLID_H 94