brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.1 KiB · aa60792 Raw
502 lines · cpp
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-exception6//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 31namespace clang {32namespace clangd {33namespace remote {34 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;40 41namespace {42 43template <typename IDRange>44llvm::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(*SID);51  }52  return Result;53}54 55} // namespace56 57Marshaller::Marshaller(llvm::StringRef RemoteIndexRoot,58                       llvm::StringRef LocalIndexRoot)59    : Strings(Arena) {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;67  }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;74  }75  assert(!RemoteIndexRoot.empty() || !LocalIndexRoot.empty());76}77 78llvm::Expected<clangd::LookupRequest>79Marshaller::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 88llvm::Expected<clangd::FuzzyFindRequest>89Marshaller::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 format103    // 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 112llvm::Expected<clangd::RefsRequest>113Marshaller::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  else122    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 129llvm::Expected<clangd::ContainedRefsRequest>130Marshaller::fromProtobuf(const ContainedRefsRequest *Message) {131  clangd::ContainedRefsRequest Req;132  if (!Message->has_id())133    return error("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 143llvm::Expected<clangd::RelationsRequest>144Marshaller::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("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 158llvm::Expected<clangd::Symbol> Marshaller::fromProtobuf(const Symbol &Message) {159  if (!Message.has_info() || !Message.has_canonical_declaration())160    return error("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 197llvm::Expected<clangd::Ref> Marshaller::fromProtobuf(const Ref &Message) {198  if (!Message.has_location())199    return error("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 212llvm::Expected<clangd::ContainedRefsResult>213Marshaller::fromProtobuf(const ContainedRef &Message) {214  clangd::ContainedRefsResult Result;215  if (!Message.has_location())216    return error("ContainedRef must have a location.");217  if (!Message.has_kind())218    return error("ContainedRef must have a kind.");219  if (!Message.has_symbol())220    return error("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 233llvm::Expected<std::pair<clangd::SymbolID, clangd::Symbol>>234Marshaller::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("Missing Object.");240  auto Object = fromProtobuf(Message.object());241  if (!Object)242    return Object.takeError();243  return std::make_pair(*SubjectID, *Object);244}245 246LookupRequest 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 253FuzzyFindRequest 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(RelativePath, LocalIndexRoot, ""))266      RPCRequest.add_proximity_paths(267          convert_to_slash(RelativePath, Style::windows));268  }269  for (const auto &Type : From.PreferredTypes)270    RPCRequest.add_preferred_types(Type);271  return RPCRequest;272}273 274RefsRequest 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 285ContainedRefsRequest286Marshaller::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 294RelationsRequest 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 304llvm::Expected<Symbol> Marshaller::toProtobuf(const clangd::Symbol &From) {305  Symbol Result;306  Result.set_id(From.ID.str());307  *Result.mutable_info() = toProtobuf(From.SymInfo);308  Result.set_name(From.Name.str());309  if (*From.Definition.FileURI) {310    auto Definition = toProtobuf(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(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 &Header : From.IncludeHeaders) {329    auto Serialized = toProtobuf(Header);330    if (!Serialized)331      return Serialized.takeError();332    auto *NextHeader = Result.add_headers();333    *NextHeader = *Serialized;334  }335  Result.set_flags(static_cast<uint32_t>(From.Flags));336  return Result;337}338 339llvm::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(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 350llvm::Expected<ContainedRef>351Marshaller::toProtobuf(const clangd::ContainedRefsResult &From) {352  ContainedRef Result;353  auto Location = toProtobuf(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 362llvm::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(Object);367  if (!SerializedObject)368    return SerializedObject.takeError();369  *Result.mutable_object() = *SerializedObject;370  return Result;371}372 373llvm::Expected<std::string>374Marshaller::relativePathToURI(llvm::StringRef RelativePath) {375  assert(!LocalIndexRoot.empty());376  assert(RelativePath == convert_to_slash(RelativePath));377  if (RelativePath.empty())378    return error("Empty relative path.");379  if (is_absolute(RelativePath, Style::posix))380    return error("RelativePath '{0}' is absolute.", RelativePath);381  llvm::SmallString<256> FullPath = llvm::StringRef(LocalIndexRoot);382  append(FullPath, RelativePath);383  auto Result = URI::createFile(FullPath);384  return Result.toString();385}386 387llvm::Expected<std::string> Marshaller::uriToRelativePath(llvm::StringRef URI) {388  assert(!RemoteIndexRoot.empty());389  auto ParsedURI = URI::parse(URI);390  if (!ParsedURI)391    return ParsedURI.takeError();392  if (ParsedURI->scheme() != "file")393    return error("Can not use URI schemes other than file, given: '{0}'.", 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.substr(1), Style::windows))398    Result = Path.drop_front();399  if (!replace_path_prefix(Result, RemoteIndexRoot, ""))400    return error("File path '{0}' doesn't start with '{1}'.", Result.str(),401                 RemoteIndexRoot);402  assert(Result == convert_to_slash(Result, Style::windows));403  return std::string(Result);404}405 406clangd::SymbolLocation::Position407Marshaller::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 414Position415Marshaller::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 422clang::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 432SymbolInfo 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 441llvm::Expected<clangd::SymbolLocation>442Marshaller::fromProtobuf(const SymbolLocation &Message) {443  clangd::SymbolLocation Location;444  auto URIString = relativePathToURI(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 453llvm::Expected<SymbolLocation>454Marshaller::toProtobuf(const clangd::SymbolLocation &Location) {455  remote::SymbolLocation Result;456  auto RelativePath = uriToRelativePath(Location.FileURI);457  if (!RelativePath)458    return RelativePath.takeError();459  *Result.mutable_file_path() = *RelativePath;460  *Result.mutable_start() = toProtobuf(Location.Start);461  *Result.mutable_end() = toProtobuf(Location.End);462  return Result;463}464 465llvm::Expected<HeaderWithReferences> Marshaller::toProtobuf(466    const clangd::Symbol::IncludeHeaderWithReferences &IncludeHeader) {467  HeaderWithReferences Result;468  Result.set_references(IncludeHeader.References);469  Result.set_supported_directives(IncludeHeader.SupportedDirectives);470  const std::string Header = IncludeHeader.IncludeHeader.str();471  if (isLiteralInclude(Header)) {472    Result.set_header(Header);473    return Result;474  }475  auto RelativePath = uriToRelativePath(Header);476  if (!RelativePath)477    return RelativePath.takeError();478  Result.set_header(*RelativePath);479  return Result;480}481 482llvm::Expected<clangd::Symbol::IncludeHeaderWithReferences>483Marshaller::fromProtobuf(const HeaderWithReferences &Message) {484  std::string Header = Message.header();485  if (!isLiteralInclude(Header)) {486    auto URIString = relativePathToURI(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(Header), Message.references(), Directives};497}498 499} // namespace remote500} // namespace clangd501} // namespace clang502