clang-tools  7.0.0
Index.cpp
Go to the documentation of this file.
1 //===--- Index.cpp -----------------------------------------------*- 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 #include "Index.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/Support/SHA1.h"
13 #include "llvm/Support/raw_ostream.h"
14 
15 namespace clang {
16 namespace clangd {
17 using namespace llvm;
18 
19 raw_ostream &operator<<(raw_ostream &OS, const SymbolLocation &L) {
20  if (!L)
21  return OS << "(none)";
22  return OS << L.FileURI << "[" << L.Start.Line << ":" << L.Start.Column << "-"
23  << L.End.Line << ":" << L.End.Column << ")";
24 }
25 
26 SymbolID::SymbolID(StringRef USR)
27  : HashValue(SHA1::hash(arrayRefFromStringRef(USR))) {}
28 
29 raw_ostream &operator<<(raw_ostream &OS, const SymbolID &ID) {
30  OS << toHex(toStringRef(ID.HashValue));
31  return OS;
32 }
33 
34 std::string SymbolID::str() const {
35  std::string ID;
36  llvm::raw_string_ostream OS(ID);
37  OS << *this;
38  return OS.str();
39 }
40 
41 void operator>>(StringRef Str, SymbolID &ID) {
42  std::string HexString = fromHex(Str);
43  assert(HexString.size() == ID.HashValue.size());
44  std::copy(HexString.begin(), HexString.end(), ID.HashValue.begin());
45 }
46 
47 raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
48  if (O == SymbolOrigin::Unknown)
49  return OS << "unknown";
50  constexpr static char Sigils[] = "ADSM4567";
51  for (unsigned I = 0; I < sizeof(Sigils); ++I)
52  if (static_cast<uint8_t>(O) & 1u << I)
53  OS << Sigils[I];
54  return OS;
55 }
56 
57 raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
58  return OS << S.Scope << S.Name;
59 }
60 
61 double quality(const Symbol &S) {
62  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
63  // question of whether 0 references means a bad symbol or missing data.
64  if (S.References < 3)
65  return 1;
66  return std::log(S.References);
67 }
68 
70  auto It = std::lower_bound(Symbols.begin(), Symbols.end(), ID,
71  [](const Symbol &S, const SymbolID &I) {
72  return S.ID < I;
73  });
74  if (It != Symbols.end() && It->ID == ID)
75  return It;
76  return Symbols.end();
77 }
78 
79 // Copy the underlying data of the symbol into the owned arena.
80 static void own(Symbol &S, DenseSet<StringRef> &Strings,
81  BumpPtrAllocator &Arena) {
82  // Intern replaces V with a reference to the same string owned by the arena.
83  auto Intern = [&](StringRef &V) {
84  auto R = Strings.insert(V);
85  if (R.second) { // New entry added to the table, copy the string.
86  *R.first = V.copy(Arena);
87  }
88  V = *R.first;
89  };
90 
91  // We need to copy every StringRef field onto the arena.
92  Intern(S.Name);
93  Intern(S.Scope);
94  Intern(S.CanonicalDeclaration.FileURI);
95  Intern(S.Definition.FileURI);
96 
97  Intern(S.Signature);
98  Intern(S.CompletionSnippetSuffix);
99 
100  if (S.Detail) {
101  // Copy values of StringRefs into arena.
102  auto *Detail = Arena.Allocate<Symbol::Details>();
103  *Detail = *S.Detail;
104  // Intern the actual strings.
105  Intern(Detail->Documentation);
106  Intern(Detail->ReturnType);
107  Intern(Detail->IncludeHeader);
108  // Replace the detail pointer with our copy.
109  S.Detail = Detail;
110  }
111 }
112 
114  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
115  if (R.second) {
116  Symbols.push_back(S);
117  own(Symbols.back(), Strings, Arena);
118  } else {
119  auto &Copy = Symbols[R.first->second] = S;
120  own(Copy, Strings, Arena);
121  }
122 }
123 
125  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
126  // Sort symbols so the slab can binary search over them.
127  std::sort(Symbols.begin(), Symbols.end(),
128  [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
129  // We may have unused strings from overwritten symbols. Build a new arena.
130  BumpPtrAllocator NewArena;
131  DenseSet<StringRef> Strings;
132  for (auto &S : Symbols)
133  own(S, Strings, NewArena);
134  return SymbolSlab(std::move(NewArena), std::move(Symbols));
135 }
136 
137 } // namespace clangd
138 } // namespace clang
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
Definition: Index.h:208
Optional symbol details that are not required to be set.
Definition: Index.h:206
Some operations such as code completion produce a set of candidates.
llvm::StringRef IncludeHeader
This can be either a URI of the header to be #include&#39;d for this symbol, or a literal header quoted w...
Definition: Index.h:219
void log(Logger::Level, const llvm::formatv_object_base &)
Definition: Logger.cpp:28
std::vector< Symbol >::const_iterator const_iterator
Definition: Index.h:240
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:317
const_iterator find(const SymbolID &SymID) const
Definition: Index.cpp:69
void insert(const Symbol &S)
Definition: Index.cpp:113
llvm::StringRef Scope
Definition: Index.h:172
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
Definition: Index.h:211
unsigned References
Definition: Index.h:187
SymbolLocation Definition
Definition: Index.h:175
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list...
Definition: Index.h:195
std::string str() const
Definition: Index.cpp:34
llvm::StringRef FileURI
Definition: Index.h:39
SymbolLocation CanonicalDeclaration
Definition: Index.h:184
Position Start
The symbol range, using half-open range [Start, End).
Definition: Index.h:42
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::StringRef Name
Definition: Index.h:170
const Details * Detail
Definition: Index.h:223
void operator>>(StringRef Str, SymbolID &ID)
Definition: Index.cpp:41
double quality(const Symbol &S)
Definition: Index.cpp:61
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
Definition: Index.h:199
static void own(Symbol &S, DenseSet< StringRef > &Strings, BumpPtrAllocator &Arena)
Definition: Index.cpp:80
raw_ostream & operator<<(raw_ostream &OS, const CodeCompletion &C)