80 lines
2.7 KiB
Python
80 lines
2.7 KiB
Python
import asyncio
|
|
from concurrent.futures import Future
|
|
from typing import Dict
|
|
|
|
from lsprotocol.types import (
|
|
PROGRESS,
|
|
WINDOW_WORK_DONE_PROGRESS_CREATE,
|
|
ProgressParams,
|
|
ProgressToken,
|
|
WorkDoneProgressBegin,
|
|
WorkDoneProgressEnd,
|
|
WorkDoneProgressReport,
|
|
WorkDoneProgressCreateParams,
|
|
)
|
|
from pygls.protocol import LanguageServerProtocol
|
|
|
|
|
|
class Progress:
|
|
"""A class for working with client's progress bar.
|
|
|
|
Attributes:
|
|
_lsp(LanguageServerProtocol): Language server protocol instance
|
|
tokens(dict): Holds futures for work done progress tokens that are
|
|
already registered. These futures will be cancelled if the client
|
|
sends a cancel work done process notification.
|
|
"""
|
|
|
|
def __init__(self, lsp: LanguageServerProtocol) -> None:
|
|
self._lsp = lsp
|
|
|
|
self.tokens: Dict[ProgressToken, Future] = {}
|
|
|
|
def _check_token_registered(self, token: ProgressToken) -> None:
|
|
if token in self.tokens:
|
|
raise Exception("Token is already registered!")
|
|
|
|
def _register_token(self, token: ProgressToken) -> None:
|
|
self.tokens[token] = Future()
|
|
|
|
def create(self, token: ProgressToken, callback=None) -> Future:
|
|
"""Create a server initiated work done progress."""
|
|
self._check_token_registered(token)
|
|
|
|
def on_created(*args, **kwargs):
|
|
self._register_token(token)
|
|
if callback is not None:
|
|
callback(*args, **kwargs)
|
|
|
|
return self._lsp.send_request(
|
|
WINDOW_WORK_DONE_PROGRESS_CREATE,
|
|
WorkDoneProgressCreateParams(token=token),
|
|
on_created,
|
|
)
|
|
|
|
async def create_async(self, token: ProgressToken) -> asyncio.Future:
|
|
"""Create a server initiated work done progress."""
|
|
self._check_token_registered(token)
|
|
|
|
result = await self._lsp.send_request_async(
|
|
WINDOW_WORK_DONE_PROGRESS_CREATE,
|
|
WorkDoneProgressCreateParams(token=token),
|
|
)
|
|
self._register_token(token)
|
|
return result
|
|
|
|
def begin(self, token: ProgressToken, value: WorkDoneProgressBegin) -> None:
|
|
"""Notify beginning of work."""
|
|
# Register cancellation future for the case of client initiated progress
|
|
self.tokens.setdefault(token, Future())
|
|
|
|
return self._lsp.notify(PROGRESS, ProgressParams(token=token, value=value))
|
|
|
|
def report(self, token: ProgressToken, value: WorkDoneProgressReport) -> None:
|
|
"""Notify progress of work."""
|
|
self._lsp.notify(PROGRESS, ProgressParams(token=token, value=value))
|
|
|
|
def end(self, token: ProgressToken, value: WorkDoneProgressEnd) -> None:
|
|
"""Notify end of work."""
|
|
self._lsp.notify(PROGRESS, ProgressParams(token=token, value=value))
|