Skip to content

Commit

Permalink
Align to breaking changes
Browse files Browse the repository at this point in the history
Nothing too interesting in this one, just updating imports, class names
etc to align `pygls` to the definitions in `lsprotocol`
  • Loading branch information
alcarney committed Aug 14, 2022
1 parent 6ab8b0f commit f58ce61
Show file tree
Hide file tree
Showing 22 changed files with 163 additions and 137 deletions.
15 changes: 7 additions & 8 deletions examples/json-extension/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from typing import Optional

from pygls.lsp.methods import (COMPLETION, TEXT_DOCUMENT_DID_CHANGE,
TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN,
TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN,
TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL)
from pygls.lsp.types import (CompletionItem, CompletionList, CompletionOptions,
CompletionParams, ConfigurationItem,
Expand All @@ -33,10 +33,9 @@
DidOpenTextDocumentParams, MessageType, Position,
Range, Registration, RegistrationParams,
SemanticTokens, SemanticTokensLegend, SemanticTokensParams,
Unregistration, UnregistrationParams)
from pygls.lsp.types.basic_structures import (WorkDoneProgressBegin,
WorkDoneProgressEnd,
WorkDoneProgressReport)
Unregistration, UnregistrationParams,
WorkDoneProgressBegin, WorkDoneProgressEnd,
WorkDoneProgressReport)
from pygls.server import LanguageServer

COUNT_DOWN_START_IN_SECONDS = 10
Expand Down Expand Up @@ -164,9 +163,9 @@ async def did_open(ls, params: DidOpenTextDocumentParams):
def semantic_tokens(ls: JsonLanguageServer, params: SemanticTokensParams):
"""See https://microsoft.github.io/language-server-protocol/specification#textDocument_semanticTokens
for details on how semantic tokens are encoded."""

TOKENS = re.compile('".*"(?=:)')

uri = params.text_document.uri
doc = ls.workspace.get_document(uri)

Expand All @@ -184,7 +183,7 @@ def semantic_tokens(ls: JsonLanguageServer, params: SemanticTokensParams):
(lineno - last_line),
(start - last_start),
(end - start),
0,
0,
0
]

Expand Down
68 changes: 43 additions & 25 deletions pygls/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and #
# limitations under the License. #
############################################################################
from functools import reduce
from typing import Any

from pygls.lsp.methods import (CODE_ACTION, CODE_LENS, COMPLETION, DECLARATION, DEFINITION,
DOCUMENT_COLOR, DOCUMENT_HIGHLIGHT, DOCUMENT_LINK, DOCUMENT_SYMBOL,
FOLDING_RANGE, FORMATTING, HOVER, IMPLEMENTATION,
Expand All @@ -30,14 +33,30 @@
WORKSPACE_DID_RENAME_FILES, WORKSPACE_SYMBOL,
WORKSPACE_WILL_CREATE_FILES, WORKSPACE_WILL_DELETE_FILES,
WORKSPACE_WILL_RENAME_FILES)
from pygls.lsp.types import (CodeLensOptions, CompletionOptions, DocumentLinkOptions,
ExecuteCommandOptions, ImplementationOptions, SaveOptions,
SemanticTokensOptions, SemanticTokensRegistrationOptions,
SemanticTokensRequestsFull,
from pygls.lsp.types import (ClientCapabilities, CodeLensOptions, CompletionOptions,
DocumentLinkOptions, ExecuteCommandOptions, ImplementationOptions,
SaveOptions, SemanticTokensOptions, SemanticTokensRegistrationOptions,
ServerCapabilities, SignatureHelpOptions,
TextDocumentSyncOptionsServerCapabilities, TypeDefinitionOptions,
WorkspaceFileOperationsServerCapabilities,
WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities)
TextDocumentSyncOptions, TypeDefinitionOptions,
FileOperationOptions,
WorkspaceFoldersServerCapabilities)


def get_capability(
client_capabilities: ClientCapabilities, field: str, default: Any = None
) -> Any:
"""Check if ClientCapabilities has some nested value without raising
AttributeError.
e.g. get_capability('text_document.synchronization.will_save')
"""
try:
value = reduce(getattr, field.split("."), client_capabilities)
except AttributeError:
return default

# If we reach the desired leaf value but it's None, return the default.
value = default if value is None else value
return


