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::RelationsRequest>
132 auto IDs = getIDs(Message->subjects());
134 return IDs.takeError();
136 if (!Message->has_predicate())
137 return error(
"RelationsRequest requires RelationKind predicate.");
139 if (Message->limit())
140 Req.
Limit = Message->limit();
145 if (!Message.has_info() || !Message.has_canonical_declaration())
146 return error(
"Missing info or declaration.");
150 return ID.takeError();
153 Result.Name = Message.name();
154 Result.Scope = Message.scope();
155 if (Message.has_definition()) {
164 Result.References = Message.references();
167 Result.Signature = Message.signature();
168 Result.TemplateSpecializationArgs = Message.template_specialization_args();
169 Result.CompletionSnippetSuffix = Message.completion_snippet_suffix();
170 Result.Documentation = Message.documentation();
171 Result.ReturnType = Message.return_type();
172 Result.Type = Message.type();
173 for (
const auto &Header : Message.headers()) {
175 if (!SerializedHeader)
176 return SerializedHeader.takeError();
177 Result.IncludeHeaders.push_back(*SerializedHeader);
184 if (!Message.has_location())
185 return error(
"Missing location.");
191 Result.Kind =
static_cast<RefKind>(Message.kind());
195llvm::Expected<std::pair<clangd::SymbolID, clangd::Symbol>>
199 return SubjectID.takeError();
200 if (!Message.has_object())
201 return error(
"Missing Object.");
204 return Object.takeError();
205 return std::make_pair(*SubjectID, *
Object);
216 assert(!LocalIndexRoot.empty());
218 RPCRequest.set_query(From.
Query);
219 for (
const auto &Scope : From.
Scopes)
220 RPCRequest.add_scopes(Scope);
221 RPCRequest.set_any_scope(From.
AnyScope);
223 RPCRequest.set_limit(*From.
Limit);
226 llvm::SmallString<256> RelativePath = llvm::StringRef(
Path);
227 if (replace_path_prefix(RelativePath, LocalIndexRoot,
""))
228 RPCRequest.add_proximity_paths(
229 convert_to_slash(RelativePath, Style::windows));
232 RPCRequest.add_preferred_types(
Type);
238 for (
const auto &
ID : From.
IDs)
239 RPCRequest.add_ids(
ID.str());
240 RPCRequest.set_filter(
static_cast<uint32_t
>(From.
Filter));
242 RPCRequest.set_limit(*From.
Limit);
250 RPCRequest.add_subjects(
ID.str());
251 RPCRequest.set_predicate(
static_cast<uint32_t
>(From.
Predicate));
253 RPCRequest.set_limit(*From.
Limit);
259 Result.set_id(From.
ID.
str());
261 Result.set_name(From.
Name.str());
268 Result.set_scope(From.
Scope.str());
272 *Result.mutable_canonical_declaration() = *
Declaration;
274 Result.set_signature(From.
Signature.str());
275 Result.set_template_specialization_args(
279 Result.set_return_type(From.
ReturnType.str());
280 Result.set_type(From.
Type.str());
284 return Serialized.takeError();
285 auto *NextHeader = Result.add_headers();
286 *NextHeader = *Serialized;
288 Result.set_flags(
static_cast<uint32_t
>(From.
Flags));
294 Result.set_kind(
static_cast<uint32_t
>(From.
Kind));
298 *Result.mutable_location() = *
Location;
305 *Result.mutable_subject_id() = Subject.
str();
307 if (!SerializedObject)
308 return SerializedObject.takeError();
309 *Result.mutable_object() = *SerializedObject;
313llvm::Expected<std::string>
315 assert(!LocalIndexRoot.empty());
316 assert(RelativePath == convert_to_slash(RelativePath));
317 if (RelativePath.empty())
318 return error(
"Empty relative path.");
319 if (is_absolute(RelativePath, Style::posix))
320 return error(
"RelativePath '{0}' is absolute.", RelativePath);
321 llvm::SmallString<256> FullPath = llvm::StringRef(LocalIndexRoot);
322 append(FullPath, RelativePath);
324 return Result.toString();
328 assert(!RemoteIndexRoot.empty());
331 return ParsedURI.takeError();
332 if (ParsedURI->scheme() !=
"file")
333 return error(
"Can not use URI schemes other than file, given: '{0}'.",
URI);
334 llvm::SmallString<256> Result = ParsedURI->body();
335 llvm::StringRef
Path(Result);
337 if (is_absolute(
Path.substr(1), Style::windows))
338 Result =
Path.drop_front();
339 if (!replace_path_prefix(Result, RemoteIndexRoot,
""))
340 return error(
"File path '{0}' doesn't start with '{1}'.", Result.str(),
342 assert(Result == convert_to_slash(Result, Style::windows));
343 return std::string(Result);
349 Result.setColumn(
static_cast<uint32_t
>(Message.column()));
350 Result.setLine(
static_cast<uint32_t
>(Message.line()));
356 remote::Position Result;
357 Result.set_column(
Position.column());
363 clang::index::SymbolInfo Result;
364 Result.Kind =
static_cast<clang::index::SymbolKind
>(Message.kind());
365 Result.SubKind =
static_cast<clang::index::SymbolSubKind
>(Message.subkind());
366 Result.Lang =
static_cast<clang::index::SymbolLanguage
>(Message.language());
368 static_cast<clang::index::SymbolPropertySet
>(Message.properties());
374 Result.set_kind(
static_cast<uint32_t
>(
Info.Kind));
375 Result.set_subkind(
static_cast<uint32_t
>(
Info.SubKind));
376 Result.set_language(
static_cast<uint32_t
>(
Info.Lang));
377 Result.set_properties(
static_cast<uint32_t
>(
Info.Properties));
381llvm::Expected<clangd::SymbolLocation>
386 return URIString.takeError();
387 Location.FileURI = Strings.save(*URIString).begin();
393llvm::Expected<SymbolLocation>
395 remote::SymbolLocation Result;
398 return RelativePath.takeError();
399 *Result.mutable_file_path() = *RelativePath;
406 const clangd::Symbol::IncludeHeaderWithReferences &IncludeHeader) {
407 HeaderWithReferences Result;
408 Result.set_references(IncludeHeader.References);
409 Result.set_supported_directives(IncludeHeader.SupportedDirectives);
410 const std::string Header = IncludeHeader.IncludeHeader.str();
412 Result.set_header(Header);
417 return RelativePath.takeError();
418 Result.set_header(*RelativePath);
422llvm::Expected<clangd::Symbol::IncludeHeaderWithReferences>
424 std::string Header =
Message.header();
428 return URIString.takeError();
432 if (
Message.has_supported_directives())
434 Message.supported_directives());
435 return clangd::Symbol::IncludeHeaderWithReferences{
436 Strings.save(Header),
Message.references(), Directives};
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::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.