diff --git a/LSP.sublime-settings b/LSP.sublime-settings index 6cb35033c..d5ed44adc 100644 --- a/LSP.sublime-settings +++ b/LSP.sublime-settings @@ -342,6 +342,15 @@ // // If the server supports `diagnosticProvider.workspaceDiagnostics`, // // diagnostics are requested for all files in the project folders. // "diagnostics_mode": "open_files", + // + // // Map the paths of URIs in the data exchanged between the server and the client. + // // + // // WARNING: Due to its working principle of modifying the interaction data between + // // the client and the server, it cannot identify the source of the content in the + // // data. If your code file happens to start with a URI and meets the mapping conditions, + // // it may inadvertently send incorrect messages to the server. However, such situations + // // should be virtually nonexistent. + // "path_maps": [ {"local": "file:///C:", "remote": "file:///mnt/c"} ] // } // } "clients": {}, diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 79f8a3d5c..79e6a6bf1 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -2383,6 +2383,7 @@ def exit(self) -> None: def send_payload(self, payload: dict[str, Any]) -> None: try: + payload = self.config.map_uri_on_payload(payload, is_from_client_to_server=True) self.transport.send(payload) # type: ignore except AttributeError: pass @@ -2425,6 +2426,7 @@ def deduce_payload( return (None, None, None, None, None) def on_payload(self, payload: dict[str, Any]) -> None: + payload = self.config.map_uri_on_payload(payload, is_from_client_to_server=False) handler, result, req_id, typestr, _method = self.deduce_payload(payload) if handler: try: diff --git a/plugin/core/types.py b/plugin/core/types.py index b5d5b932f..fafed05c4 100644 --- a/plugin/core/types.py +++ b/plugin/core/types.py @@ -854,24 +854,23 @@ def match_view(self, view: sublime.View, scheme: str) -> bool: return False return scheme in self.schemes and sublime.score_selector(syntax.scope, selector) > 0 - def map_client_path_to_server_uri(self, path: str) -> str: - if self.path_maps: - for path_map in self.path_maps: - path, mapped = path_map.map_from_local_to_remote(path) - if mapped: - break - return filename_to_uri(path) - - def map_server_uri_to_client_path(self, uri: str) -> str: - scheme, path = parse_uri(uri) - if scheme not in ("file", "res"): - raise ValueError(f"{uri}: {scheme} URI scheme is unsupported") - if self.path_maps: + def map_uri_on_payload(self, payload: Any, is_from_client_to_server: bool) -> Any: + if isinstance(payload, dict): + for k, v in payload.items(): + payload[k] = self.map_uri_on_payload(v, is_from_client_to_server) + + if isinstance(payload, list): + for i, v in enumerate(payload): + payload[i] = self.map_uri_on_payload(v, is_from_client_to_server) + + if isinstance(payload, str) and payload.startswith("file://"): for path_map in self.path_maps: - path, mapped = path_map.map_from_remote_to_local(path) + path, mapped = path_map.map_from_local_to_remote(payload) if is_from_client_to_server else \ + path_map.map_from_remote_to_local(payload) if mapped: - break - return path + payload = path + + return payload def is_disabled_capability(self, capability_path: str) -> bool: for value in self.disabled_capabilities.walk(capability_path): diff --git a/plugin/core/views.py b/plugin/core/views.py index 654fabef7..46b0581c7 100644 --- a/plugin/core/views.py +++ b/plugin/core/views.py @@ -771,7 +771,7 @@ def location_to_human_readable( scheme, _ = parse_uri(uri) if scheme == "file": fmt = "{}:{}" - pathname = config.map_server_uri_to_client_path(uri) + pathname = parse_uri(uri)[1] if base_dir and is_subpath_of(pathname, base_dir): pathname = pathname[len(os.path.commonprefix((pathname, base_dir))) + 1:] elif scheme == "res": diff --git a/plugin/goto_diagnostic.py b/plugin/goto_diagnostic.py index 5f3018481..e5b01b045 100644 --- a/plugin/goto_diagnostic.py +++ b/plugin/goto_diagnostic.py @@ -265,7 +265,7 @@ def open_location( session: Session, location: Location, flags: sublime.NewFileFlags = sublime.NewFileFlags.NONE, group: int = -1 ) -> sublime.View: uri, position = get_uri_and_position_from_location(location) - file_name = to_encoded_filename(session.config.map_server_uri_to_client_path(uri), position) + file_name = to_encoded_filename(parse_uri(uri)[1], position) return session.window.open_file(file_name, flags=flags | sublime.NewFileFlags.ENCODED_POSITION, group=group) diff --git a/plugin/locationpicker.py b/plugin/locationpicker.py index 97d5f73b0..0854f4b16 100644 --- a/plugin/locationpicker.py +++ b/plugin/locationpicker.py @@ -7,6 +7,7 @@ from .core.protocol import LocationLink from .core.protocol import Position from .core.sessions import Session +from .core.url import parse_uri from .core.views import get_uri_and_position_from_location from .core.views import location_to_human_readable from .core.views import to_encoded_filename @@ -49,7 +50,7 @@ def open_basic_file( if group is None: group = session.window.active_group() if uri.startswith("file:"): - filename = session.config.map_server_uri_to_client_path(uri) + filename = parse_uri(uri)[1] else: prefix = 'res:/Packages' # Note: keep in sync with core/url.py#_to_resource_uri assert uri.startswith(prefix) diff --git a/plugin/references.py b/plugin/references.py index 09e97cdd7..a86006e8f 100644 --- a/plugin/references.py +++ b/plugin/references.py @@ -9,6 +9,7 @@ from .core.sessions import Session from .core.settings import userprefs from .core.types import ClientConfig +from .core.url import parse_uri from .core.views import get_line from .core.views import get_symbol_kind_from_scope from .core.views import get_uri_and_position_from_location @@ -183,7 +184,7 @@ def _show_references_in_quick_panel( pt = selection[0].b view_filename = self.view.file_name() for idx, location in enumerate(locations): - if view_filename != session.config.map_server_uri_to_client_path(location['uri']): + if view_filename != parse_uri(location['uri'])[1]: continue index = idx if position_to_offset(location['range']['start'], self.view) > pt: @@ -246,7 +247,7 @@ def _group_locations_by_uri( grouped_locations: dict[str, list[tuple[Point, str]]] = {} for location in locations: uri, position = get_uri_and_position_from_location(location) - file_path = config.map_server_uri_to_client_path(uri) + file_path = parse_uri(uri)[1] point = Point.from_lsp(position) # get line of the reference, to showcase its use reference_line = get_line(window, file_path, point.row)