| 1 | //===--- Marshalling.cpp -----------------------------------------*- C++-*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "Marshalling.h" |
| 10 | #include "Headers.h" |
| 11 | #include "Index.pb.h" |
| 12 | #include "Protocol.h" |
| 13 | #include "index/Index.h" |
| 14 | #include "index/Ref.h" |
| 15 | #include "index/Serialization.h" |
| 16 | #include "index/Symbol.h" |
| 17 | #include "index/SymbolID.h" |
| 18 | #include "index/SymbolLocation.h" |
| 19 | #include "index/SymbolOrigin.h" |
| 20 | #include "support/Logger.h" |
| 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" |
| 30 | |
| 31 | namespace clang { |
| 32 | namespace clangd { |
| 33 | namespace remote { |
| 34 | |
| 35 | using llvm::sys::path::append; |
| 36 | using llvm::sys::path::convert_to_slash; |
| 37 | using llvm::sys::path::is_absolute; |
| 38 | using llvm::sys::path::replace_path_prefix; |
| 39 | using llvm::sys::path::Style; |
| 40 | |
| 41 | namespace { |
| 42 | |
| 43 | template <typename IDRange> |
| 44 | llvm::Expected<llvm::DenseSet<SymbolID>> getIDs(IDRange IDs) { |
| 45 | llvm::DenseSet<SymbolID> Result; |
| 46 | for (const auto &ID : IDs) { |
| 47 | auto SID = SymbolID::fromStr(StringRef(ID)); |
| 48 | if (!SID) |
| 49 | return SID.takeError(); |
| 50 | Result.insert(V: *SID); |
| 51 | } |
| 52 | return Result; |
| 53 | } |
| 54 | |
| 55 | } // namespace |
| 56 | |
| 57 | Marshaller::Marshaller(llvm::StringRef RemoteIndexRoot, |
| 58 | llvm::StringRef LocalIndexRoot) |
| 59 | : Strings(Arena) { |
| 60 | llvm::StringRef PosixSeparator = get_separator(style: Style::posix); |
| 61 | if (!RemoteIndexRoot.empty()) { |
| 62 | assert(is_absolute(RemoteIndexRoot)); |
| 63 | this->RemoteIndexRoot = convert_to_slash(path: RemoteIndexRoot, style: Style::windows); |
| 64 | llvm::StringRef Path(this->RemoteIndexRoot); |
| 65 | if (!is_separator(value: this->RemoteIndexRoot.back(), style: Style::posix)) |
| 66 | this->RemoteIndexRoot += PosixSeparator; |
| 67 | } |
| 68 | if (!LocalIndexRoot.empty()) { |
| 69 | assert(is_absolute(LocalIndexRoot)); |
| 70 | this->LocalIndexRoot = convert_to_slash(path: LocalIndexRoot, style: Style::windows); |
| 71 | llvm::StringRef Path(this->LocalIndexRoot); |
| 72 | if (!is_separator(value: this->LocalIndexRoot.back(), style: Style::posix)) |
| 73 | this->LocalIndexRoot += PosixSeparator; |
| 74 | } |
| 75 | assert(!RemoteIndexRoot.empty() || !LocalIndexRoot.empty()); |
| 76 | } |
| 77 | |
| 78 | llvm::Expected<clangd::LookupRequest> |
| 79 | Marshaller::fromProtobuf(const LookupRequest *Message) { |
| 80 | clangd::LookupRequest Req; |
| 81 | auto IDs = getIDs(Message->ids()); |
| 82 | if (!IDs) |
| 83 | return IDs.takeError(); |
| 84 | Req.IDs = std::move(*IDs); |
| 85 | return Req; |
| 86 | } |
| 87 | |
| 88 | llvm::Expected<clangd::FuzzyFindRequest> |
| 89 | Marshaller::fromProtobuf(const FuzzyFindRequest *Message) { |
| 90 | assert(!RemoteIndexRoot.empty()); |
| 91 | clangd::FuzzyFindRequest Result; |
| 92 | Result.Query = Message->query(); |
| 93 | for (const auto &Scope : Message->scopes()) |
| 94 | Result.Scopes.push_back(Scope); |
| 95 | Result.AnyScope = Message->any_scope(); |
| 96 | if (Message->limit()) |
| 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); |
| 102 | // FuzzyFindRequest requires proximity paths to have platform-native format |
| 103 | // in order for SymbolIndex to process the query correctly. |
| 104 | llvm::sys::path::native(LocalPath); |
| 105 | Result.ProximityPaths.push_back(std::string(LocalPath)); |
| 106 | } |
| 107 | for (const auto &Type : Message->preferred_types()) |
| 108 | Result.ProximityPaths.push_back(Type); |
| 109 | return Result; |
| 110 | } |
| 111 | |
| 112 | llvm::Expected<clangd::RefsRequest> |
| 113 | Marshaller::fromProtobuf(const RefsRequest *Message) { |
| 114 | clangd::RefsRequest Req; |
| 115 | auto IDs = getIDs(Message->ids()); |
| 116 | if (!IDs) |
| 117 | return IDs.takeError(); |
| 118 | Req.IDs = std::move(*IDs); |
| 119 | if (Message->has_filter()) |
| 120 | Req.Filter = static_cast<clangd::RefKind>(Message->filter()); |
| 121 | else |
| 122 | Req.Filter = clangd::RefKind::All; |
| 123 | if (Message->limit()) |
| 124 | Req.Limit = Message->limit(); |
| 125 | Req.WantContainer = Message->want_container(); |
| 126 | return Req; |
| 127 | } |
| 128 | |
| 129 | llvm::Expected<clangd::ContainedRefsRequest> |
| 130 | Marshaller::fromProtobuf(const ContainedRefsRequest *Message) { |
| 131 | clangd::ContainedRefsRequest Req; |
| 132 | if (!Message->has_id()) |
| 133 | return error(Fmt: "ContainedRefsRequest requires an id." ); |
| 134 | auto ID = SymbolID::fromStr(Message->id()); |
| 135 | if (!ID) |
| 136 | return ID.takeError(); |
| 137 | Req.ID = *ID; |
| 138 | if (Message->has_limit()) |
| 139 | Req.Limit = Message->limit(); |
| 140 | return Req; |
| 141 | } |
| 142 | |
| 143 | llvm::Expected<clangd::RelationsRequest> |
| 144 | Marshaller::fromProtobuf(const RelationsRequest *Message) { |
| 145 | clangd::RelationsRequest Req; |
| 146 | auto IDs = getIDs(Message->subjects()); |
| 147 | if (!IDs) |
| 148 | return IDs.takeError(); |
| 149 | Req.Subjects = std::move(*IDs); |
| 150 | if (!Message->has_predicate()) |
| 151 | return error(Fmt: "RelationsRequest requires RelationKind predicate." ); |
| 152 | Req.Predicate = static_cast<RelationKind>(Message->predicate()); |
| 153 | if (Message->limit()) |
| 154 | Req.Limit = Message->limit(); |
| 155 | return Req; |
| 156 | } |
| 157 | |
| 158 | llvm::Expected<clangd::Symbol> Marshaller::fromProtobuf(const Symbol &Message) { |
| 159 | if (!Message.has_info() || !Message.has_canonical_declaration()) |
| 160 | return error(Fmt: "Missing info or declaration." ); |
| 161 | clangd::Symbol Result; |
| 162 | auto ID = SymbolID::fromStr(Message.id()); |
| 163 | if (!ID) |
| 164 | return ID.takeError(); |
| 165 | Result.ID = *ID; |
| 166 | Result.SymInfo = fromProtobuf(Message.info()); |
| 167 | Result.Name = Message.name(); |
| 168 | Result.Scope = Message.scope(); |
| 169 | if (Message.has_definition()) { |
| 170 | auto Definition = fromProtobuf(Message.definition()); |
| 171 | if (Definition) |
| 172 | Result.Definition = *Definition; |
| 173 | } |
| 174 | auto Declaration = fromProtobuf(Message.canonical_declaration()); |
| 175 | if (!Declaration) |
| 176 | return Declaration.takeError(); |
| 177 | Result.CanonicalDeclaration = *Declaration; |
| 178 | Result.References = Message.references(); |
| 179 | // Overwrite symbol origin: it's coming from remote index. |
| 180 | Result.Origin = clangd::SymbolOrigin::Remote; |
| 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()) { |
| 188 | auto SerializedHeader = fromProtobuf(Header); |
| 189 | if (!SerializedHeader) |
| 190 | return SerializedHeader.takeError(); |
| 191 | Result.IncludeHeaders.push_back(*SerializedHeader); |
| 192 | } |
| 193 | Result.Flags = static_cast<clangd::Symbol::SymbolFlag>(Message.flags()); |
| 194 | return Result; |
| 195 | } |
| 196 | |
| 197 | llvm::Expected<clangd::Ref> Marshaller::fromProtobuf(const Ref &Message) { |
| 198 | if (!Message.has_location()) |
| 199 | return error(Fmt: "Missing location." ); |
| 200 | clangd::Ref Result; |
| 201 | auto Location = fromProtobuf(Message.location()); |
| 202 | if (!Location) |
| 203 | return Location.takeError(); |
| 204 | Result.Location = *Location; |
| 205 | Result.Kind = static_cast<RefKind>(Message.kind()); |
| 206 | auto ContainerID = SymbolID::fromStr(Message.container()); |
| 207 | if (ContainerID) |
| 208 | Result.Container = *ContainerID; |
| 209 | return Result; |
| 210 | } |
| 211 | |
| 212 | llvm::Expected<clangd::ContainedRefsResult> |
| 213 | Marshaller::fromProtobuf(const ContainedRef &Message) { |
| 214 | clangd::ContainedRefsResult Result; |
| 215 | if (!Message.has_location()) |
| 216 | return error(Fmt: "ContainedRef must have a location." ); |
| 217 | if (!Message.has_kind()) |
| 218 | return error(Fmt: "ContainedRef must have a kind." ); |
| 219 | if (!Message.has_symbol()) |
| 220 | return error(Fmt: "ContainedRef must have a symbol." ); |
| 221 | auto Location = fromProtobuf(Message.location()); |
| 222 | if (!Location) |
| 223 | return Location.takeError(); |
| 224 | Result.Location = *Location; |
| 225 | Result.Kind = static_cast<RefKind>(Message.kind()); |
| 226 | auto Symbol = SymbolID::fromStr(Message.symbol()); |
| 227 | if (!Symbol) |
| 228 | return Symbol.takeError(); |
| 229 | Result.Symbol = *Symbol; |
| 230 | return Result; |
| 231 | } |
| 232 | |
| 233 | llvm::Expected<std::pair<clangd::SymbolID, clangd::Symbol>> |
| 234 | Marshaller::fromProtobuf(const Relation &Message) { |
| 235 | auto SubjectID = SymbolID::fromStr(Message.subject_id()); |
| 236 | if (!SubjectID) |
| 237 | return SubjectID.takeError(); |
| 238 | if (!Message.has_object()) |
| 239 | return error(Fmt: "Missing Object." ); |
| 240 | auto Object = fromProtobuf(Message.object()); |
| 241 | if (!Object) |
| 242 | return Object.takeError(); |
| 243 | return std::make_pair(*SubjectID, *Object); |
| 244 | } |
| 245 | |
| 246 | LookupRequest Marshaller::toProtobuf(const clangd::LookupRequest &From) { |
| 247 | LookupRequest RPCRequest; |
| 248 | for (const auto &SymbolID : From.IDs) |
| 249 | RPCRequest.add_ids(SymbolID.str()); |
| 250 | return RPCRequest; |
| 251 | } |
| 252 | |
| 253 | FuzzyFindRequest Marshaller::toProtobuf(const clangd::FuzzyFindRequest &From) { |
| 254 | assert(!LocalIndexRoot.empty()); |
| 255 | FuzzyFindRequest RPCRequest; |
| 256 | RPCRequest.set_query(From.Query); |
| 257 | for (const auto &Scope : From.Scopes) |
| 258 | RPCRequest.add_scopes(Scope); |
| 259 | RPCRequest.set_any_scope(From.AnyScope); |
| 260 | if (From.Limit) |
| 261 | RPCRequest.set_limit(*From.Limit); |
| 262 | RPCRequest.set_restricted_for_code_completion(From.RestrictForCodeCompletion); |
| 263 | for (const auto &Path : From.ProximityPaths) { |
| 264 | llvm::SmallString<256> RelativePath = llvm::StringRef(Path); |
| 265 | if (replace_path_prefix(Path&: RelativePath, OldPrefix: LocalIndexRoot, NewPrefix: "" )) |
| 266 | RPCRequest.add_proximity_paths( |
| 267 | convert_to_slash(path: RelativePath, style: Style::windows)); |
| 268 | } |
| 269 | for (const auto &Type : From.PreferredTypes) |
| 270 | RPCRequest.add_preferred_types(Type); |
| 271 | return RPCRequest; |
| 272 | } |
| 273 | |
| 274 | RefsRequest Marshaller::toProtobuf(const clangd::RefsRequest &From) { |
| 275 | RefsRequest RPCRequest; |
| 276 | for (const auto &ID : From.IDs) |
| 277 | RPCRequest.add_ids(ID.str()); |
| 278 | RPCRequest.set_filter(static_cast<uint32_t>(From.Filter)); |
| 279 | if (From.Limit) |
| 280 | RPCRequest.set_limit(*From.Limit); |
| 281 | RPCRequest.set_want_container(From.WantContainer); |
| 282 | return RPCRequest; |
| 283 | } |
| 284 | |
| 285 | ContainedRefsRequest |
| 286 | Marshaller::toProtobuf(const clangd::ContainedRefsRequest &From) { |
| 287 | ContainedRefsRequest RPCRequest; |
| 288 | RPCRequest.set_id(From.ID.str()); |
| 289 | if (From.Limit) |
| 290 | RPCRequest.set_limit(*From.Limit); |
| 291 | return RPCRequest; |
| 292 | } |
| 293 | |
| 294 | RelationsRequest Marshaller::toProtobuf(const clangd::RelationsRequest &From) { |
| 295 | RelationsRequest RPCRequest; |
| 296 | for (const auto &ID : From.Subjects) |
| 297 | RPCRequest.add_subjects(ID.str()); |
| 298 | RPCRequest.set_predicate(static_cast<uint32_t>(From.Predicate)); |
| 299 | if (From.Limit) |
| 300 | RPCRequest.set_limit(*From.Limit); |
| 301 | return RPCRequest; |
| 302 | } |
| 303 | |
| 304 | llvm::Expected<Symbol> Marshaller::toProtobuf(const clangd::Symbol &From) { |
| 305 | Symbol Result; |
| 306 | Result.set_id(From.ID.str()); |
| 307 | *Result.mutable_info() = toProtobuf(Info: From.SymInfo); |
| 308 | Result.set_name(From.Name.str()); |
| 309 | if (*From.Definition.FileURI) { |
| 310 | auto Definition = toProtobuf(Location: From.Definition); |
| 311 | if (!Definition) |
| 312 | return Definition.takeError(); |
| 313 | *Result.mutable_definition() = *Definition; |
| 314 | } |
| 315 | Result.set_scope(From.Scope.str()); |
| 316 | auto Declaration = toProtobuf(Location: From.CanonicalDeclaration); |
| 317 | if (!Declaration) |
| 318 | return Declaration.takeError(); |
| 319 | *Result.mutable_canonical_declaration() = *Declaration; |
| 320 | Result.set_references(From.References); |
| 321 | Result.set_signature(From.Signature.str()); |
| 322 | Result.set_template_specialization_args( |
| 323 | From.TemplateSpecializationArgs.str()); |
| 324 | Result.set_completion_snippet_suffix(From.CompletionSnippetSuffix.str()); |
| 325 | Result.set_documentation(From.Documentation.str()); |
| 326 | Result.set_return_type(From.ReturnType.str()); |
| 327 | Result.set_type(From.Type.str()); |
| 328 | for (const auto & : From.IncludeHeaders) { |
| 329 | auto Serialized = toProtobuf(Header); |
| 330 | if (!Serialized) |
| 331 | return Serialized.takeError(); |
| 332 | auto * = Result.add_headers(); |
| 333 | *NextHeader = *Serialized; |
| 334 | } |
| 335 | Result.set_flags(static_cast<uint32_t>(From.Flags)); |
| 336 | return Result; |
| 337 | } |
| 338 | |
| 339 | llvm::Expected<Ref> Marshaller::toProtobuf(const clangd::Ref &From) { |
| 340 | Ref Result; |
| 341 | Result.set_kind(static_cast<uint32_t>(From.Kind)); |
| 342 | auto Location = toProtobuf(Location: From.Location); |
| 343 | if (!Location) |
| 344 | return Location.takeError(); |
| 345 | *Result.mutable_location() = *Location; |
| 346 | Result.set_container(From.Container.str()); |
| 347 | return Result; |
| 348 | } |
| 349 | |
| 350 | llvm::Expected<ContainedRef> |
| 351 | Marshaller::toProtobuf(const clangd::ContainedRefsResult &From) { |
| 352 | ContainedRef Result; |
| 353 | auto Location = toProtobuf(Location: From.Location); |
| 354 | if (!Location) |
| 355 | return Location.takeError(); |
| 356 | *Result.mutable_location() = *Location; |
| 357 | Result.set_kind(static_cast<uint32_t>(From.Kind)); |
| 358 | *Result.mutable_symbol() = From.Symbol.str(); |
| 359 | return Result; |
| 360 | } |
| 361 | |
| 362 | llvm::Expected<Relation> Marshaller::toProtobuf(const clangd::SymbolID &Subject, |
| 363 | const clangd::Symbol &Object) { |
| 364 | Relation Result; |
| 365 | *Result.mutable_subject_id() = Subject.str(); |
| 366 | auto SerializedObject = toProtobuf(From: Object); |
| 367 | if (!SerializedObject) |
| 368 | return SerializedObject.takeError(); |
| 369 | *Result.mutable_object() = *SerializedObject; |
| 370 | return Result; |
| 371 | } |
| 372 | |
| 373 | llvm::Expected<std::string> |
| 374 | Marshaller::relativePathToURI(llvm::StringRef RelativePath) { |
| 375 | assert(!LocalIndexRoot.empty()); |
| 376 | assert(RelativePath == convert_to_slash(RelativePath)); |
| 377 | if (RelativePath.empty()) |
| 378 | return error(Fmt: "Empty relative path." ); |
| 379 | if (is_absolute(path: RelativePath, style: Style::posix)) |
| 380 | return error(Fmt: "RelativePath '{0}' is absolute." , Vals&: RelativePath); |
| 381 | llvm::SmallString<256> FullPath = llvm::StringRef(LocalIndexRoot); |
| 382 | append(path&: FullPath, a: RelativePath); |
| 383 | auto Result = URI::createFile(AbsolutePath: FullPath); |
| 384 | return Result.toString(); |
| 385 | } |
| 386 | |
| 387 | llvm::Expected<std::string> Marshaller::uriToRelativePath(llvm::StringRef URI) { |
| 388 | assert(!RemoteIndexRoot.empty()); |
| 389 | auto ParsedURI = URI::parse(Uri: URI); |
| 390 | if (!ParsedURI) |
| 391 | return ParsedURI.takeError(); |
| 392 | if (ParsedURI->scheme() != "file" ) |
| 393 | return error(Fmt: "Can not use URI schemes other than file, given: '{0}'." , Vals&: URI); |
| 394 | llvm::SmallString<256> Result = ParsedURI->body(); |
| 395 | llvm::StringRef Path(Result); |
| 396 | // Check for Windows paths (URI=file:///X:/path => Body=/X:/path) |
| 397 | if (is_absolute(path: Path.substr(Start: 1), style: Style::windows)) |
| 398 | Result = Path.drop_front(); |
| 399 | if (!replace_path_prefix(Path&: Result, OldPrefix: RemoteIndexRoot, NewPrefix: "" )) |
| 400 | return error(Fmt: "File path '{0}' doesn't start with '{1}'." , Vals: Result.str(), |
| 401 | Vals&: RemoteIndexRoot); |
| 402 | assert(Result == convert_to_slash(Result, Style::windows)); |
| 403 | return std::string(Result); |
| 404 | } |
| 405 | |
| 406 | clangd::SymbolLocation::Position |
| 407 | Marshaller::fromProtobuf(const Position &Message) { |
| 408 | clangd::SymbolLocation::Position Result; |
| 409 | Result.setColumn(static_cast<uint32_t>(Message.column())); |
| 410 | Result.setLine(static_cast<uint32_t>(Message.line())); |
| 411 | return Result; |
| 412 | } |
| 413 | |
| 414 | Position |
| 415 | Marshaller::toProtobuf(const clangd::SymbolLocation::Position &Position) { |
| 416 | remote::Position Result; |
| 417 | Result.set_column(Position.column()); |
| 418 | Result.set_line(Position.line()); |
| 419 | return Result; |
| 420 | } |
| 421 | |
| 422 | clang::index::SymbolInfo Marshaller::fromProtobuf(const SymbolInfo &Message) { |
| 423 | clang::index::SymbolInfo Result; |
| 424 | Result.Kind = static_cast<clang::index::SymbolKind>(Message.kind()); |
| 425 | Result.SubKind = static_cast<clang::index::SymbolSubKind>(Message.subkind()); |
| 426 | Result.Lang = static_cast<clang::index::SymbolLanguage>(Message.language()); |
| 427 | Result.Properties = |
| 428 | static_cast<clang::index::SymbolPropertySet>(Message.properties()); |
| 429 | return Result; |
| 430 | } |
| 431 | |
| 432 | SymbolInfo Marshaller::toProtobuf(const clang::index::SymbolInfo &Info) { |
| 433 | SymbolInfo Result; |
| 434 | Result.set_kind(static_cast<uint32_t>(Info.Kind)); |
| 435 | Result.set_subkind(static_cast<uint32_t>(Info.SubKind)); |
| 436 | Result.set_language(static_cast<uint32_t>(Info.Lang)); |
| 437 | Result.set_properties(static_cast<uint32_t>(Info.Properties)); |
| 438 | return Result; |
| 439 | } |
| 440 | |
| 441 | llvm::Expected<clangd::SymbolLocation> |
| 442 | Marshaller::fromProtobuf(const SymbolLocation &Message) { |
| 443 | clangd::SymbolLocation Location; |
| 444 | auto URIString = relativePathToURI(RelativePath: Message.file_path()); |
| 445 | if (!URIString) |
| 446 | return URIString.takeError(); |
| 447 | Location.FileURI = Strings.save(*URIString).begin(); |
| 448 | Location.Start = fromProtobuf(Message.start()); |
| 449 | Location.End = fromProtobuf(Message.end()); |
| 450 | return Location; |
| 451 | } |
| 452 | |
| 453 | llvm::Expected<SymbolLocation> |
| 454 | Marshaller::toProtobuf(const clangd::SymbolLocation &Location) { |
| 455 | remote::SymbolLocation Result; |
| 456 | auto RelativePath = uriToRelativePath(URI: Location.FileURI); |
| 457 | if (!RelativePath) |
| 458 | return RelativePath.takeError(); |
| 459 | *Result.mutable_file_path() = *RelativePath; |
| 460 | *Result.mutable_start() = toProtobuf(Position: Location.Start); |
| 461 | *Result.mutable_end() = toProtobuf(Position: Location.End); |
| 462 | return Result; |
| 463 | } |
| 464 | |
| 465 | llvm::Expected<HeaderWithReferences> Marshaller::( |
| 466 | const clangd::Symbol::IncludeHeaderWithReferences &) { |
| 467 | HeaderWithReferences Result; |
| 468 | Result.set_references(IncludeHeader.References); |
| 469 | Result.set_supported_directives(IncludeHeader.SupportedDirectives); |
| 470 | const std::string = IncludeHeader.IncludeHeader.str(); |
| 471 | if (isLiteralInclude(Include: Header)) { |
| 472 | Result.set_header(Header); |
| 473 | return Result; |
| 474 | } |
| 475 | auto RelativePath = uriToRelativePath(URI: Header); |
| 476 | if (!RelativePath) |
| 477 | return RelativePath.takeError(); |
| 478 | Result.set_header(*RelativePath); |
| 479 | return Result; |
| 480 | } |
| 481 | |
| 482 | llvm::Expected<clangd::Symbol::IncludeHeaderWithReferences> |
| 483 | Marshaller::fromProtobuf(const HeaderWithReferences &Message) { |
| 484 | std::string = Message.header(); |
| 485 | if (!isLiteralInclude(Include: Header)) { |
| 486 | auto URIString = relativePathToURI(RelativePath: Header); |
| 487 | if (!URIString) |
| 488 | return URIString.takeError(); |
| 489 | Header = *URIString; |
| 490 | } |
| 491 | auto Directives = clangd::Symbol::IncludeDirective::Include; |
| 492 | if (Message.has_supported_directives()) |
| 493 | Directives = static_cast<clangd::Symbol::IncludeDirective>( |
| 494 | Message.supported_directives()); |
| 495 | return clangd::Symbol::IncludeHeaderWithReferences{ |
| 496 | Strings.save(S: Header), Message.references(), Directives}; |
| 497 | } |
| 498 | |
| 499 | } // namespace remote |
| 500 | } // namespace clangd |
| 501 | } // namespace clang |
| 502 | |