21#include "clang/Index/IndexSymbol.h"
22#include "llvm/ADT/DenseSet.h"
23#include "llvm/ADT/SmallString.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/Support/Error.h"
27#include "llvm/Support/FormatVariadic.h"
28#include "llvm/Support/Path.h"
29#include "llvm/Support/StringSaver.h"
35using llvm::sys::path::append;
36using llvm::sys::path::convert_to_slash;
37using llvm::sys::path::is_absolute;
38using llvm::sys::path::replace_path_prefix;
39using llvm::sys::path::Style;
43template <
typename IDRange>
44llvm::Expected<llvm::DenseSet<SymbolID>> getIDs(IDRange IDs) {
45 llvm::DenseSet<SymbolID> Result;
46 for (
const auto &
ID : IDs) {
49 return SID.takeError();
58 llvm::StringRef LocalIndexRoot)
60 llvm::StringRef PosixSeparator = get_separator(Style::posix);
61 if (!RemoteIndexRoot.empty()) {
62 assert(is_absolute(RemoteIndexRoot));
63 this->RemoteIndexRoot = convert_to_slash(RemoteIndexRoot, Style::windows);
64 llvm::StringRef
Path(this->RemoteIndexRoot);
65 if (!is_separator(this->RemoteIndexRoot.back(), Style::posix))
66 this->RemoteIndexRoot += PosixSeparator;
68 if (!LocalIndexRoot.empty()) {
69 assert(is_absolute(LocalIndexRoot));
70 this->LocalIndexRoot = convert_to_slash(LocalIndexRoot, Style::windows);
71 llvm::StringRef
Path(this->LocalIndexRoot);
72 if (!is_separator(this->LocalIndexRoot.back(), Style::posix))
73 this->LocalIndexRoot += PosixSeparator;
75 assert(!RemoteIndexRoot.empty() || !LocalIndexRoot.empty());
78llvm::Expected<clangd::LookupRequest>
81 auto IDs = getIDs(Message->ids());
83 return IDs.takeError();
84 Req.
IDs = std::move(*IDs);
88llvm::Expected<clangd::FuzzyFindRequest>
90 assert(!RemoteIndexRoot.empty());
92 Result.Query = Message->query();
93 for (
const auto &Scope : Message->scopes())
94 Result.Scopes.push_back(Scope);
95 Result.AnyScope = Message->any_scope();
97 Result.Limit = Message->limit();
98 Result.RestrictForCodeCompletion = Message->restricted_for_code_completion();
99 for (
const auto &
Path : Message->proximity_paths()) {
100 llvm::SmallString<256> LocalPath = llvm::StringRef(RemoteIndexRoot);
101 append(LocalPath,
Path);
104 llvm::sys::path::native(LocalPath);
105 Result.ProximityPaths.push_back(std::string(LocalPath));
107 for (
const auto &
Type : Message->preferred_types())
108 Result.ProximityPaths.push_back(
Type);
112llvm::Expected<clangd::RefsRequest>
115 auto IDs = getIDs(Message->ids());
117 return IDs.takeError();
118 Req.
IDs = std::move(*IDs);
119 if (Message->has_filter())
123 if (Message->limit())
124 Req.
Limit = Message->limit();
129llvm::Expected<clangd::ContainedRefsRequest>
132 if (!Message->has_id())
133 return error(
"ContainedRefsRequest requires an id.");
136 return ID.takeError();
138 if (Message->has_limit())
139 Req.
Limit = Message->limit();
143llvm::Expected<clangd::RelationsRequest>
146 auto IDs = getIDs(Message->subjects());
148 return IDs.takeError();
150 if (!Message->has_predicate())
151 return error(
"RelationsRequest requires RelationKind predicate.");
153 if (Message->limit())
154 Req.
Limit = Message->limit();
159 if (!Message.has_info() || !Message.has_canonical_declaration())
160 return error(
"Missing info or declaration.");
164 return ID.takeError();
167 Result.Name = Message.name();
168 Result.Scope = Message.scope();
169 if (Message.has_definition()) {
178 Result.References = Message.references();
181 Result.Signature = Message.signature();
182 Result.TemplateSpecializationArgs = Message.template_specialization_args();
183 Result.CompletionSnippetSuffix = Message.completion_snippet_suffix();
184 Result.Documentation = Message.documentation();
185 Result.ReturnType = Message.return_type();
186 Result.Type = Message.type();
187 for (
const auto &Header : Message.headers()) {
189 if (!SerializedHeader)
190 return SerializedHeader.takeError();
191 Result.IncludeHeaders.push_back(*SerializedHeader);
198 if (!Message.has_location())
199 return error(
"Missing location.");
205 Result.Kind =
static_cast<RefKind>(Message.kind());
209llvm::Expected<clangd::ContainedRefsResult>
212 if (!Message.has_location())
213 return error(
"ContainedRef must have a location.");
214 if (!Message.has_kind())
215 return error(
"ContainedRef must have a kind.");
216 if (!Message.has_symbol())
217 return error(
"ContainedRef must have a symbol.");
222 Result.Kind =
static_cast<RefKind>(Message.kind());
225 return Symbol.takeError();
230llvm::Expected<std::pair<clangd::SymbolID, clangd::Symbol>>
234 return SubjectID.takeError();
235 if (!Message.has_object())
236 return error(
"Missing Object.");
239 return Object.takeError();
240 return std::make_pair(*SubjectID, *
Object);
251 assert(!LocalIndexRoot.empty());
253 RPCRequest.set_query(From.
Query);
254 for (
const auto &Scope : From.
Scopes)
255 RPCRequest.add_scopes(Scope);
256 RPCRequest.set_any_scope(From.
AnyScope);
258 RPCRequest.set_limit(*From.
Limit);
261 llvm::SmallString<256> RelativePath = llvm::StringRef(
Path);
262 if (replace_path_prefix(RelativePath, LocalIndexRoot,
""))
263 RPCRequest.add_proximity_paths(
264 convert_to_slash(RelativePath, Style::windows));
267 RPCRequest.add_preferred_types(
Type);
273 for (
const auto &
ID : From.
IDs)
274 RPCRequest.add_ids(
ID.str());
275 RPCRequest.set_filter(
static_cast<uint32_t
>(From.
Filter));
277 RPCRequest.set_limit(*From.
Limit);
285 RPCRequest.set_id(From.
ID.
str());
287 RPCRequest.set_limit(*From.
Limit);
294 RPCRequest.add_subjects(
ID.str());
295 RPCRequest.set_predicate(
static_cast<uint32_t
>(From.
Predicate));
297 RPCRequest.set_limit(*From.
Limit);
303 Result.set_id(From.
ID.
str());
305 Result.set_name(From.
Name.str());
312 Result.set_scope(From.
Scope.str());
316 *Result.mutable_canonical_declaration() = *
Declaration;
318 Result.set_signature(From.
Signature.str());
319 Result.set_template_specialization_args(
323 Result.set_return_type(From.
ReturnType.str());
324 Result.set_type(From.
Type.str());
328 return Serialized.takeError();
329 auto *NextHeader = Result.add_headers();
330 *NextHeader = *Serialized;
332 Result.set_flags(
static_cast<uint32_t
>(From.
Flags));
338 Result.set_kind(
static_cast<uint32_t
>(From.
Kind));
342 *Result.mutable_location() = *
Location;
346llvm::Expected<ContainedRef>
352 *Result.mutable_location() = *
Location;
353 Result.set_kind(
static_cast<uint32_t
>(From.
Kind));
354 *Result.mutable_symbol() = From.
Symbol.
str();
361 *Result.mutable_subject_id() = Subject.
str();
363 if (!SerializedObject)
364 return SerializedObject.takeError();
365 *Result.mutable_object() = *SerializedObject;
369llvm::Expected<std::string>
371 assert(!LocalIndexRoot.empty());
372 assert(RelativePath == convert_to_slash(RelativePath));
373 if (RelativePath.empty())
374 return error(
"Empty relative path.");
375 if (is_absolute(RelativePath, Style::posix))
376 return error(
"RelativePath '{0}' is absolute.", RelativePath);
377 llvm::SmallString<256> FullPath = llvm::StringRef(LocalIndexRoot);
378 append(FullPath, RelativePath);
380 return Result.toString();
384 assert(!RemoteIndexRoot.empty());
387 return ParsedURI.takeError();
388 if (ParsedURI->scheme() !=
"file")
389 return error(
"Can not use URI schemes other than file, given: '{0}'.",
URI);
390 llvm::SmallString<256> Result = ParsedURI->body();
391 llvm::StringRef
Path(Result);
393 if (is_absolute(
Path.substr(1), Style::windows))
394 Result =
Path.drop_front();
395 if (!replace_path_prefix(Result, RemoteIndexRoot,
""))
396 return error(
"File path '{0}' doesn't start with '{1}'.", Result.str(),
398 assert(Result == convert_to_slash(Result, Style::windows));
399 return std::string(Result);
405 Result.setColumn(
static_cast<uint32_t
>(Message.column()));
406 Result.setLine(
static_cast<uint32_t
>(Message.line()));
412 remote::Position Result;
413 Result.set_column(
Position.column());
419 clang::index::SymbolInfo Result;
420 Result.Kind =
static_cast<clang::index::SymbolKind
>(Message.kind());
421 Result.SubKind =
static_cast<clang::index::SymbolSubKind
>(Message.subkind());
422 Result.Lang =
static_cast<clang::index::SymbolLanguage
>(Message.language());
424 static_cast<clang::index::SymbolPropertySet
>(Message.properties());
430 Result.set_kind(
static_cast<uint32_t
>(
Info.Kind));
431 Result.set_subkind(
static_cast<uint32_t
>(
Info.SubKind));
432 Result.set_language(
static_cast<uint32_t
>(
Info.Lang));
433 Result.set_properties(
static_cast<uint32_t
>(
Info.Properties));
437llvm::Expected<clangd::SymbolLocation>
442 return URIString.takeError();
443 Location.FileURI = Strings.save(*URIString).begin();
449llvm::Expected<SymbolLocation>
451 remote::SymbolLocation Result;
454 return RelativePath.takeError();
455 *Result.mutable_file_path() = *RelativePath;
462 const clangd::Symbol::IncludeHeaderWithReferences &IncludeHeader) {
463 HeaderWithReferences Result;
464 Result.set_references(IncludeHeader.References);
465 Result.set_supported_directives(IncludeHeader.SupportedDirectives);
466 const std::string Header = IncludeHeader.IncludeHeader.str();
468 Result.set_header(Header);
473 return RelativePath.takeError();
474 Result.set_header(*RelativePath);
478llvm::Expected<clangd::Symbol::IncludeHeaderWithReferences>
480 std::string Header =
Message.header();
484 return URIString.takeError();
488 if (
Message.has_supported_directives())
490 Message.supported_directives());
491 return clangd::Symbol::IncludeHeaderWithReferences{
std::vector< llvm::StringRef > Strings
llvm::BumpPtrAllocator Arena
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
A URI describes the location of a source file.
static URI createFile(llvm::StringRef AbsolutePath)
This creates a file:// URI for AbsolutePath. The path must be absolute.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
LookupRequest toProtobuf(const clangd::LookupRequest &From)
toProtobuf() functions serialize native clangd types and strip IndexRoot from the file paths specific...
llvm::Expected< std::string > uriToRelativePath(llvm::StringRef URI)
Translates a URI from the server's backing index to a relative path suitable to send over the wire to...
llvm::Expected< clangd::Symbol > fromProtobuf(const Symbol &Message)
llvm::Expected< std::string > relativePathToURI(llvm::StringRef RelativePath)
Translates RelativePath into the absolute path and builds URI for the user machine.
Describes a named symbol from a header.
bool isLiteralInclude(llvm::StringRef Include)
Returns true if Include is literal include like "path" or <path>.
@ Info
An information message.
std::string Path
A typedef to represent a file path.
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
RefKind
Describes the kind of a cross-reference.
@ Type
An inlay hint that for a type annotation.
constexpr llvm::StringLiteral Message
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::optional< uint32_t > Limit
If set, limit the number of refers returned from the index.
SymbolID Symbol
The ID of the symbol which is referred to.
SymbolLocation Location
The source location where the symbol is named.
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
bool RestrictForCodeCompletion
If set to true, only symbols for completion support will be considered.
std::string Query
A query string for the fuzzy find.
std::vector< std::string > ProximityPaths
Contextually relevant files (e.g.
bool AnyScope
If set to true, allow symbols from any scope.
std::optional< uint32_t > Limit
The number of top candidates to return.
std::vector< std::string > PreferredTypes
Preferred types of symbols. These are raw representation of OpaqueType.
llvm::DenseSet< SymbolID > IDs
int line
Line position in a document (zero-based).
Represents a symbol occurrence in the source file.
SymbolLocation Location
The source location where the symbol is named.
bool WantContainer
If set, populates the container of the reference.
llvm::DenseSet< SymbolID > IDs
std::optional< uint32_t > Limit
If set, limit the number of refers returned from the index.
Represents a relation between two symbols.
std::optional< uint32_t > Limit
If set, limit the number of relations returned from the index.
llvm::DenseSet< SymbolID > Subjects
The class presents a C++ symbol, e.g.
@ Include
#include "header.h"
SymbolLocation Definition
The location of the symbol's definition, if one was found.
llvm::StringRef Type
Raw representation of the OpaqueType of the symbol, used for scoring purposes.
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
llvm::SmallVector< IncludeHeaderWithReferences, 1 > IncludeHeaders
One Symbol can potentially be included via different headers.
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
llvm::StringRef Scope
The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list.
unsigned References
The number of translation units that reference this symbol from their main file.
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
llvm::StringRef TemplateSpecializationArgs
Argument list in human-readable format, will be displayed to help disambiguate between different spec...
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
SymbolID ID
The ID of the symbol.