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;
22 void SymbolLocation::Position::setLine(uint32_t L) {
23 if (L > MaxLine) {
24 Line = MaxLine;
25 return;
26 }
27 Line = L;
28 }
29 void SymbolLocation::Position::setColumn(uint32_t Col) {
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|";
60 if (F & Symbol::IndexedForCodeCompletion)
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
77 SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
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
91 void SymbolSlab::Builder::insert(const Symbol &S) {
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
102 SymbolSlab SymbolSlab::Builder::build() && {
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
142 RefSlab RefSlab::Builder::build() && {
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
200 bool SwapIndex::fuzzyFind(const FuzzyFindRequest &R,
201 llvm::function_ref<void(const Symbol &)> CB) const {
202 return snapshot()->fuzzyFind(R, CB);
203 }
204 void SwapIndex::lookup(const LookupRequest &R,
205 llvm::function_ref<void(const Symbol &)> CB) const {
206 return snapshot()->lookup(R, CB);
207 }
208 void SwapIndex::refs(const RefsRequest &R,
209 llvm::function_ref<void(const Ref &)> CB) const {
210 return snapshot()->refs(R, CB);
211 }
212 size_t SwapIndex::estimateMemoryUsage() const {
213 return snapshot()->estimateMemoryUsage();
214 }
215
216 } // namespace clangd
217 } // namespace clang
clang::clangd::RefKind::Unknown
clang::clangd::SymbolSlab
Definition: Index.h:292
clang::clangd::toJSON
llvm::json::Value toJSON(const FuzzyFindRequest &Request)
Definition: Index.cpp:189
clang::clangd::FuzzyFindRequest::AnyScope
bool AnyScope
If set to true, allow symbols from any scope.
Definition: Index.h:449
clang::clangd::SwapIndex::lookup
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
clang::clangd::SymbolLocation::Position::setColumn
void setColumn(uint32_t Column)
Definition: Index.cpp:29
clang::clangd::FuzzyFindRequest::RestrictForCodeCompletion
bool RestrictForCodeCompletion
If set to true, only symbols for completion support will be considered.
Definition: Index.h:454
clang::clangd::SymbolLocation
Definition: Index.h:34
clang::clangd::SymbolLocation::Position::column
uint32_t column() const
Definition: Index.h:45
clang::clangd::RefSlab
Definition: Index.h:388
Index.h
clang::clangd::detail::log
void log(Logger::Level, const llvm::formatv_object_base &)
Definition: Logger.cpp:31
clang::clangd::SymbolLocation::Position::setLine
void setLine(uint32_t Line)
Definition: Index.cpp:22
clang::clangd::SymbolSlab::const_iterator
std::vector< Symbol >::const_iterator const_iterator
Definition: Index.h:294
clang::clangd::SymbolIndex
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:487
clang::clangd::SymbolSlab::find
const_iterator find(const SymbolID &SymID) const
Definition: Index.cpp:77
clang::clangd::Ref
Definition: Index.h:373
clang::clangd::RefsRequest
Definition: Index.h:476
clang::clangd::SymbolSlab::Builder::insert
void insert(const Symbol &S)
Definition: Index.cpp:91
clang::clangd::Symbol::Scope
llvm::StringRef Scope
Definition: Index.h:168
clang::clangd::FuzzyFindRequest
Definition: Index.h:436
clang::clangd::Symbol::SymbolFlag
SymbolFlag
Definition: Index.h:233
clang::clangd::SymbolKind::Array
clang::clangd::Symbol::References
unsigned References
Definition: Index.h:183
clang::clangd::FuzzyFindRequest::Scopes
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
clang::clangd::Symbol::ID
SymbolID ID
Definition: Index.h:162
clang::clangd::SymbolSlab::Builder::build
SymbolSlab build() &&
Definition: Index.cpp:102
Arena
llvm::BumpPtrAllocator Arena
Definition: Serialization.cpp:189
clang::clangd::TraceLevel::Messages
clang::clangd::Symbol::IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
Definition: Index.h:239
clang::clangd::SymbolLocation::Position::MaxColumn
static constexpr uint32_t MaxColumn
Definition: Index.h:52
clang::clangd::SwapIndex::refs
void refs(const RefsRequest &, llvm::function_ref< void(const Ref &)>) const override
Finds all occurrences (e.g.
Definition: Index.cpp:208
clang::clangd::Ref::Location
SymbolLocation Location
Definition: Index.h:375
clang::clangd::FuzzyFindRequest::Query
std::string Query
A query string for the fuzzy find.
Definition: Index.h:439
Result
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: ClangdServer.cpp:60
clang::clangd::RefKind
RefKind
Definition: Index.h:351
clang::clangd::fromJSON
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request)
Definition: Index.cpp:176
clang::clangd::SymbolLocation::End
Position End
Definition: Index.h:62
Strings
std::vector< llvm::StringRef > Strings
Definition: Serialization.cpp:190
clang::clangd::own
static void own(Symbol &S, llvm::UniqueStringSaver &Strings)
Definition: Index.cpp:87
Logger.h
clang::clangd::Symbol
Definition: Index.h:160
clang::clangd::SymbolLocation::Position::MaxLine
static constexpr uint32_t MaxLine
Definition: Index.h:51
clang::clangd::SymbolLocation::Start
Position Start
The symbol range, using half-open range [Start, End).
Definition: Index.h:61
clang::clangd::LookupRequest
Definition: Index.h:472
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18
clang::clangd::FuzzyFindRequest::ProximityPaths
std::vector< std::string > ProximityPaths
Contextually relevant files (e.g.
Definition: Index.h:457
clang::clangd::Symbol::Name
llvm::StringRef Name
Definition: Index.h:166
clang::clangd::SwapIndex::fuzzyFind
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
clang::clangd::SwapIndex::estimateMemoryUsage
size_t estimateMemoryUsage() const override
Returns estimated size of index (in bytes).
Definition: Index.cpp:212
clang::clangd::SymbolOrigin::Unknown
clang::clangd::RefSlab::Builder::insert
void insert(const SymbolID &ID, const Ref &S)
Definition: Index.cpp:135
clang::clangd::FuzzyFindRequest::Limit
llvm::Optional< uint32_t > Limit
The number of top candidates to return.
Definition: Index.h:452
clang::clangd::SymbolLocation::Position::line
uint32_t line() const
Definition: Index.h:43
clang::clangd::Symbol::Deprecated
Indicates if the symbol is deprecated.
Definition: Index.h:241
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:1719
clang::clangd::SymbolOrigin
SymbolOrigin
Definition: Index.h:126
clang::clangd::SymbolLocation::FileURI
const char * FileURI
Definition: Index.h:72
clang::clangd::Symbol::None
Definition: Index.h:234
clang::clangd::Ref::Kind
RefKind Kind
Definition: Index.h:376
clang::clangd::RefSlab::Builder::build
RefSlab build() &&
Definition: Index.cpp:142
clang::clangd::SwapIndex::reset
void reset(std::unique_ptr< SymbolIndex >)
Definition: Index.cpp:162
clang::clangd::visitStrings
void visitStrings(Symbol &S, const Callback &CB)
Definition: Index.h:263
clang::clangd::quality
float quality(const Symbol &S)
Definition: Index.cpp:69
Index
const SymbolIndex * Index
Definition: Dexp.cpp:85
clang::clangd::SymbolID
Definition: SymbolID.h:31