1 | //===--- PathMapping.h - apply path mappings to LSP messages -===// |
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_PATHMAPPING_H |
10 | #define |
11 | |
12 | #include "llvm/ADT/StringRef.h" |
13 | #include "llvm/Support/Error.h" |
14 | #include "llvm/Support/JSON.h" |
15 | #include "llvm/Support/raw_ostream.h" |
16 | #include <memory> |
17 | #include <optional> |
18 | #include <string> |
19 | #include <vector> |
20 | |
21 | namespace clang { |
22 | namespace clangd { |
23 | |
24 | class Transport; |
25 | |
26 | /// PathMappings are a collection of paired client and server paths. |
27 | /// These pairs are used to alter file:// URIs appearing in inbound and outbound |
28 | /// LSP messages, as the client's environment may have source files or |
29 | /// dependencies at different locations than the server. Therefore, both |
30 | /// paths are stored as they appear in file URI bodies, e.g. /usr/include or |
31 | /// /C:/config |
32 | /// |
33 | /// For example, if the mappings were {{"/home/user", "/workarea"}}, then |
34 | /// a client-to-server LSP message would have file:///home/user/foo.cpp |
35 | /// remapped to file:///workarea/foo.cpp, and the same would happen for replies |
36 | /// (in the opposite order). |
37 | struct PathMapping { |
38 | std::string ClientPath; |
39 | std::string ServerPath; |
40 | enum class Direction { ClientToServer, ServerToClient }; |
41 | }; |
42 | using PathMappings = std::vector<PathMapping>; |
43 | |
44 | llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PathMapping &M); |
45 | |
46 | /// Parse the command line \p RawPathMappings (e.g. "/client=/server") into |
47 | /// pairs. Returns an error if the mappings are malformed, i.e. not absolute or |
48 | /// not a proper pair. |
49 | llvm::Expected<PathMappings> parsePathMappings(llvm::StringRef RawPathMappings); |
50 | |
51 | /// Returns a modified \p S with the first matching path in \p Mappings |
52 | /// substituted, if applicable |
53 | std::optional<std::string> doPathMapping(llvm::StringRef S, |
54 | PathMapping::Direction Dir, |
55 | const PathMappings &Mappings); |
56 | |
57 | /// Applies the \p Mappings to all the file:// URIs in \p Params. |
58 | /// NOTE: The first matching mapping will be applied, otherwise \p Params will |
59 | /// be untouched. |
60 | void applyPathMappings(llvm::json::Value &Params, PathMapping::Direction Dir, |
61 | const PathMappings &Mappings); |
62 | |
63 | /// Creates a wrapping transport over \p Transp that applies the \p Mappings to |
64 | /// all inbound and outbound LSP messages. All calls are then delegated to the |
65 | /// regular transport (e.g. XPC, JSON). |
66 | std::unique_ptr<Transport> |
67 | createPathMappingTransport(std::unique_ptr<Transport> Transp, |
68 | PathMappings Mappings); |
69 | |
70 | } // namespace clangd |
71 | } // namespace clang |
72 | |
73 | #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PATHMAPPING_H |
74 | |