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

how to run time-consuming initialization asynchronously? #206

Open
daquexian opened this issue Aug 10, 2021 · 3 comments
Open

how to run time-consuming initialization asynchronously? #206

daquexian opened this issue Aug 10, 2021 · 3 comments

Comments

@daquexian
Copy link

daquexian commented Aug 10, 2021

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 daquexian changed the title how to run time-consuming initialization? how to run time-consuming initialization asynchronously? Aug 10, 2021
@danixeee
Copy link
Contributor

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!

@daquexian
Copy link
Author

daquexian commented Dec 27, 2021

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.

@tombh
Copy link
Collaborator

tombh commented Dec 3, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants