12#include "llvm/Support/Error.h"
13#include "llvm/Support/Path.h"
24 if (!S.starts_with(
"file://"))
28 llvm::consumeError(Uri.takeError());
31 for (
const auto &Mapping : Mappings) {
38 llvm::StringRef Body = Uri->body();
39 if (Body.consume_front(From) && (Body.empty() || Body.front() ==
'/')) {
40 std::string MappedBody = (To + Body).str();
41 return URI(Uri->scheme(), Uri->authority(), MappedBody)
50 using Kind = llvm::json::Value::Kind;
52 if (
K == Kind::Object) {
53 llvm::json::Object *
Obj = V.getAsObject();
54 llvm::json::Object MappedObj;
56 for (
auto &KV : *
Obj) {
57 if (std::optional<std::string> MappedKey =
59 MappedObj.try_emplace(std::move(*MappedKey), std::move(KV.second));
61 MappedObj.try_emplace(std::move(KV.first), std::move(KV.second));
64 *
Obj = std::move(MappedObj);
68 }
else if (
K == Kind::Array) {
69 for (llvm::json::Value &Val : *V.getAsArray())
71 }
else if (
K == Kind::String) {
72 if (std::optional<std::string> Mapped =
74 V = std::move(*Mapped);
80class PathMappingMessageHandler :
public Transport::MessageHandler {
82 PathMappingMessageHandler(MessageHandler &Handler,
84 : WrappedHandler(Handler), Mappings(Mappings) {}
86 bool onNotify(llvm::StringRef
Method, llvm::json::Value Params)
override {
88 return WrappedHandler.onNotify(
Method, std::move(Params));
91 bool onCall(llvm::StringRef
Method, llvm::json::Value Params,
92 llvm::json::Value
ID)
override {
94 return WrappedHandler.onCall(
Method, std::move(Params), std::move(
ID));
97 bool onReply(llvm::json::Value
ID,
98 llvm::Expected<llvm::json::Value> Result)
override {
102 return WrappedHandler.onReply(std::move(
ID), std::move(Result));
106 Transport::MessageHandler &WrappedHandler;
112class PathMappingTransport :
public Transport {
114 PathMappingTransport(std::unique_ptr<Transport> Transp,
PathMappings Mappings)
115 : WrappedTransport(std::move(Transp)), Mappings(std::move(Mappings)) {}
117 void notify(llvm::StringRef
Method, llvm::json::Value Params)
override {
119 WrappedTransport->notify(
Method, std::move(Params));
122 void call(llvm::StringRef
Method, llvm::json::Value Params,
123 llvm::json::Value
ID)
override {
125 WrappedTransport->call(
Method, std::move(Params), std::move(
ID));
128 void reply(llvm::json::Value
ID,
129 llvm::Expected<llvm::json::Value> Result)
override {
133 WrappedTransport->reply(std::move(
ID), std::move(Result));
136 llvm::Error loop(MessageHandler &Handler)
override {
137 PathMappingMessageHandler WrappedHandler(Handler, Mappings);
138 return WrappedTransport->loop(WrappedHandler);
142 std::unique_ptr<Transport> WrappedTransport;
148llvm::Expected<std::string> parsePath(llvm::StringRef
Path) {
149 namespace path = llvm::sys::path;
150 if (path::is_absolute(
Path, path::Style::posix)) {
151 return std::string(
Path);
153 if (path::is_absolute(
Path, path::Style::windows)) {
154 std::string Converted = path::convert_to_slash(
Path, path::Style::windows);
155 if (Converted.front() !=
'/')
156 Converted =
"/" + Converted;
159 return error(
"Path not absolute: {0}",
Path);
165 return OS <<
M.ClientPath <<
"=" <<
M.ServerPath;
168llvm::Expected<PathMappings>
170 llvm::StringRef ClientPath, ServerPath, PathPair, Rest = RawPathMappings;
172 while (!Rest.empty()) {
173 std::tie(PathPair, Rest) = Rest.split(
",");
174 std::tie(ClientPath, ServerPath) = PathPair.split(
"=");
175 if (ClientPath.empty() || ServerPath.empty())
176 return error(
"Not a valid path mapping pair: {0}", PathPair);
177 llvm::Expected<std::string> ParsedClientPath = parsePath(ClientPath);
178 if (!ParsedClientPath)
179 return ParsedClientPath.takeError();
180 llvm::Expected<std::string> ParsedServerPath = parsePath(ServerPath);
181 if (!ParsedServerPath)
182 return ParsedServerPath.takeError();
183 ParsedMappings.push_back(
184 {std::move(*ParsedClientPath), std::move(*ParsedServerPath)});
186 return ParsedMappings;
189std::unique_ptr<Transport>
192 return std::make_unique<PathMappingTransport>(std::move(Transp), Mappings);
enum clang::clangd::@1062::Bracket::Direction Dir
const google::protobuf::Message & M
A URI describes the location of a source file.
std::string toString() const
Returns a string URI with all components percent-encoded.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
std::string Path
A typedef to represent a file path.
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
llvm::Expected< PathMappings > parsePathMappings(llvm::StringRef RawPathMappings)
Parse the command line RawPathMappings (e.g.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
void applyPathMappings(llvm::json::Value &V, PathMapping::Direction Dir, const PathMappings &Mappings)
Applies the Mappings to all the file:// URIs in Params.
std::vector< PathMapping > PathMappings
std::unique_ptr< Transport > createPathMappingTransport(std::unique_ptr< Transport > Transp, PathMappings Mappings)
Creates a wrapping transport over Transp that applies the Mappings to all inbound and outbound LSP me...
std::optional< std::string > doPathMapping(llvm::StringRef S, PathMapping::Direction Dir, const PathMappings &Mappings)
Returns a modified S with the first matching path in Mappings substituted, if applicable.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
PathMappings are a collection of paired client and server paths.