class ServerCapabilitiesBuilder:
Expand Down Expand Up @@ -71,12 +90,12 @@ def _with_text_doc_sync(self):
or TEXT_DOCUMENT_DID_CLOSE in self.features
)
will_save = (
self.client_capabilities.get_capability(
get_capability(self.client_capabilities,
'text_document.synchronization.will_save')
and TEXT_DOCUMENT_WILL_SAVE in self.features
)
will_save_wait_until = (
self.client_capabilities.get_capability(
get_capability(self.client_capabilities,
'text_document.synchronization.will_save_wait_until')
and TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL in self.features
)
Expand All @@ -89,7 +108,7 @@ def _with_text_doc_sync(self):
else:
save = False

self.server_cap.text_document_sync = TextDocumentSyncOptionsServerCapabilities(
self.server_cap.text_document_sync = TextDocumentSyncOptions(
open_close=open_close,
change=self.sync_kind,
will_save=will_save,
Expand Down Expand Up @@ -250,11 +269,10 @@ def _with_semantic_tokens(self):
self.server_cap.semantic_tokens_provider = value
return self

full_support = (
SemanticTokensRequestsFull(delta=True)
if TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA in self.features
else TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL in self.features
)
if TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA in self.features:
full_support = {"delta": True}
else:
full_support = TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL in self.features

options = SemanticTokensOptions(
legend=value,
Expand Down Expand Up @@ -287,62 +305,62 @@ def _with_workspace_symbol(self):

def _with_workspace_capabilities(self):
# File operations
file_operations = WorkspaceFileOperationsServerCapabilities()
file_operations = FileOperationOptions()

will_create = (
self.client_capabilities.get_capability('workspace.fileOperations.willCreate')
get_capability(self.client_capabilities, 'workspace.fileOperations.willCreate')
if WORKSPACE_WILL_CREATE_FILES in self.features
else None
)
if will_create is not None:
file_operations.will_create = will_create

did_create = (
self.client_capabilities.get_capability('workspace.fileOperations.didCreate')
get_capability(self.client_capabilities, 'workspace.fileOperations.didCreate')
if WORKSPACE_DID_CREATE_FILES in self.features
else None
)
if did_create is not None:
file_operations.did_create = did_create

will_rename = (
self.client_capabilities.get_capability('workspace.fileOperations.willRename')
get_capability(self.client_capabilities, 'workspace.fileOperations.willRename')
if WORKSPACE_WILL_RENAME_FILES in self.features
else None
)
if will_rename is not None:
file_operations.will_rename = will_rename

did_rename = (
self.client_capabilities.get_capability('workspace.fileOperations.didRename')
get_capability(self.client_capabilities, 'workspace.fileOperations.didRename')
if WORKSPACE_DID_RENAME_FILES in self.features
else None
)
if did_rename is not None:
file_operations.did_rename = did_rename

will_delete = (
self.client_capabilities.get_capability('workspace.fileOperations.willDelete')
get_capability(self.client_capabilities, 'workspace.fileOperations.willDelete')
if WORKSPACE_WILL_DELETE_FILES in self.features
else None
)
if will_delete is not None:
file_operations.will_delete = will_delete

did_delete = (
self.client_capabilities.get_capability('workspace.fileOperations.didDelete')
get_capability(self.client_capabilities, 'workspace.fileOperations.didDelete')
if WORKSPACE_DID_DELETE_FILES in self.features
else None
)
if did_delete is not None:
file_operations.did_delete = did_delete

self.server_cap.workspace = WorkspaceServerCapabilities(
workspace_folders=WorkspaceFoldersServerCapabilities(
self.server_cap.workspace = dict(
workspaceFolders=WorkspaceFoldersServerCapabilities(
supported=True,
change_notifications=True,
),
file_operations=file_operations,
fileOperations=file_operations,
)
return self

Expand Down
6 changes: 3 additions & 3 deletions pygls/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from pygls.lsp.methods import (PROGRESS_NOTIFICATION, WINDOW_WORK_DONE_PROGRESS_CANCEL,
WINDOW_WORK_DONE_PROGRESS_CREATE)
from pygls.lsp.types.basic_structures import (ProgressParams, ProgressToken, WorkDoneProgressBegin,
WorkDoneProgressEnd, WorkDoneProgressReport)
from pygls.lsp.types.window import WorkDoneProgressCancelParams, WorkDoneProgressCreateParams
from pygls.lsp.types import (ProgressParams, ProgressToken, WorkDoneProgressBegin,
WorkDoneProgressEnd, WorkDoneProgressReport,
WorkDoneProgressCancelParams, WorkDoneProgressCreateParams)
from pygls.protocol import LanguageServerProtocol


Expand Down
25 changes: 12 additions & 13 deletions pygls/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@
WORKSPACE_APPLY_EDIT, WORKSPACE_CONFIGURATION,
WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS, WORKSPACE_EXECUTE_COMMAND,
WORKSPACE_SEMANTIC_TOKENS_REFRESH)
from pygls.lsp.types import (ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse, Diagnostic,
from pygls.lsp.types import (ApplyWorkspaceEditParams,
ConfigurationParams, ConfigCallbackType, Diagnostic,
DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams,
DidCloseTextDocumentParams, DidOpenTextDocumentParams,
ExecuteCommandParams, InitializeParams, InitializeResult,
LogMessageParams, MessageType, PublishDiagnosticsParams,
RegistrationParams, ShowMessageParams, UnregistrationParams,
LogMessageParams, LogTraceParams, MessageType, PublishDiagnosticsParams,
RegistrationParams, ResponseErrorMessage, SetTraceParams,
ShowDocumentParams, ShowMessageParams, ShowDocumentCallbackType,
TraceValues, UnregistrationParams, WorkspaceApplyEditResponse,
WorkspaceEdit)
from pygls.lsp.types.basic_structures import (ConfigCallbackType, LogTraceParams, SetTraceParams,
Trace)
from pygls.lsp.types.window import ShowDocumentCallbackType, ShowDocumentParams
from pygls.lsp.types.workspace import ConfigurationParams
from pygls.uris import from_fs_path
from pygls.workspace import Workspace

Expand Down Expand Up @@ -586,7 +585,7 @@ def _register_builtin_features(self):
if callable(attr) and hasattr(attr, 'method_name'):
self.fm.add_builtin_feature(attr.method_name, attr)

def apply_edit(self, edit: WorkspaceEdit, label: str = None) -> ApplyWorkspaceEditResponse:
def apply_edit(self, edit: WorkspaceEdit, label: str = None) -> WorkspaceApplyEditResponse:
"""Sends apply edit request to the client."""
return self.send_request(WORKSPACE_APPLY_EDIT,
ApplyWorkspaceEditParams(edit=edit, label=label))
Expand Down Expand Up @@ -628,7 +627,7 @@ def lsp_initialize(self, params: InitializeParams) -> InitializeResult:
workspace_folders = params.workspace_folders or []
self.workspace = Workspace(root_uri, self._server.sync_kind, workspace_folders)

self.trace = Trace.Off
self.trace = TraceValues.OFF

return InitializeResult(capabilities=self.server_capabilities)

Expand Down Expand Up @@ -719,11 +718,11 @@ def get_configuration_async(self, params: ConfigurationParams) -> asyncio.Future

def log_trace(self, message: str, verbose: Optional[str] = None) -> None:
"""Sends trace notification to the client."""
if self.trace == Trace.Off:
if self.trace == TraceValues.OFF:
return

params = LogTraceParams(message=message)
if verbose and self.trace == Trace.Verbose:
if verbose and self.trace == TraceValues.VERBOSE:
params.verbose = verbose

self.notify(LOG_TRACE_NOTIFICATION, params)
Expand Down Expand Up @@ -808,11 +807,11 @@ def show_document_async(self, params: ShowDocumentParams) -> asyncio.Future:
"""
return asyncio.wrap_future(self.show_document(params, None))

def show_message(self, message, msg_type=MessageType.Info):
def show_message(self, message, msg_type=MessageType.INFO):
"""Sends message to the client to display message."""
self.notify(WINDOW_SHOW_MESSAGE, ShowMessageParams(type=msg_type, message=message))

def show_message_log(self, message, msg_type=MessageType.Log):
def show_message_log(self, message, msg_type=MessageType.LOG):
"""Sends message to the client's output channel."""
self.notify(WINDOW_LOG_MESSAGE, LogMessageParams(type=msg_type, message=message))

Expand Down
12 changes: 6 additions & 6 deletions pygls/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
from typing import Any, Callable, List, Optional, TypeVar

from pygls import IS_WIN, IS_PYODIDE
from pygls.lsp.types import (ApplyWorkspaceEditResponse, ClientCapabilities, ConfigCallbackType,
from pygls.lsp.types import (WorkspaceApplyEditResponse, ClientCapabilities, ConfigCallbackType,
ConfigurationParams, Diagnostic, MessageType, RegistrationParams,
ServerCapabilities, TextDocumentSyncKind, UnregistrationParams,
ServerCapabilities, ShowDocumentCallbackType, ShowDocumentParams,
TextDocumentSyncKind, UnregistrationParams,
WorkspaceEdit)
from pygls.lsp.types.window import ShowDocumentCallbackType, ShowDocumentParams
from pygls.progress import Progress
from pygls.protocol import LanguageServerProtocol, deserialize_message
from pygls.workspace import Workspace
Expand Down Expand Up @@ -330,7 +330,7 @@ def __init__(self, loop=None, protocol_cls=LanguageServerProtocol, max_workers:
raise TypeError('Protocol class should be subclass of LanguageServerProtocol')
super().__init__(protocol_cls, loop, max_workers)

def apply_edit(self, edit: WorkspaceEdit, label: str = None) -> ApplyWorkspaceEditResponse:
def apply_edit(self, edit: WorkspaceEdit, label: str = None) -> WorkspaceApplyEditResponse:
"""Sends apply edit request to the client."""
return self.lsp.apply_edit(edit, label)

Expand Down Expand Up @@ -418,11 +418,11 @@ def show_document_async(self, params: ShowDocumentParams) -> asyncio.Future:
"""Display a particular document in the user interface. Should be called with `await`"""
return self.lsp.show_document_async(params)

def show_message(self, message, msg_type=MessageType.Info) -> None:
def show_message(self, message, msg_type=MessageType.INFO) -> None:
"""Sends message to the client to display message."""
self.lsp.show_message(message, msg_type)

def show_message_log(self, message, msg_type=MessageType.Log) -> None:
def show_message_log(self, message, msg_type=MessageType.LOG) -> None:
"""Sends message to the client's output channel."""
self.lsp.show_message_log(message, msg_type)

Expand Down
19 changes: 12 additions & 7 deletions pygls/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import re
from typing import List, Optional, Pattern

from pygls.lsp.types import (NumType, Position, Range, TextDocumentContentChangeEvent,
from pygls.lsp.types import (Position, Range, TextDocumentContentChangeEvent,
TextDocumentItem, TextDocumentSyncKind,
VersionedTextDocumentIdentifier, WorkspaceFolder)
from pygls.uris import to_fs_path, uri_scheme
Expand Down Expand Up @@ -164,7 +164,7 @@ def __init__(
self,
uri: str,
source: Optional[str] = None,
version: Optional[NumType] = None,
version: Optional[int] = None,
language_id: Optional[str] = None,
local: bool = True,
sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.INCREMENTAL
Expand All @@ -191,8 +191,11 @@ def _apply_incremental_change(self, change: TextDocumentContentChangeEvent) -> N
text = change.text
change_range = change.range

(start_line, start_col), (end_line, end_col) = \
range_from_utf16(lines, change_range) # type: ignore
range = range_from_utf16(lines, change_range) # type: ignore
start_line = range.start.line
start_col = range.start.character
end_line = range.end.line
end_col = range.end.character

# Check for an edit occurring at the very end of the file
if start_line == len(lines):
Expand Down Expand Up @@ -274,7 +277,8 @@ def lines(self) -> List[str]:
def offset_at_position(self, position: Position) -> int:
"""Return the character offset pointed at by the given position."""
lines = self.lines
row, col = position_from_utf16(lines, position)
pos = position_from_utf16(lines, position)
row, col = pos.line, pos.character
return col + sum(len(line) for line in lines[:row])

@property
Expand Down Expand Up @@ -313,7 +317,8 @@ def word_at_position(
if position.line >= len(lines):
return ''

row, col = position_from_utf16(lines, position)
pos = position_from_utf16(lines, position)
row, col = pos.line, pos.character
line = lines[row]
# Split word in two
start = line[:col]
Expand Down Expand Up @@ -345,7 +350,7 @@ def _create_document(
self,
doc_uri: str,
source: Optional[str] = None,
version: Optional[NumType] = None,
version: Optional[int] = None,
language_id: Optional[str] = None,
) -> Document:
return Document(
Expand Down
Loading

0 comments on commit f58ce61

Please sign in to comment.