clang-tools  8.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 "Logger.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/raw_ostream.h"
16 
17 namespace clang {
18 namespace clangd {
19 
20 constexpr uint32_t SymbolLocation::Position::MaxLine;
21 constexpr uint32_t SymbolLocation::Position::MaxColumn;
23  if (L > MaxLine) {
24  Line = MaxLine;
25  return;
26  }
27  Line = L;
28 }
30  if (Col > MaxColumn) {
31  Column = MaxColumn;
32  return;
33  }
34  Column = Col;
35 }
36 
37 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolLocation &L) {
38  if (!L)
39  return OS << "(none)";
40  return OS << L.FileURI << "[" << L.Start.line() << ":" << L.Start.column()
41  << "-" << L.End.line() << ":" << L.End.column() << ")";
42 }
43 
44 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SymbolOrigin O) {
45  if (O == SymbolOrigin::Unknown)
46  return OS << "unknown";
47  constexpr static char Sigils[] = "ADSM4567";
48  for (unsigned I = 0; I < sizeof(Sigils); ++I)
49  if (static_cast<uint8_t>(O) & 1u << I)
50  OS << Sigils[I];
51  return OS;
52 }
53 
54 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
55  if (F == Symbol::None)
56  return OS << "None";
57  std::string s;
58  if (F & Symbol::Deprecated)
59  s += "deprecated|";
61  s += "completion|";
62  return OS << llvm::StringRef(s).rtrim('|');
63 }
64 
65 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
66  return OS << S.Scope << S.Name;
67 }
68 
69 float quality(const Symbol &S) {
70  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
71  // question of whether 0 references means a bad symbol or missing data.
72  if (S.References < 3)
73  return 1;
74  return std::log(S.References);
75 }
76 
78  auto It = std::lower_bound(
79  Symbols.begin(), Symbols.end(), ID,
80  [](const Symbol &S, const SymbolID &I) { return S.ID < I; });
81  if (It != Symbols.end() && It->ID == ID)
82  return It;
83  return Symbols.end();
84 }
85 
86 // Copy the underlying data of the symbol into the owned arena.
87 static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
88  visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
89 }
90 
92  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
93  if (R.second) {
94  Symbols.push_back(S);
95  own(Symbols.back(), UniqueStrings);
96  } else {
97  auto &Copy = Symbols[R.first->second] = S;
98  own(Copy, UniqueStrings);
99  }
100 }
101 
103  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
104  // Sort symbols so the slab can binary search over them.
105  llvm::sort(Symbols,
106  [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
107  // We may have unused strings from overwritten symbols. Build a new arena.
108  llvm::BumpPtrAllocator NewArena;
109  llvm::UniqueStringSaver Strings(NewArena);
110  for (auto &S : Symbols)
111  own(S, Strings);
112  return SymbolSlab(std::move(NewArena), std::move(Symbols));
113 }
114 
115 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, RefKind K) {
116  if (K == RefKind::Unknown)
117  return OS << "Unknown";
118  static const std::vector<const char *> Messages = {"Decl", "Def", "Ref"};
119  bool VisitedOnce = false;
120  for (unsigned I = 0; I < Messages.size(); ++I) {
121  if (static_cast<uint8_t>(K) & 1u << I) {
122  if (VisitedOnce)
123  OS << ", ";
124  OS << Messages[I];
125  VisitedOnce = true;
126  }
127  }
128  return OS;
129 }
130 
131 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Ref &R) {
132  return OS << R.Location << ":" << R.Kind;
133 }
134 
135 void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
136  auto &M = Refs[ID];
137  M.push_back(S);
138  M.back().Location.FileURI =
139  UniqueStrings.save(M.back().Location.FileURI).data();
140 }
141 
143  // We can reuse the arena, as it only has unique strings and we need them all.
144  // Reallocate refs on the arena to reduce waste and indirections when reading.
145  std::vector<std::pair<SymbolID, llvm::ArrayRef<Ref>>> Result;
146  Result.reserve(Refs.size());
147  size_t NumRefs = 0;
148  for (auto &Sym : Refs) {
149  auto &SymRefs = Sym.second;
150  llvm::sort(SymRefs);
151  // FIXME: do we really need to dedup?
152  SymRefs.erase(std::unique(SymRefs.begin(), SymRefs.end()), SymRefs.end());
153 
154  NumRefs += SymRefs.size();
155  auto *Array = Arena.Allocate<Ref>(SymRefs.size());
156  std::uninitialized_copy(SymRefs.begin(), SymRefs.end(), Array);
157  Result.emplace_back(Sym.first, llvm::ArrayRef<Ref>(Array, SymRefs.size()));
158  }
159  return RefSlab(std::move(Result), std::move(Arena), NumRefs);
160 }
161 
162 void SwapIndex::reset(std::unique_ptr<SymbolIndex> Index) {
163  // Keep the old index alive, so we don't destroy it under lock (may be slow).
164  std::shared_ptr<SymbolIndex> Pin;
165  {
166  std::lock_guard<std::mutex> Lock(Mutex);
167  Pin = std::move(this->Index);
168  this->Index = std::move(Index);
169  }
170 }
171 std::shared_ptr<SymbolIndex> SwapIndex::snapshot() const {
172  std::lock_guard<std::mutex> Lock(Mutex);
173  return Index;
174 }
175 
176 bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request) {
177  llvm::json::ObjectMapper O(Parameters);
178  int64_t Limit;
179  bool OK =
180  O && O.map("Query", Request.Query) && O.map("Scopes", Request.Scopes) &&
181  O.map("AnyScope", Request.AnyScope) && O.map("Limit", Limit) &&
182  O.map("RestrictForCodeCompletion", Request.RestrictForCodeCompletion) &&
183  O.map("ProximityPaths", Request.ProximityPaths);
184  if (OK && Limit <= std::numeric_limits<uint32_t>::max())
185  Request.Limit = Limit;
186  return OK;
187 }
188 
189 llvm::json::Value toJSON(const FuzzyFindRequest &Request) {
190  return llvm::json::Object{
191  {"Query", Request.Query},
192  {"Scopes", llvm::json::Array{Request.Scopes}},
193  {"AnyScope", Request.AnyScope},
194  {"Limit", Request.Limit},
195  {"RestrictForCodeCompletion", Request.RestrictForCodeCompletion},
196  {"ProximityPaths", llvm::json::Array{Request.ProximityPaths}},
197  };
198 }
199 
201  llvm::function_ref<void(const Symbol &)> CB) const {
202  return snapshot()->fuzzyFind(R, CB);
203 }
205  llvm::function_ref<void(const Symbol &)> CB) const {
206  return snapshot()->lookup(R, CB);
207 }
209  llvm::function_ref<void(const Ref &)> CB) const {
210  return snapshot()->refs(R, CB);
211 }
213  return snapshot()->estimateMemoryUsage();
214 }
215 
216 } // namespace clangd
217 } // namespace clang
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
Definition: Index.cpp:189
bool AnyScope
If set to true, allow symbols from any scope.
Definition: Index.h:449
void lookup(const LookupRequest &, llvm::function_ref< void(const Symbol &)>) const override
Looks up symbols with any of the given symbol IDs and applies Callback on each matched symbol...
Definition: Index.cpp:204
void setColumn(uint32_t Column)
Definition: Index.cpp:29
bool RestrictForCodeCompletion
If set to true, only symbols for completion support will be considered.
Definition: Index.h:454
void log(Logger::Level, const llvm::formatv_object_base &)
Definition: Logger.cpp:31
std::vector< Symbol >::const_iterator const_iterator
Definition: Index.h:294
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:487
const_iterator find(const SymbolID &SymID) const
Definition: Index.cpp:77
void insert(const Symbol &S)
Definition: Index.cpp:91
llvm::StringRef Scope
Definition: Index.h:168
unsigned References
Definition: Index.h:183
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
Definition: Index.h:446
llvm::BumpPtrAllocator Arena
Whether or not this symbol is meant to be used for the code completion.
Definition: Index.h:239
static constexpr uint32_t MaxColumn
Definition: Index.h:52
void refs(const RefsRequest &, llvm::function_ref< void(const Ref &)>) const override
Finds all occurrences (e.g.
Definition: Index.cpp:208
SymbolLocation Location
Definition: Index.h:375
std::string Query
A query string for the fuzzy find.
Definition: Index.h:439
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request)
Definition: Index.cpp:176
std::vector< llvm::StringRef > Strings
static void own(Symbol &S, llvm::UniqueStringSaver &Strings)
Definition: Index.cpp:87
static constexpr uint32_t MaxLine
Definition: Index.h:51
Position Start
The symbol range, using half-open range [Start, End).
Definition: Index.h:61
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< std::string > ProximityPaths
Contextually relevant files (e.g.
Definition: Index.h:457
llvm::StringRef Name
Definition: Index.h:166
bool fuzzyFind(const FuzzyFindRequest &, llvm::function_ref< void(const Symbol &)>) const override
Matches symbols in the index fuzzily and applies Callback on each matched symbol before returning...
Definition: Index.cpp:200
size_t estimateMemoryUsage() const override
Returns estimated size of index (in bytes).
Definition: Index.cpp:212
void insert(const SymbolID &ID, const Ref &S)
Definition: Index.cpp:135
llvm::Optional< uint32_t > Limit
The number of top candidates to return.
Definition: Index.h:452
Indicates if the symbol is deprecated.
Definition: Index.h:241
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
const char * FileURI
Definition: Index.h:72
RefKind Kind
Definition: Index.h:376
void reset(std::unique_ptr< SymbolIndex >)
Definition: Index.cpp:162
void visitStrings(Symbol &S, const Callback &CB)
Definition: Index.h:263
float quality(const Symbol &S)
Definition: Index.cpp:69
const SymbolIndex * Index
Definition: Dexp.cpp:85