pygls icon indicating copy to clipboard operation
pygls copied to clipboard

how to run time-consuming initialization asynchronously?

Open daquexian opened this issue 3 years ago • 3 comments

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!

daquexian avatar Aug 10 '21 13:08 daquexian

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!

danixeee avatar Aug 26 '21 17:08 danixeee

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.

image

Please correct me if I'm wrong.

daquexian avatar Dec 27 '21 03:12 daquexian

Where are we with this? Would it still be helpful to make any changes in Pygls?

tombh avatar Dec 03 '22 20:12 tombh