1 //===--- Marshalling.h -------------------------------------------*- 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H 11 12 #include "Index.pb.h" 13 #include "index/Index.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Support/StringSaver.h" 16 17 namespace clang { 18 namespace clangd { 19 namespace remote { 20 21 // Marshalling provides an interface for translattion between native clangd 22 // types into the Protobuf-generated classes. Most translations are 1-to-1 and 23 // wrap variables into appropriate Protobuf types. 24 // 25 /// A notable exception is URI translation. Because paths to files are different 26 /// on indexing machine and client machine 27 /// ("/remote/machine/projects/llvm-project/llvm/include/HelloWorld.h" versus 28 /// "/usr/local/username/llvm-project/llvm/include/HelloWorld.h"), they need to 29 /// be converted appropriately. Remote machine strips the prefix 30 /// (RemoteIndexRoot) from the absolute path and passes paths relative to the 31 /// project root over the wire ("include/HelloWorld.h" in this example). The 32 /// indexed project root is passed to the remote server. Client receives this 33 /// relative path and constructs a URI that points to the relevant file in the 34 /// filesystem. The relative path is appended to LocalIndexRoot to construct the 35 /// full path and build the final URI. 36 class Marshaller { 37 public: 38 Marshaller() = delete; 39 Marshaller(llvm::StringRef RemoteIndexRoot, llvm::StringRef LocalIndexRoot); 40 41 llvm::Expected<clangd::Symbol> fromProtobuf(const Symbol &Message); 42 llvm::Expected<clangd::Ref> fromProtobuf(const Ref &Message); 43 llvm::Expected<clangd::ContainedRefsResult> 44 fromProtobuf(const ContainedRef &Message); 45 llvm::Expected<std::pair<clangd::SymbolID, clangd::Symbol>> 46 fromProtobuf(const Relation &Message); 47 48 llvm::Expected<clangd::LookupRequest> 49 fromProtobuf(const LookupRequest *Message); 50 llvm::Expected<clangd::FuzzyFindRequest> 51 fromProtobuf(const FuzzyFindRequest *Message); 52 llvm::Expected<clangd::RefsRequest> fromProtobuf(const RefsRequest *Message); 53 llvm::Expected<clangd::ContainedRefsRequest> 54 fromProtobuf(const ContainedRefsRequest *Message); 55 llvm::Expected<clangd::RelationsRequest> 56 fromProtobuf(const RelationsRequest *Message); 57 58 /// toProtobuf() functions serialize native clangd types and strip IndexRoot 59 /// from the file paths specific to indexing machine. fromProtobuf() functions 60 /// deserialize clangd types and translate relative paths into machine-native 61 /// URIs. 62 LookupRequest toProtobuf(const clangd::LookupRequest &From); 63 FuzzyFindRequest toProtobuf(const clangd::FuzzyFindRequest &From); 64 RefsRequest toProtobuf(const clangd::RefsRequest &From); 65 ContainedRefsRequest toProtobuf(const clangd::ContainedRefsRequest &From); 66 RelationsRequest toProtobuf(const clangd::RelationsRequest &From); 67 68 llvm::Expected<Symbol> toProtobuf(const clangd::Symbol &From); 69 llvm::Expected<Ref> toProtobuf(const clangd::Ref &From); 70 llvm::Expected<ContainedRef> 71 toProtobuf(const clangd::ContainedRefsResult &From); 72 llvm::Expected<Relation> toProtobuf(const clangd::SymbolID &Subject, 73 const clangd::Symbol &Object); 74 75 /// Translates \p RelativePath into the absolute path and builds URI for the 76 /// user machine. This translation happens on the client side with the 77 /// \p RelativePath received from remote index server and \p IndexRoot is 78 /// provided by the client. 79 /// 80 /// The relative path passed over the wire has unix slashes. 81 llvm::Expected<std::string> relativePathToURI(llvm::StringRef RelativePath); 82 /// Translates a URI from the server's backing index to a relative path 83 /// suitable to send over the wire to the client. 84 llvm::Expected<std::string> uriToRelativePath(llvm::StringRef URI); 85 86 private: 87 clangd::SymbolLocation::Position fromProtobuf(const Position &Message); 88 Position toProtobuf(const clangd::SymbolLocation::Position &Position); 89 clang::index::SymbolInfo fromProtobuf(const SymbolInfo &Message); 90 SymbolInfo toProtobuf(const clang::index::SymbolInfo &Info); 91 llvm::Expected<clangd::SymbolLocation> 92 fromProtobuf(const SymbolLocation &Message); 93 llvm::Expected<SymbolLocation> 94 toProtobuf(const clangd::SymbolLocation &Location); 95 llvm::Expected<HeaderWithReferences> 96 toProtobuf(const clangd::Symbol::IncludeHeaderWithReferences &IncludeHeader); 97 llvm::Expected<clangd::Symbol::IncludeHeaderWithReferences> 98 fromProtobuf(const HeaderWithReferences &Message); 99 100 /// RemoteIndexRoot and LocalIndexRoot are absolute paths to the project (on 101 /// remote and local machine respectively) and include a trailing slash. One 102 /// of them can be missing (if the machines are different they don't know each 103 /// other's specifics and will only do one-way translation), but both can not 104 /// be missing at the same time. 105 std::string RemoteIndexRoot; 106 std::string LocalIndexRoot; 107 llvm::BumpPtrAllocator Arena; 108 llvm::UniqueStringSaver Strings; 109 }; 110 111 } // namespace remote 112 } // namespace clangd 113 } // namespace clang 114 115 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H 116