Skip to content

Ignore notifications sent from sourcekit-lsp when waiting for a request reply #134

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

Merged
Merged
Changes from all 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
57 changes: 40 additions & 17 deletions test-sourcekit-lsp/test-sourcekit-lsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,11 @@ def send_data(self, dict: Dict[str, object]):
self.process.stdin.write(data)
self.process.stdin.flush()

def send_request(self, method: str, params: Dict[str, object]) -> str:
def read_message_from_lsp_server(self) -> str:
"""
Send a request of the given method and parameters to the LSP server and wait for the response.
Read a single message sent from the LSP server to the client.
This can be a request reply, notification or request sent from the server to the client.
"""
self.request_id += 1

self.send_data(
{
"jsonrpc": "2.0",
"id": self.request_id,
"method": method,
"params": params,
}
)

assert self.process.stdout
# Read Content-Length: 123\r\n
# Note: Even though the Content-Length header ends with \r\n, `readline` returns it with a single \n.
Expand All @@ -71,11 +61,44 @@ def send_request(self, method: str, params: Dict[str, object]) -> str:
assert empty_line == "\n", f"Expected empty line, got '{empty_line}'"

# Read the actual response
response = self.process.stdout.read(int(match.group(1)))
return self.process.stdout.read(int(match.group(1)))

def read_request_reply_from_lsp_server(self, request_id: int) -> str:
"""
Read all messages sent from the LSP server until we see a request reply.
Assert that this request reply was for the given request_id and return it.
"""
message = self.read_message_from_lsp_server()
message_obj = json.loads(message)
if "result" not in message_obj:
# We received a message that wasn't the request reply.
# Log it, ignore it and wait for the next message.
print("Received message")
print(message)
return self.read_request_reply_from_lsp_server(request_id)
# We always wait for a request reply before sending the next request.
# If we received a request reply, it should thus have the request ID of the last request that we sent.
assert (
f'"id":{self.request_id}' in response
), f"Expected response for request {self.request_id}, got '{response}'"
return response
message_obj["id"] == self.request_id
), f"Expected response for request {self.request_id}, got '{message}'"
return message

def send_request(self, method: str, params: Dict[str, object]) -> str:
"""
Send a request of the given method and parameters to the LSP server and wait for the response.
"""
self.request_id += 1

self.send_data(
{
"jsonrpc": "2.0",
"id": self.request_id,
"method": method,
"params": params,
}
)

return self.read_request_reply_from_lsp_server(self.request_id)

def send_notification(self, method: str, params: Dict[str, object]):
"""
Expand Down