Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow plugins to modify server response messages #1992

Merged
merged 4 commits into from
Jul 13, 2022
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions plugin/core/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,17 @@ def on_pre_send_notification_async(self, notification: Notification) -> None:
"""
pass

def on_server_response(self, method: str, response: Response) -> None:
"""
Notifies about a response message that has been received from the language server.
Only successful responses are passed to this method.

:param method: The method of the request.
:param response: The response object to the request. The response.result field can be modified by the
plugin, before it gets further handled by the LSP package.
"""
pass

def on_open_uri_async(self, uri: DocumentUri, callback: Callable[[str, str, str], None]) -> bool:
"""
Called when a language server reports to open an URI. If you know how to handle this URI, then return True and
Expand Down Expand Up @@ -1898,10 +1909,12 @@ def deduce_payload(
return res
elif "id" in payload:
response_id = int(payload["id"])
handler, result, is_error = self.response_handler(response_id, payload)
response_tuple = (handler, result, None, None, None)
handler, method, result, is_error = self.response_handler(response_id, payload)
self._logger.incoming_response(response_id, result, is_error)
return response_tuple
response = Response(response_id, result)
if self._plugin and not is_error:
self._plugin.on_server_response(method, response) # type: ignore
return handler, response.result, None, None, None
else:
debug("Unknown payload type: ", payload)
return (None, None, None, None, None)
Expand All @@ -1925,21 +1938,25 @@ def on_payload(self, payload: Dict[str, Any]) -> None:
except Exception as err:
exception_log("Error handling {}".format(typestr), err)

def response_handler(self, response_id: int, response: Dict[str, Any]) -> Tuple[Optional[Callable], Any, bool]:
def response_handler(
self,
response_id: int,
response: Dict[str, Any]
) -> Tuple[Optional[Callable], Optional[str], Any, bool]:
request, handler, error_handler = self._response_handlers.pop(response_id, (None, None, None))
if not request:
error = {"code": ErrorCode.InvalidParams, "message": "unknown response ID {}".format(response_id)}
return (print_to_status_bar, error, True)
return (print_to_status_bar, None, error, True)
self._invoke_views(request, "on_request_finished_async", response_id)
if "result" in response and "error" not in response:
return (handler, response["result"], False)
return (handler, request.method, response["result"], False)
if not error_handler:
error_handler = print_to_status_bar
if "result" not in response and "error" in response:
error = response["error"]
else:
error = {"code": ErrorCode.InvalidParams, "message": "invalid response payload"}
return (error_handler, error, True)
return (error_handler, request.method, error, True)

def _get_handler(self, method: str) -> Optional[Callable]:
return getattr(self, method2attr(method), None)