pygls
pygls copied to clipboard
how to run time-consuming initialization asynchronously?
Thanks for your great library!
I'm writing a language server that will do some time-consuming preparation when initializing (that means I don't want the client to send any other messages before the initialization completes). Just registerring the feature by @server.feature(INITIALIZE)
doesn't work, for the InitializeResult
is sent in the parent class method:
(From documents) Built-in features in most cases should not be overridden. Instead, register the feature with the same name and it will be called immediately after the corresponding built-in feature.
When I'm trying to override the protocol, I find that I can't override the lsp_initialize
method with an async function:
Traceback (most recent call last): File "/home/dev/.local/lib/python3.6/site-packages/pygls/protocol.py", line 382, in _send_data body = data.json(by_alias=True, exclude_unset=True, encoder=default_serializer) File "pydantic/main.py", line 557, in pydantic.main.BaseModel.json File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps **kw).encode(obj) File "/usr/lib/python3.6/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/lib/python3.6/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/home/dev/.local/lib/python3.6/site-packages/pygls/protocol.py", line 102, in default_serializer return o.__dict__ AttributeError: 'coroutine' object has no attribute '__dict__'
I also don't want the initialization to be blocking, for the need of sending progress
notification.
Is there any other way? Thanks!
I think you should not override the protocol, just register and use initialized LSP method. There you can do all your work and use a flag to indicate that server is ready to process other requests. Don't worry about client sending requests, just ignore them until everything is set up.
Does that make sense?
Sorry for the late response!
Thanks for your reply. Sorry for the late response.
It works, but not so perfectly.
Now I hacked the initialize method: https://github.com/daquexian/tagls/blob/c5a826b8e7945d53bd29c6b1819a3e025955ba4e/tagls/server.py line 139, 204 and 235. IMO it works better than using a server-side flag because it interacts better with lsp client. For example, in coc.nvim, I get a "initializing" message until my initialization really finishes. What's more, it remains the possibility of supporting "progress" method in the future.
Please correct me if I'm wrong.
Where are we with this? Would it still be helpful to make any changes in Pygls?