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<std::pair<clangd::SymbolID, clangd::Symbol>> 44 fromProtobuf(const Relation &Message); 45 46 llvm::Expected<clangd::LookupRequest> 47 fromProtobuf(const LookupRequest *Message); 48 llvm::Expected<clangd::FuzzyFindRequest> 49 fromProtobuf(const FuzzyFindRequest *Message); 50 llvm::Expected<clangd::RefsRequest> fromProtobuf(const RefsRequest *Message); 51 llvm::Expected<clangd::RelationsRequest> 52 fromProtobuf(const RelationsRequest *Message); 53 54 /// toProtobuf() functions serialize native clangd types and strip IndexRoot 55 /// from the file paths specific to indexing machine. fromProtobuf() functions 56 /// deserialize clangd types and translate relative paths into machine-native 57 /// URIs. 58 LookupRequest toProtobuf(const clangd::LookupRequest &From); 59 FuzzyFindRequest toProtobuf(const clangd::FuzzyFindRequest &From); 60 RefsRequest toProtobuf(const clangd::RefsRequest &From); 61 RelationsRequest toProtobuf(const clangd::RelationsRequest &From); 62 63 llvm::Expected<Symbol> toProtobuf(const clangd::Symbol &From); 64 llvm::Expected<Ref> toProtobuf(const clangd::Ref &From); 65 llvm::Expected<Relation> toProtobuf(const clangd::SymbolID &Subject, 66 const clangd::Symbol &Object); 67 68 /// Translates \p RelativePath into the absolute path and builds URI for the 69 /// user machine. This translation happens on the client side with the 70 /// \p RelativePath received from remote index server and \p IndexRoot is 71 /// provided by the client. 72 /// 73 /// The relative path passed over the wire has unix slashes. 74 llvm::Expected<std::string> relativePathToURI(llvm::StringRef RelativePath); 75 /// Translates a URI from the server's backing index to a relative path 76 /// suitable to send over the wire to the client. 77 llvm::Expected<std::string> uriToRelativePath(llvm::StringRef URI); 78 79 private: 80 clangd::SymbolLocation::Position fromProtobuf(const Position &Message); 81 Position toProtobuf(const clangd::SymbolLocation::Position &Position); 82 clang::index::SymbolInfo fromProtobuf(const SymbolInfo &Message); 83 SymbolInfo toProtobuf(const clang::index::SymbolInfo &Info); 84 llvm::Expected<clangd::SymbolLocation> 85 fromProtobuf(const SymbolLocation &Message); 86 llvm::Expected<SymbolLocation> 87 toProtobuf(const clangd::SymbolLocation &Location); 88 llvm::Expected<HeaderWithReferences> 89 toProtobuf(const clangd::Symbol::IncludeHeaderWithReferences &IncludeHeader); 90 llvm::Expected<clangd::Symbol::IncludeHeaderWithReferences> 91 fromProtobuf(const HeaderWithReferences &Message); 92 93 /// RemoteIndexRoot and LocalIndexRoot are absolute paths to the project (on 94 /// remote and local machine respectively) and include a trailing slash. One 95 /// of them can be missing (if the machines are different they don't know each 96 /// other's specifics and will only do one-way translation), but both can not 97 /// be missing at the same time. 98 std::string RemoteIndexRoot; 99 std::string LocalIndexRoot; 100 llvm::BumpPtrAllocator Arena; 101 llvm::UniqueStringSaver Strings; 102 }; 103 104 } // namespace remote 105 } // namespace clangd 106 } // namespace clang 107 108 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_REMOTE_MARSHALLING_H 109