From 79cb8d081b1889d01b6455af379413a6ac327e5b Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 14 Aug 2022 15:16:36 +0100 Subject: [PATCH 1/9] Remove pygls' built in type definitions --- pygls/lsp/methods.py | 120 ----- pygls/lsp/types/__init__.py | 10 - pygls/lsp/types/basic_structures.py | 479 ------------------ pygls/lsp/types/client.py | 48 -- pygls/lsp/types/diagnostics.py | 47 -- pygls/lsp/types/file_operations.py | 79 --- pygls/lsp/types/general_messages.py | 280 ---------- pygls/lsp/types/language_features/__init__.py | 27 - .../types/language_features/call_hierarchy.py | 81 --- .../types/language_features/code_action.py | 99 ---- .../lsp/types/language_features/code_lens.py | 53 -- .../language_features/color_presentation.py | 44 -- .../lsp/types/language_features/completion.py | 165 ------ .../types/language_features/declaration.py | 51 -- .../lsp/types/language_features/definition.py | 43 -- .../types/language_features/document_color.py | 62 --- .../language_features/document_highlight.py | 60 --- .../types/language_features/document_link.py | 51 -- .../language_features/document_symbol.py | 116 ----- .../types/language_features/folding_range.py | 67 --- .../lsp/types/language_features/formatting.py | 51 -- pygls/lsp/types/language_features/hover.py | 57 --- .../types/language_features/implementation.py | 52 -- .../language_features/linked_editing_range.py | 53 -- pygls/lsp/types/language_features/monikers.py | 70 --- .../language_features/on_type_formatting.py | 45 -- .../types/language_features/prepare_rename.py | 37 -- .../language_features/range_formatting.py | 45 -- .../lsp/types/language_features/references.py | 47 -- pygls/lsp/types/language_features/rename.py | 50 -- .../language_features/selection_range.py | 60 --- .../language_features/semantic_tokens.py | 151 ------ .../types/language_features/signature_help.py | 88 ---- .../language_features/type_definition.py | 51 -- pygls/lsp/types/text_synchronization.py | 46 -- pygls/lsp/types/window.py | 91 ---- pygls/lsp/types/workspace.py | 202 -------- 37 files changed, 3178 deletions(-) delete mode 100644 pygls/lsp/methods.py delete mode 100644 pygls/lsp/types/__init__.py delete mode 100644 pygls/lsp/types/basic_structures.py delete mode 100644 pygls/lsp/types/client.py delete mode 100644 pygls/lsp/types/diagnostics.py delete mode 100644 pygls/lsp/types/file_operations.py delete mode 100644 pygls/lsp/types/general_messages.py delete mode 100644 pygls/lsp/types/language_features/__init__.py delete mode 100644 pygls/lsp/types/language_features/call_hierarchy.py delete mode 100644 pygls/lsp/types/language_features/code_action.py delete mode 100644 pygls/lsp/types/language_features/code_lens.py delete mode 100644 pygls/lsp/types/language_features/color_presentation.py delete mode 100644 pygls/lsp/types/language_features/completion.py delete mode 100644 pygls/lsp/types/language_features/declaration.py delete mode 100644 pygls/lsp/types/language_features/definition.py delete mode 100644 pygls/lsp/types/language_features/document_color.py delete mode 100644 pygls/lsp/types/language_features/document_highlight.py delete mode 100644 pygls/lsp/types/language_features/document_link.py delete mode 100644 pygls/lsp/types/language_features/document_symbol.py delete mode 100644 pygls/lsp/types/language_features/folding_range.py delete mode 100644 pygls/lsp/types/language_features/formatting.py delete mode 100644 pygls/lsp/types/language_features/hover.py delete mode 100644 pygls/lsp/types/language_features/implementation.py delete mode 100644 pygls/lsp/types/language_features/linked_editing_range.py delete mode 100644 pygls/lsp/types/language_features/monikers.py delete mode 100644 pygls/lsp/types/language_features/on_type_formatting.py delete mode 100644 pygls/lsp/types/language_features/prepare_rename.py delete mode 100644 pygls/lsp/types/language_features/range_formatting.py delete mode 100644 pygls/lsp/types/language_features/references.py delete mode 100644 pygls/lsp/types/language_features/rename.py delete mode 100644 pygls/lsp/types/language_features/selection_range.py delete mode 100644 pygls/lsp/types/language_features/semantic_tokens.py delete mode 100644 pygls/lsp/types/language_features/signature_help.py delete mode 100644 pygls/lsp/types/language_features/type_definition.py delete mode 100644 pygls/lsp/types/text_synchronization.py delete mode 100644 pygls/lsp/types/window.py delete mode 100644 pygls/lsp/types/workspace.py diff --git a/pygls/lsp/methods.py b/pygls/lsp/methods.py deleted file mode 100644 index fdfd41b2..00000000 --- a/pygls/lsp/methods.py +++ /dev/null @@ -1,120 +0,0 @@ -############################################################################ -# Copyright(c) Open Law Library. All rights reserved. # -# See ThirdPartyNotices.txt in the project root for additional notices. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains all methods supported by Language Server Protocol - -LSP Specification: - https://microsoft.github.io/language-server-protocol/specification -""" - -# Special methods -CANCEL_REQUEST = '$/cancelRequest' -PROGRESS_NOTIFICATION = '$/progress' -LOG_TRACE_NOTIFICATION = '$/logTrace' -SET_TRACE_NOTIFICATION = '$/setTrace' - -# Client -CLIENT_REGISTER_CAPABILITY = 'client/registerCapability' -CLIENT_UNREGISTER_CAPABILITY = 'client/unregisterCapability' - -# Diagnostics -TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS = 'textDocument/publishDiagnostics' - -# General -EXIT = 'exit' -INITIALIZE = 'initialize' -INITIALIZED = 'initialized' -SHUTDOWN = 'shutdown' - -# Language Features -CODE_ACTION = 'textDocument/codeAction' -CODE_ACTION_RESOLVE = 'codeAction/resolve' -CODE_LENS = 'textDocument/codeLens' -CODE_LENS_RESOLVE = 'codeLens/resolve' -COLOR_PRESENTATION = 'textDocument/colorPresentation' -COMPLETION = 'textDocument/completion' -COMPLETION_ITEM_RESOLVE = 'completionItem/resolve' -DECLARATION = 'textDocument/declaration' -DEFINITION = 'textDocument/definition' -DOCUMENT_COLOR = 'textDocument/documentColor' -DOCUMENT_HIGHLIGHT = 'textDocument/documentHighlight' -DOCUMENT_LINK = 'textDocument/documentLink' -DOCUMENT_LINK_RESOLVE = 'documentLink/resolve' -DOCUMENT_SYMBOL = 'textDocument/documentSymbol' -FOLDING_RANGE = 'textDocument/foldingRange' -FORMATTING = 'textDocument/formatting' -HOVER = 'textDocument/hover' -IMPLEMENTATION = 'textDocument/implementation' -ON_TYPE_FORMATTING = 'textDocument/onTypeFormatting' -PREPARE_RENAME = 'textDocument/prepareRename' -RANGE_FORMATTING = 'textDocument/rangeFormatting' -REFERENCES = 'textDocument/references' -RENAME = 'textDocument/rename' -SELECTION_RANGE = 'textDocument/selectionRange' -SIGNATURE_HELP = 'textDocument/signatureHelp' -TYPE_DEFINITION = 'textDocument/typeDefinition' - -# Telemetry -TELEMETRY_EVENT = 'telemetry/event' - -# Text Synchronization -TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE = 'textDocument/prepareCallHierarchy' -TEXT_DOCUMENT_CALL_HIERARCHY_INCOMING_CALLS = 'callHierarchy/incomingCalls' -TEXT_DOCUMENT_CALL_HIERARCHY_OUTGOING_CALLS = 'callHierarchy/outgoingCalls' -TEXT_DOCUMENT_DID_CHANGE = 'textDocument/didChange' -TEXT_DOCUMENT_DID_CLOSE = 'textDocument/didClose' -TEXT_DOCUMENT_DID_OPEN = 'textDocument/didOpen' -TEXT_DOCUMENT_DID_SAVE = 'textDocument/didSave' -TEXT_DOCUMENT_LINKED_EDITING_RANGE = 'textDocument/linkedEditingRange' -TEXT_DOCUMENT_MONIKER = 'textDocument/moniker' -# NOTE: From official specs regarding semantic tokens: -# Since the registration option handles range, full and delta requests the method used to -# register for semantic tokens requests is textDocument/semanticTokens -# and not one of the specific methods described below. -TEXT_DOCUMENT_SEMANTIC_TOKENS = 'textDocument/semanticTokens' -TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL = 'textDocument/semanticTokens/full' -TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA = 'textDocument/semanticTokens/full/delta' -TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE = 'textDocument/semanticTokens/range' -TEXT_DOCUMENT_WILL_SAVE = 'textDocument/willSave' -TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL = 'textDocument/willSaveWaitUntil' - -# Window -WINDOW_LOG_MESSAGE = 'window/logMessage' -WINDOW_SHOW_DOCUMENT = 'window/showDocument' -WINDOW_SHOW_MESSAGE = 'window/showMessage' -WINDOW_SHOW_MESSAGE_REQUEST = 'window/showMessageRequest' -WINDOW_WORK_DONE_PROGRESS_CANCEL = 'window/workDoneProgress/cancel' -WINDOW_WORK_DONE_PROGRESS_CREATE = 'window/workDoneProgress/create' - -# Workspace -WORKSPACE_APPLY_EDIT = 'workspace/applyEdit' -WORKSPACE_CODE_LENS_REFRESH = 'workspace/codeLens/refresh' -WORKSPACE_CONFIGURATION = 'workspace/configuration' -WORKSPACE_DID_CHANGE_CONFIGURATION = 'workspace/didChangeConfiguration' -WORKSPACE_DID_CHANGE_WATCHED_FILES = 'workspace/didChangeWatchedFiles' -WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS = 'workspace/didChangeWorkspaceFolders' -WORKSPACE_EXECUTE_COMMAND = 'workspace/executeCommand' -WORKSPACE_FOLDERS = 'workspace/workspaceFolders' -WORKSPACE_SEMANTIC_TOKENS_REFRESH = 'workspace/semanticTokens/refresh' -WORKSPACE_SYMBOL = 'workspace/symbol' - -# File Operations -WORKSPACE_WILL_CREATE_FILES = 'workspace/willCreateFiles' -WORKSPACE_DID_CREATE_FILES = 'workspace/didCreateFiles' -WORKSPACE_WILL_RENAME_FILES = 'workspace/willRenameFiles' -WORKSPACE_DID_RENAME_FILES = 'workspace/didRenameFiles' -WORKSPACE_WILL_DELETE_FILES = 'workspace/willDeleteFiles' -WORKSPACE_DID_DELETE_FILES = 'workspace/didDeleteFiles' diff --git a/pygls/lsp/types/__init__.py b/pygls/lsp/types/__init__.py deleted file mode 100644 index 0da5ba46..00000000 --- a/pygls/lsp/types/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# flake8: noqa -from pygls.lsp.types.basic_structures import * -from pygls.lsp.types.client import * -from pygls.lsp.types.diagnostics import * -from pygls.lsp.types.file_operations import * -from pygls.lsp.types.general_messages import * -from pygls.lsp.types.language_features import * -from pygls.lsp.types.text_synchronization import * -from pygls.lsp.types.window import * -from pygls.lsp.types.workspace import * diff --git a/pygls/lsp/types/basic_structures.py b/pygls/lsp/types/basic_structures.py deleted file mode 100644 index 2b28b597..00000000 --- a/pygls/lsp/types/basic_structures.py +++ /dev/null @@ -1,479 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Basic Structures -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Any, Callable, Dict, List, NewType, Optional, TypeVar, Union - -from pydantic import BaseModel, root_validator -from typeguard import check_type - -ChangeAnnotationIdentifier = NewType('ChangeAnnotationIdentifier', str) -NumType = Union[int, float] -ProgressToken = Union[int, str] -URI = NewType('URI', str) -T = TypeVar('T') - -ConfigCallbackType = Callable[[List[Any]], None] - - -def snake_to_camel(string: str) -> str: - return ''.join( - word.capitalize() if idx > 0 else word - for idx, word in enumerate(string.split('_')) - ) - - -class Model(BaseModel): - class Config: - alias_generator = snake_to_camel - allow_population_by_field_name = True - fields = { - 'from_': 'from' - } - - def __init__(self, **data: Any) -> None: - super().__init__(**data) - - # Serialize (.json()) fields that has default value which is not None - for name, field in self.__fields__.items(): - if getattr(field, 'default', None) is not None: - self.__fields_set__.add(name) - - -class JsonRpcMessage(Model): - """A base json rpc message defined by LSP.""" - jsonrpc: str - - -class JsonRPCNotification(JsonRpcMessage): - """A class that represents json rpc notification message.""" - method: str - params: Any - - -class JsonRPCRequestMessage(JsonRpcMessage): - """A class that represents json rpc request message.""" - id: Any - method: str - params: Any - - @root_validator - def check_result_or_error(cls, values): - # Workaround until pydantic supports StrictUnion - # https://github.com/samuelcolvin/pydantic/pull/2092 - id_val = values.get('id') - check_type('', id_val, Union[int, str]) - - return values - - -class JsonRPCResponseMessage(JsonRpcMessage): - """A class that represents json rpc response message.""" - id: Any - result: Any - error: Any - - @root_validator - def check_result_or_error(cls, values): - # Workaround until pydantic supports StrictUnion - # https://github.com/samuelcolvin/pydantic/pull/2092 - id_val = values.get('id') - check_type('', id_val, Union[int, str]) - - result_val, error_val = values.get('result'), values.get('error') - - if result_val is not None and error_val is not None: - raise ValueError('Fields "result" and "error" are both set!') - - return values - - -class Position(Model): - line: int - character: int - - def __eq__(self, other): - return ( - isinstance(other, Position) - and self.line == other.line - and self.character == other.character) - - def __ge__(self, other): - line_gt = self.line > other.line - - if line_gt: - return line_gt - - if self.line == other.line: - return self.character >= other.character - - return False - - def __gt__(self, other): - line_gt = self.line > other.line - - if line_gt: - return line_gt - - if self.line == other.line: - return self.character > other.character - - return False - - def __le__(self, other): - line_lt = self.line < other.line - - if line_lt: - return line_lt - - if self.line == other.line: - return self.character <= other.character - - return False - - def __lt__(self, other): - line_lt = self.line < other.line - - if line_lt: - return line_lt - - if self.line == other.line: - return self.character < other.character - - return False - - def __ne__(self, other): - return not self.__eq__(other) - - def __hash__(self): - return hash((self.line, self.character)) - - def __iter__(self): - return iter((self.line, self.character)) - - def __repr__(self): - return f'{self.line}:{self.character}' - - -class Range(Model): - start: Position - end: Position - - def __eq__(self, other): - return ( - isinstance(other, Range) - and self.start == other.start - and self.end == other.end) - - def __hash__(self): - return hash((self.start, self.end)) - - def __iter__(self): - return iter((self.start, self.end)) - - def __repr__(self): - return f'{self.start!r}-{self.end!r}' - - -class Location(Model): - uri: str - range: Range - - def __eq__(self, other): - return ( - isinstance(other, Location) - and self.uri == other.uri - and self.range == other.range) - - def __repr__(self): - return f"{self.uri}:{self.range!r}" - - -class Trace(str, enum.Enum): - Off = 'off' - Messages = 'messages' - Verbose = 'verbose' - - -class CancelParams(Model): - id: Union[int, str] - - -class ProgressParams(Model): - token: ProgressToken - value: Any - - -class LogTraceParams(Model): - message: str - verbose: Optional[str] - - -class SetTraceParams(Model): - value: Trace - - -class RegularExpressionsClientCapabilities(Model): - engine: str - version: Optional[str] - - -class ResolveSupportClientCapabilities(Model): - properties: List[str] - - -class LocationLink(Model): - target_uri: str - target_range: Range - target_selection_range: Range - origin_selection_range: Optional[Range] - - -class DiagnosticSeverity(enum.IntEnum): - Error = 1 - Warning = 2 - Information = 3 - Hint = 4 - - -class DiagnosticTag(enum.IntEnum): - Unnecessary = 1 - Deprecated = 2 - - -class DiagnosticRelatedInformation(Model): - location: Location - message: str - - -class CodeDescription(Model): - href: URI - - -class Diagnostic(Model): - range: Range - message: str - severity: Optional[DiagnosticSeverity] - code: Optional[Union[int, str]] - code_description: Optional[CodeDescription] - source: Optional[str] - related_information: Optional[List[DiagnosticRelatedInformation]] - tags: Optional[List[DiagnosticTag]] - data: Optional[Any] - - -class Command(Model): - title: str - command: str - arguments: Optional[List[Any]] - - -class TextEdit(Model): - range: Range - new_text: str - - -class AnnotatedTextEdit(TextEdit): - annotation_id: ChangeAnnotationIdentifier - - -class ChangeAnnotation(Model): - label: str - needs_confirmation: Optional[bool] - description: Optional[str] - - -class ResourceOperationKind(str, enum.Enum): - Create = 'create' - Rename = 'rename' - Delete = 'delete' - - -class CreateFileOptions(Model): - overwrite: Optional[bool] - ignore_if_exists: Optional[bool] - - -class CreateFile(Model): - kind: ResourceOperationKind = ResourceOperationKind.Create - uri: str - options: Optional[CreateFileOptions] - annotation_id: Optional[ChangeAnnotationIdentifier] - - -class RenameFileOptions(Model): - overwrite: Optional[bool] - ignore_if_exists: Optional[bool] - - -class RenameFile(Model): - kind: ResourceOperationKind = ResourceOperationKind.Rename - old_uri: str - new_uri: str - options: Optional[RenameFileOptions] - annotation_id: Optional[ChangeAnnotationIdentifier] - - -class DeleteFileOptions(Model): - recursive: Optional[bool] - ignore_if_exists: Optional[bool] - - -class DeleteFile(Model): - kind: ResourceOperationKind = ResourceOperationKind.Delete - uri: str - options: Optional[DeleteFileOptions] - annotation_id: Optional[ChangeAnnotationIdentifier] - - -class FailureHandlingKind(str, enum.Enum): - Abort = 'abort' - Transactional = 'transactional' - TextOnlyTransactional = 'textOnlyTransactional' - Undo = 'undo' - - -class ChangeAnnotationSupport(Model): - groups_on_label: Optional[bool] - - -class WorkspaceEditClientCapabilities(Model): - document_changes: Optional[bool] - resource_operations: Optional[List[ResourceOperationKind]] - failure_handling: Optional[FailureHandlingKind] - normalizes_line_endings: Optional[bool] - change_annotation_support: Optional[ChangeAnnotationSupport] - - -class TextDocumentIdentifier(Model): - uri: str - - -class TextDocumentItem(Model): - uri: str - language_id: str - version: NumType - text: str - - -class VersionedTextDocumentIdentifier(TextDocumentIdentifier): - version: NumType - - -class OptionalVersionedTextDocumentIdentifier(TextDocumentIdentifier): - version: Optional[NumType] - - -class TextDocumentEdit(Model): - text_document: OptionalVersionedTextDocumentIdentifier - edits: List[Union[TextEdit, AnnotatedTextEdit]] - - -class TextDocumentPositionParams(Model): - text_document: TextDocumentIdentifier - position: Position - - -class DocumentFilter(Model): - language: Optional[str] - scheme: Optional[str] - pattern: Optional[str] - - -DocumentSelector = List[DocumentFilter] - - -class StaticRegistrationOptions(Model): - id: Optional[str] - - -class TextDocumentRegistrationOptions(Model): - document_selector: Optional[DocumentSelector] - - -class MarkupKind(str, enum.Enum): - PlainText = 'plaintext' - Markdown = 'markdown' - - -class MarkupContent(Model): - kind: MarkupKind - value: str - - -class WorkspaceEdit(Model): - changes: Optional[Dict[str, List[TextEdit]]] - document_changes: Optional[Any] - change_annotations: Optional[Dict[ChangeAnnotationIdentifier, ChangeAnnotation]] - - @root_validator - def check_result_or_error(cls, values): - # Workaround until pydantic supports StrictUnion - # https://github.com/samuelcolvin/pydantic/pull/2092 - - document_changes_val = values.get('document_changes') - check_type( - '', - document_changes_val, - Optional[Union[ - List[TextDocumentEdit], - List[Union[TextDocumentEdit, CreateFile, RenameFile, DeleteFile]], - ]] - ) - - return values - - -class WorkDoneProgressBegin(Model): - kind: str = 'begin' - title: str - cancellable: Optional[bool] - message: Optional[str] - percentage: Optional[NumType] - - -class WorkDoneProgressReport(Model): - kind: str = 'report' - cancellable: Optional[bool] - message: Optional[str] - percentage: Optional[NumType] - - -class WorkDoneProgressEnd(Model): - kind: str = 'end' - message: Optional[str] - - -class WorkDoneProgressParams(Model): - work_done_token: Optional[ProgressToken] - - -class WorkDoneProgressOptions(Model): - work_done_progress: Optional[ProgressToken] - - -class PartialResultParams(Model): - partial_result_token: Optional[ProgressToken] diff --git a/pygls/lsp/types/client.py b/pygls/lsp/types/client.py deleted file mode 100644 index 14c979cb..00000000 --- a/pygls/lsp/types/client.py +++ /dev/null @@ -1,48 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Client -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Any, List, Optional - -from pygls.lsp.types.basic_structures import Model - - -class Registration(Model): - id: str - method: str - register_options: Optional[Any] - - -class RegistrationParams(Model): - registrations: List[Registration] - - -class Unregistration(Model): - id: str - method: str - - -class UnregistrationParams(Model): - unregisterations: List[Unregistration] diff --git a/pygls/lsp/types/diagnostics.py b/pygls/lsp/types/diagnostics.py deleted file mode 100644 index 1b4e7c1a..00000000 --- a/pygls/lsp/types/diagnostics.py +++ /dev/null @@ -1,47 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Diagnostics -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import List, Optional - -from pygls.lsp.types.basic_structures import Diagnostic, DiagnosticTag, Model, NumType - - -class PublishDiagnosticsTagSupportClientCapabilities(Model): - value_set: Optional[List[DiagnosticTag]] - - -class PublishDiagnosticsClientCapabilities(Model): - related_information: Optional[bool] - tag_support: Optional[PublishDiagnosticsTagSupportClientCapabilities] - version_support: Optional[bool] - code_description_support: Optional[bool] - data_support: Optional[bool] - - -class PublishDiagnosticsParams(Model): - uri: str - diagnostics: List[Diagnostic] - version: Optional[NumType] diff --git a/pygls/lsp/types/file_operations.py b/pygls/lsp/types/file_operations.py deleted file mode 100644 index 477d77a7..00000000 --- a/pygls/lsp/types/file_operations.py +++ /dev/null @@ -1,79 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- File Operations -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import List, Optional - -from pygls.lsp.types.basic_structures import Model - - -class FileOperationPatternKind(str, enum.Enum): - File = 'file' - Folder = 'folder' - - -class FileOperationPatternOptions(Model): - ignore_case: Optional[bool] - - -class FileOperationPattern(Model): - glob: str - matches: Optional[FileOperationPatternKind] - options: Optional[FileOperationPatternOptions] - - -class FileOperationFilter(Model): - scheme: Optional[str] - pattern: FileOperationPattern - - -class FileOperationRegistrationOptions(Model): - filters: List[FileOperationFilter] - - -class FileCreate(Model): - uri: str - - -class CreateFilesParams(Model): - files: List[FileCreate] - - -class FileRename(Model): - oldUri: str - newUri: str - - -class RenameFilesParams(Model): - files: List[FileRename] - - -class FileDelete(Model): - uri: str - - -class DeleteFilesParams(Model): - files: List[FileDelete] diff --git a/pygls/lsp/types/general_messages.py b/pygls/lsp/types/general_messages.py deleted file mode 100644 index f26f74fb..00000000 --- a/pygls/lsp/types/general_messages.py +++ /dev/null @@ -1,280 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- General Messages -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from functools import reduce -from typing import Any, List, Optional, Union - -from pygls.lsp.types.basic_structures import (Model, NumType, RegularExpressionsClientCapabilities, - Trace, WorkDoneProgressParams, - WorkspaceEditClientCapabilities) -from pygls.lsp.types.diagnostics import PublishDiagnosticsClientCapabilities -from pygls.lsp.types.file_operations import FileOperationRegistrationOptions -from pygls.lsp.types.language_features import (CallHierarchyClientCapabilities, - CallHierarchyOptions, - CallHierarchyRegistrationOptions, - CodeActionClientCapabilities, CodeActionOptions, - CodeLensClientCapabilities, CodeLensOptions, - CodeLensWorkspaceClientCapabilities, - CompletionClientCapabilities, CompletionOptions, - DeclarationClientCapabilities, DeclarationOptions, - DeclarationRegistrationOptions, - DefinitionClientCapabilities, DefinitionOptions, - DocumentColorClientCapabilities, - DocumentColorOptions, - DocumentColorRegistrationOptions, - DocumentFormattingClientCapabilities, - DocumentFormattingOptions, - DocumentHighlightClientCapabilities, - DocumentHighlightOptions, - DocumentLinkClientCapabilities, DocumentLinkOptions, - DocumentOnTypeFormattingClientCapabilities, - DocumentOnTypeFormattingOptions, - DocumentRangeFormattingClientCapabilities, - DocumentRangeFormattingOptions, - DocumentSymbolClientCapabilities, - DocumentSymbolOptions, - FoldingRangeClientCapabilities, FoldingRangeOptions, - FoldingRangeRegistrationOptions, - HoverClientCapabilities, HoverOptions, - ImplementationClientCapabilities, - ImplementationOptions, - ImplementationRegistrationOptions, - LinkedEditingRangeClientCapabilities, - LinkedEditingRangeOptions, - LinkedEditingRangeRegistrationOptions, - MonikerClientCapabilities, MonikerOptions, - MonikerRegistrationOptions, - ReferenceClientCapabilities, ReferenceOptions, - RenameClientCapabilities, RenameOptions, - SelectionRangeClientCapabilities, - SelectionRangeOptions, - SelectionRangeRegistrationOptions, - SemanticTokensClientCapabilities, - SemanticTokensOptions, - SemanticTokensRegistrationOptions, - SemanticTokensWorkspaceClientCapabilities, - SignatureHelpClientCapabilities, - SignatureHelpOptions, - TypeDefinitionClientCapabilities, - TypeDefinitionOptions, - TypeDefinitionRegistrationOptions) -from pygls.lsp.types.text_synchronization import TextDocumentSyncKind -from pygls.lsp.types.window import (ShowDocumentClientCapabilities, - ShowMessageRequestClientCapabilities) -from pygls.lsp.types.workspace import (DidChangeConfigurationClientCapabilities, - DidChangeWatchedFilesClientCapabilities, - ExecuteCommandClientCapabilities, ExecuteCommandOptions, - SaveOptions, TextDocumentSyncClientCapabilities, - WorkspaceFolder, WorkspaceFoldersServerCapabilities, - WorkspaceSymbolClientCapabilities) - - -class ClientInfo(Model): - name: str - version: Optional[str] - - -class ServerInfo(Model): - name: str - version: Optional[str] - - -class TextDocumentClientCapabilities(Model): - synchronization: Optional[TextDocumentSyncClientCapabilities] - completion: Optional[CompletionClientCapabilities] - hover: Optional[HoverClientCapabilities] - signature_help: Optional[SignatureHelpClientCapabilities] - declaration: Optional[DeclarationClientCapabilities] - definition: Optional[DefinitionClientCapabilities] - type_definition: Optional[TypeDefinitionClientCapabilities] - implementation: Optional[ImplementationClientCapabilities] - references: Optional[ReferenceClientCapabilities] - document_highlight: Optional[DocumentHighlightClientCapabilities] - document_symbol: Optional[DocumentSymbolClientCapabilities] - code_action: Optional[CodeActionClientCapabilities] - code_lens: Optional[CodeLensClientCapabilities] - document_link: Optional[DocumentLinkClientCapabilities] - color_provider: Optional[DocumentColorClientCapabilities] - formatting: Optional[DocumentFormattingClientCapabilities] - range_formatting: Optional[DocumentRangeFormattingClientCapabilities] - on_type_formatting: Optional[DocumentOnTypeFormattingClientCapabilities] - rename: Optional[RenameClientCapabilities] - publish_diagnostics: Optional[PublishDiagnosticsClientCapabilities] - folding_range: Optional[FoldingRangeClientCapabilities] - selection_range: Optional[SelectionRangeClientCapabilities] - linked_editing_range: Optional[LinkedEditingRangeClientCapabilities] - call_hierarchy: Optional[CallHierarchyClientCapabilities] - semantic_tokens: Optional[SemanticTokensClientCapabilities] - moniker: Optional[MonikerClientCapabilities] - - -class FileOperationsClientCapabilities(Model): - dynamic_registration: Optional[bool] - did_create: Optional[bool] - will_create: Optional[bool] - did_rename: Optional[bool] - will_rename: Optional[bool] - did_delete: Optional[bool] - will_delete: Optional[bool] - - -class WorkspaceClientCapabilities(Model): - apply_edit: Optional[bool] - workspace_edit: Optional[WorkspaceEditClientCapabilities] - did_change_configuration: Optional[DidChangeConfigurationClientCapabilities] - did_change_watched_files: Optional[DidChangeWatchedFilesClientCapabilities] - symbol: Optional[WorkspaceSymbolClientCapabilities] - execute_command: Optional[ExecuteCommandClientCapabilities] - workspace_folders: Optional[bool] - configuration: Optional[bool] - semantic_tokens: Optional[SemanticTokensWorkspaceClientCapabilities] - code_lens: Optional[CodeLensWorkspaceClientCapabilities] - file_operations: Optional[FileOperationsClientCapabilities] - - -class WindowClientCapabilities(Model): - work_done_progress: Optional[bool] - show_message: Optional[ShowMessageRequestClientCapabilities] - show_document: Optional[ShowDocumentClientCapabilities] - - -class MarkdownClientCapabilities(Model): - parser: str - version: Optional[str] - - -class GeneralClientCapabilities(Model): - regular_expressions: Optional[RegularExpressionsClientCapabilities] - markdown: Optional[MarkdownClientCapabilities] - - -class TextDocumentSyncOptionsServerCapabilities(Model): - open_close: Optional[bool] - change: Optional[TextDocumentSyncKind] - will_save: Optional[bool] - will_save_wait_until: Optional[bool] - save: Optional[Union[bool, SaveOptions]] - - -class WorkspaceFileOperationsServerCapabilities(Model): - did_create: Optional[FileOperationRegistrationOptions] - will_create: Optional[FileOperationRegistrationOptions] - did_rename: Optional[FileOperationRegistrationOptions] - will_rename: Optional[FileOperationRegistrationOptions] - did_delete: Optional[FileOperationRegistrationOptions] - will_delete: Optional[FileOperationRegistrationOptions] - - -class WorkspaceServerCapabilities(Model): - workspace_folders: Optional[WorkspaceFoldersServerCapabilities] - file_operations: Optional[WorkspaceFileOperationsServerCapabilities] - - -class ClientCapabilities(Model): - workspace: Optional[WorkspaceClientCapabilities] - text_document: Optional[TextDocumentClientCapabilities] - window: Optional[WindowClientCapabilities] - general: Optional[GeneralClientCapabilities] - experimental: Optional[Any] - - def get_capability(self, 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("."), self) - 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 value - - -class InitializeParams(WorkDoneProgressParams): - process_id: Optional[int] - root_uri: Optional[str] - capabilities: ClientCapabilities - client_info: Optional[ClientInfo] - locale: Optional[str] - root_path: Optional[str] - initialization_options: Optional[Any] - trace: Optional[Trace] - workspace_folders: Optional[List[WorkspaceFolder]] - - -class ServerCapabilities(Model): - text_document_sync: Optional[Union[TextDocumentSyncOptionsServerCapabilities, NumType]] - completion_provider: Optional[CompletionOptions] - hover_provider: Optional[Union[bool, HoverOptions]] - signature_help_provider: Optional[SignatureHelpOptions] - declaration_provider: Optional[Union[bool, DeclarationOptions, - DeclarationRegistrationOptions]] - definition_provider: Optional[Union[bool, DefinitionOptions]] - type_definition_provider: Optional[Union[bool, TypeDefinitionOptions, - TypeDefinitionRegistrationOptions]] - implementation_provider: Optional[Union[bool, ImplementationOptions, - ImplementationRegistrationOptions]] - references_provider: Optional[Union[bool, ReferenceOptions]] - document_highlight_provider: Optional[Union[bool, DocumentHighlightOptions]] - document_symbol_provider: Optional[Union[bool, DocumentSymbolOptions]] - code_action_provider: Optional[Union[bool, CodeActionOptions]] - code_lens_provider: Optional[CodeLensOptions] - document_link_provider: Optional[DocumentLinkOptions] - color_provider: Optional[Union[bool, DocumentColorOptions, - DocumentColorRegistrationOptions]] - document_formatting_provider: Optional[Union[bool, DocumentFormattingOptions]] - document_range_formatting_provider: Optional[Union[bool, - DocumentRangeFormattingOptions]] - document_on_type_formatting_provider: Optional[DocumentOnTypeFormattingOptions] - rename_provider: Optional[Union[bool, RenameOptions]] - folding_range_provider: Optional[Union[bool, FoldingRangeOptions, - FoldingRangeRegistrationOptions]] - execute_command_provider: Optional[ExecuteCommandOptions] - selection_range_provider: Optional[Union[bool, SelectionRangeOptions, - SelectionRangeRegistrationOptions]] - linked_editing_range_provider: Optional[Union[bool, LinkedEditingRangeOptions, - LinkedEditingRangeRegistrationOptions]] - call_hierarchy_provider: Optional[Union[bool, CallHierarchyOptions, - CallHierarchyRegistrationOptions]] - semantic_tokens_provider: Optional[Union[SemanticTokensOptions, - SemanticTokensRegistrationOptions]] - moniker_provider: Optional[Union[bool, MonikerOptions, - MonikerRegistrationOptions]] - workspace_symbol_provider: Optional[bool] - workspace: Optional[WorkspaceServerCapabilities] - experimental: Optional[Any] - - -class InitializeResult(Model): - capabilities: ServerCapabilities - server_info: Optional[ServerInfo] - - -class InitializedParams(Model): - pass diff --git a/pygls/lsp/types/language_features/__init__.py b/pygls/lsp/types/language_features/__init__.py deleted file mode 100644 index 118f7469..00000000 --- a/pygls/lsp/types/language_features/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# flake8: noqa -from pygls.lsp.types.language_features.call_hierarchy import * -from pygls.lsp.types.language_features.code_action import * -from pygls.lsp.types.language_features.code_lens import * -from pygls.lsp.types.language_features.color_presentation import * -from pygls.lsp.types.language_features.completion import * -from pygls.lsp.types.language_features.declaration import * -from pygls.lsp.types.language_features.definition import * -from pygls.lsp.types.language_features.document_color import * -from pygls.lsp.types.language_features.document_highlight import * -from pygls.lsp.types.language_features.document_link import * -from pygls.lsp.types.language_features.document_symbol import * -from pygls.lsp.types.language_features.folding_range import * -from pygls.lsp.types.language_features.formatting import * -from pygls.lsp.types.language_features.hover import * -from pygls.lsp.types.language_features.implementation import * -from pygls.lsp.types.language_features.linked_editing_range import * -from pygls.lsp.types.language_features.monikers import * -from pygls.lsp.types.language_features.on_type_formatting import * -from pygls.lsp.types.language_features.prepare_rename import * -from pygls.lsp.types.language_features.range_formatting import * -from pygls.lsp.types.language_features.references import * -from pygls.lsp.types.language_features.rename import * -from pygls.lsp.types.language_features.selection_range import * -from pygls.lsp.types.language_features.semantic_tokens import * -from pygls.lsp.types.language_features.signature_help import * -from pygls.lsp.types.language_features.type_definition import * diff --git a/pygls/lsp/types/language_features/call_hierarchy.py b/pygls/lsp/types/language_features/call_hierarchy.py deleted file mode 100644 index c00c4d81..00000000 --- a/pygls/lsp/types/language_features/call_hierarchy.py +++ /dev/null @@ -1,81 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Call Hierarchy -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Any, List, Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Range, - StaticRegistrationOptions, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) -from pygls.lsp.types.language_features.document_symbol import SymbolKind, SymbolTag - - -class CallHierarchyClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class CallHierarchyOptions(WorkDoneProgressOptions): - - def __eq__(self, other: Any) -> bool: - return self.__dict__ == other.__dict__ - - -class CallHierarchyRegistrationOptions(TextDocumentRegistrationOptions, CallHierarchyOptions, StaticRegistrationOptions): - pass - - -class CallHierarchyPrepareParams(TextDocumentPositionParams, WorkDoneProgressParams): - pass - - -class CallHierarchyItem(Model): - name: str - kind: SymbolKind - uri: str - range: Range - selection_range: Range - tags: Optional[List[SymbolTag]] - detail: Optional[str] - data: Optional[Any] - - -class CallHierarchyIncomingCallsParams(WorkDoneProgressParams, PartialResultParams): - item: CallHierarchyItem - - -class CallHierarchyIncomingCall(Model): - from_: CallHierarchyItem - from_ranges: List[Range] - - -class CallHierarchyOutgoingCallsParams(WorkDoneProgressParams, PartialResultParams): - item: CallHierarchyItem - - -class CallHierarchyOutgoingCall(Model): - to: CallHierarchyItem - from_ranges: List[Range] diff --git a/pygls/lsp/types/language_features/code_action.py b/pygls/lsp/types/language_features/code_action.py deleted file mode 100644 index aad7ad9e..00000000 --- a/pygls/lsp/types/language_features/code_action.py +++ /dev/null @@ -1,99 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Code Action -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Any, List, Optional, Union - -from pygls.lsp.types.basic_structures import (Command, Diagnostic, Model, PartialResultParams, - Range, ResolveSupportClientCapabilities, - TextDocumentIdentifier, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams, - WorkspaceEdit) - - -class CodeActionKind(str, enum.Enum): - Empty = '' - QuickFix = 'quickfix' - Refactor = 'refactor' - RefactorExtract = 'refactor.extract' - RefactorInline = 'refactor.inline' - RefactorRewrite = 'refactor.rewrite' - Source = 'source' - SourceOrganizeImports = 'source.organizeImports' - - -class CodeActionLiteralSupportActionKindClientCapabilities(Model): - value_set: Optional[List[Union[str, CodeActionKind]]] - - -class CodeActionLiteralSupportClientCapabilities(Model): - code_action_kind: Optional[CodeActionLiteralSupportActionKindClientCapabilities] - - -class CodeActionClientCapabilities(Model): - dynamic_registration: Optional[bool] - code_action_literal_support: Optional[CodeActionLiteralSupportClientCapabilities] - is_preferred_support: Optional[bool] - disabled_support: Optional[bool] - data_support: Optional[bool] - resolve_support: Optional[ResolveSupportClientCapabilities] - honors_change_annotations: Optional[bool] - - -class CodeActionOptions(WorkDoneProgressOptions): - code_action_kinds: Optional[List[CodeActionKind]] - resolve_provider: Optional[bool] - - -class CodeActionRegistrationOptions(TextDocumentRegistrationOptions, CodeActionOptions): - pass - - -class CodeActionContext(Model): - diagnostics: List[Diagnostic] - only: Optional[List[CodeActionKind]] - - -class CodeActionParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - range: Range - context: CodeActionContext - - -class CodeActionDisabled(Model): - reason: str - - -class CodeAction(Model): - title: str - kind: Optional[CodeActionKind] - diagnostics: Optional[List[Diagnostic]] - is_preferred: Optional[bool] - disabled: Optional[CodeActionDisabled] - edit: Optional[WorkspaceEdit] - command: Optional[Command] - data: Optional[Any] diff --git a/pygls/lsp/types/language_features/code_lens.py b/pygls/lsp/types/language_features/code_lens.py deleted file mode 100644 index 62aa3dca..00000000 --- a/pygls/lsp/types/language_features/code_lens.py +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Code Lens -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Any, Optional - -from pygls.lsp.types.basic_structures import (Command, Model, PartialResultParams, Range, - TextDocumentIdentifier, WorkDoneProgressOptions, - WorkDoneProgressParams) - - -class CodeLensClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class CodeLensWorkspaceClientCapabilities(Model): - refresh_support: Optional[bool] - - -class CodeLensOptions(WorkDoneProgressOptions): - resolve_provider: Optional[bool] - - -class CodeLensParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - - -class CodeLens(Model): - range: Range - command: Optional[Command] - data: Optional[Any] diff --git a/pygls/lsp/types/language_features/color_presentation.py b/pygls/lsp/types/language_features/color_presentation.py deleted file mode 100644 index 8c86b44f..00000000 --- a/pygls/lsp/types/language_features/color_presentation.py +++ /dev/null @@ -1,44 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Color Presentation -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import List, Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Range, - TextDocumentIdentifier, TextEdit, - WorkDoneProgressParams) -from pygls.lsp.types.language_features.document_color import Color - - -class ColorPresentationParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - color: Color - range: Range - - -class ColorPresentation(Model): - label: str - text_edit: Optional[TextEdit] - additional_text_edits: Optional[List[TextEdit]] diff --git a/pygls/lsp/types/language_features/completion.py b/pygls/lsp/types/language_features/completion.py deleted file mode 100644 index 83a38d8e..00000000 --- a/pygls/lsp/types/language_features/completion.py +++ /dev/null @@ -1,165 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Completion -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Any, List, Optional, Union - -from pygls.lsp.types.basic_structures import (Command, MarkupContent, MarkupKind, Model, - PartialResultParams, Range, - ResolveSupportClientCapabilities, - TextDocumentPositionParams, TextEdit, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class CompletionTriggerKind(enum.IntEnum): - Invoked = 1 - TriggerCharacter = 2 - TriggerForIncompleteCompletions = 3 - - -class CompletionContext(Model): - trigger_kind: CompletionTriggerKind - trigger_character: Optional[str] - - -class InsertTextFormat(enum.IntEnum): - PlainText = 1 - Snippet = 2 - - -class CompletionItemTag(enum.IntEnum): - Deprecated = 1 - - -class CompletionItemKind(enum.IntEnum): - Text = 1 - Method = 2 - Function = 3 - Constructor = 4 - Field = 5 - Variable = 6 - Class = 7 - Interface = 8 - Module = 9 - Property = 10 - Unit = 11 - Value = 12 - Enum = 13 - Keyword = 14 - Snippet = 15 - Color = 16 - File = 17 - Reference = 18 - Folder = 19 - EnumMember = 20 - Constant = 21 - Struct = 22 - Event = 23 - Operator = 24 - TypeParameter = 25 - - -class CompletionOptions(WorkDoneProgressOptions): - trigger_characters: Optional[List[str]] - all_commit_characters: Optional[List[str]] - resolve_provider: Optional[bool] - - -class CompletionParams(TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams): - context: Optional['CompletionContext'] - - -class CompletionItemKindClientCapabilities(Model): - value_set: Optional[List[CompletionItemKind]] - - -class CompletionTagSupportClientCapabilities(Model): - value_set: Optional[List[CompletionItemTag]] - - -class InsertTextMode(enum.IntEnum): - AsIs = 1 - AdjustIndentation = 2 - - -class InsertTextModeSupportClientCapabilities(Model): - value_set: List[InsertTextMode] - - -class CompletionItemClientCapabilities(Model): - snippet_support: Optional[bool] - commit_characters_support: Optional[bool] - documentation_format: Optional[List[MarkupKind]] - deprecated_support: Optional[bool] - preselect_support: Optional[bool] - tag_support: Optional[CompletionTagSupportClientCapabilities] - insert_replace_support: Optional[bool] - resolve_support: Optional[ResolveSupportClientCapabilities] - insert_text_mode_support: Optional[InsertTextModeSupportClientCapabilities] - - -class CompletionClientCapabilities(Model): - dynamic_registration: Optional[bool] - completion_item: Optional[CompletionItemClientCapabilities] - completion_item_kind: Optional[CompletionItemKindClientCapabilities] - context_support: Optional[bool] - - -class InsertReplaceEdit(Model): - new_text: str - insert: Range - replace: Range - - -class CompletionItem(Model): - label: str - kind: Optional[CompletionItemKind] - tags: Optional[List[CompletionItemTag]] - detail: Optional[str] - documentation: Optional[Union[str, MarkupContent]] - deprecated: Optional[bool] - preselect: Optional[bool] - sort_text: Optional[str] - filter_text: Optional[str] - insert_text: Optional[str] - insert_text_format: Optional[InsertTextFormat] - insert_text_mode: Optional[InsertTextMode] - text_edit: Optional[Union[TextEdit, InsertReplaceEdit]] - additional_text_edits: Optional[List[TextEdit]] - commit_characters: Optional[List[str]] - command: Optional[Command] - data: Optional[Any] - - -class CompletionList(Model): - is_incomplete: bool - items: List[CompletionItem] - - def add_item(self, completion_item): - self.items.append(completion_item) - - def add_items(self, completion_items): - self.items.extend(completion_items) diff --git a/pygls/lsp/types/language_features/declaration.py b/pygls/lsp/types/language_features/declaration.py deleted file mode 100644 index 80531f8c..00000000 --- a/pygls/lsp/types/language_features/declaration.py +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Declaration -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, StaticRegistrationOptions, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class DeclarationClientCapabilities(Model): - dynamic_registration: Optional[bool] - link_support: Optional[bool] - - -class DeclarationOptions(WorkDoneProgressOptions): - pass - - -class DeclarationRegistrationOptions(DeclarationOptions, - TextDocumentRegistrationOptions, - StaticRegistrationOptions): - pass - - -class DeclarationParams(TextDocumentPositionParams, WorkDoneProgressParams): - pass diff --git a/pygls/lsp/types/language_features/definition.py b/pygls/lsp/types/language_features/definition.py deleted file mode 100644 index b809aa66..00000000 --- a/pygls/lsp/types/language_features/definition.py +++ /dev/null @@ -1,43 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Definition -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, TextDocumentPositionParams, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class DefinitionClientCapabilities(Model): - dynamic_registration: Optional[bool] - link_support: Optional[bool] - - -class DefinitionOptions(WorkDoneProgressOptions): - pass - - -class DefinitionParams(TextDocumentPositionParams, WorkDoneProgressParams): - pass diff --git a/pygls/lsp/types/language_features/document_color.py b/pygls/lsp/types/language_features/document_color.py deleted file mode 100644 index a4a980db..00000000 --- a/pygls/lsp/types/language_features/document_color.py +++ /dev/null @@ -1,62 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Document Color -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Range, - StaticRegistrationOptions, TextDocumentIdentifier, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class DocumentColorClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class DocumentColorOptions(WorkDoneProgressOptions): - pass - - -class DocumentColorRegistrationOptions(DocumentColorOptions, - TextDocumentRegistrationOptions, - StaticRegistrationOptions): - pass - - -class DocumentColorParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - - -class Color(Model): - red: float - green: float - blue: float - alpha: float - - -class ColorInformation(Model): - range: Range - color: Color diff --git a/pygls/lsp/types/language_features/document_highlight.py b/pygls/lsp/types/language_features/document_highlight.py deleted file mode 100644 index 76d55482..00000000 --- a/pygls/lsp/types/language_features/document_highlight.py +++ /dev/null @@ -1,60 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Document Highlight -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Range, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class DocumentHighlightClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class DocumentHighlightOptions(WorkDoneProgressOptions): - pass - - -class DocumentHighlightRegistrationOptions(TextDocumentRegistrationOptions, DocumentHighlightOptions): - pass - - -class DocumentHighlightParams(TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams): - pass - - -class DocumentHighlightKind(enum.IntEnum): - Text = 1 - Read = 2 - Write = 3 - - -class DocumentHighlight(Model): - range: Range - kind: Optional[DocumentHighlightKind] diff --git a/pygls/lsp/types/language_features/document_link.py b/pygls/lsp/types/language_features/document_link.py deleted file mode 100644 index 87b03c4f..00000000 --- a/pygls/lsp/types/language_features/document_link.py +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Document Link -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Any, Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Range, - TextDocumentIdentifier, WorkDoneProgressOptions, - WorkDoneProgressParams) - - -class DocumentLinkClientCapabilities(Model): - dynamic_registration: Optional[bool] - tooltip_support: Optional[bool] - - -class DocumentLinkOptions(WorkDoneProgressOptions): - resolve_provider: Optional[bool] - - -class DocumentLinkParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - - -class DocumentLink(Model): - range: Range - target: Optional[str] - tooltip: Optional[str] - data: Optional[Any] diff --git a/pygls/lsp/types/language_features/document_symbol.py b/pygls/lsp/types/language_features/document_symbol.py deleted file mode 100644 index ada0b674..00000000 --- a/pygls/lsp/types/language_features/document_symbol.py +++ /dev/null @@ -1,116 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Document Symbol -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import List, Optional - -from pygls.lsp.types.basic_structures import (Location, Model, PartialResultParams, Range, - TextDocumentIdentifier, WorkDoneProgressOptions, - WorkDoneProgressParams) - - -class SymbolKind(enum.IntEnum): - File = 1 - Module = 2 - Namespace = 3 - Package = 4 - Class = 5 - Method = 6 - Property = 7 - Field = 8 - Constructor = 9 - Enum = 10 - Interface = 11 - Function = 12 - Variable = 13 - Constant = 14 - String = 15 - Number = 16 - Boolean = 17 - Array = 18 - Object = 19 - Key = 20 - Null = 21 - EnumMember = 22 - Struct = 23 - Event = 24 - Operator = 25 - TypeParameter = 26 - - -class SymbolTag(enum.IntEnum): - Deprecated = 1 - - -class WorkspaceCapabilitiesSymbolKind(Model): - value_set: Optional[List[SymbolKind]] - - -class WorkspaceCapabilitiesTagSupport(Model): - value_set: List[SymbolKind] - - -class DocumentSymbolCapabilitiesTagSupport(Model): - value_set: List[SymbolTag] - - -class DocumentSymbolClientCapabilities(Model): - dynamic_registration: Optional[bool] - symbol_kind: Optional[WorkspaceCapabilitiesSymbolKind] - hierarchical_document_symbol_support: Optional[bool] - tag_support: Optional[WorkspaceCapabilitiesTagSupport] - label_support: Optional[bool] - - -class DocumentSymbolOptions(WorkDoneProgressOptions): - label: Optional[str] - - -class DocumentSymbolParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - - -class DocumentSymbol(Model): - name: str - kind: SymbolKind - range: Range - selection_range: Range - detail: Optional[str] - children: Optional[List['DocumentSymbol']] - tags: Optional[List[SymbolTag]] - deprecated: Optional[bool] - - -DocumentSymbol.update_forward_refs() - - -class SymbolInformation(Model): - name: str - kind: SymbolKind - location: Location - container_name: Optional[str] - tags: Optional[List[SymbolTag]] - deprecated: Optional[bool] diff --git a/pygls/lsp/types/language_features/folding_range.py b/pygls/lsp/types/language_features/folding_range.py deleted file mode 100644 index 222a69b4..00000000 --- a/pygls/lsp/types/language_features/folding_range.py +++ /dev/null @@ -1,67 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Folding Range -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, NumType, PartialResultParams, - StaticRegistrationOptions, TextDocumentIdentifier, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class FoldingRangeClientCapabilities(Model): - dynamic_registration: Optional[bool] - range_limit: Optional[NumType] - line_folding_only: Optional[bool] - - -class FoldingRangeOptions(WorkDoneProgressOptions): - pass - - -class FoldingRangeRegistrationOptions(FoldingRangeOptions, - TextDocumentRegistrationOptions, - StaticRegistrationOptions): - pass - - -class FoldingRangeParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - - -class FoldingRangeKind(str, enum.Enum): - Comment = 'comment' - Imports = 'imports' - Region = 'region' - - -class FoldingRange(Model): - start_line: int - end_line: int - start_character: Optional[int] - end_character: Optional[int] - kind: Optional[FoldingRangeKind] diff --git a/pygls/lsp/types/language_features/formatting.py b/pygls/lsp/types/language_features/formatting.py deleted file mode 100644 index c1e29358..00000000 --- a/pygls/lsp/types/language_features/formatting.py +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Formatting -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, TextDocumentIdentifier, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class DocumentFormattingClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class DocumentFormattingOptions(WorkDoneProgressOptions): - pass - - -class FormattingOptions(Model): - tab_size: int - insert_spaces: bool - trim_trailing_whitespace: Optional[bool] - insert_final_newline: Optional[bool] - trim_final_newlines: Optional[bool] - - -class DocumentFormattingParams(WorkDoneProgressParams): - text_document: TextDocumentIdentifier - options: FormattingOptions diff --git a/pygls/lsp/types/language_features/hover.py b/pygls/lsp/types/language_features/hover.py deleted file mode 100644 index ebf0d37f..00000000 --- a/pygls/lsp/types/language_features/hover.py +++ /dev/null @@ -1,57 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Hover -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import List, Optional, Union - -from pygls.lsp.types.basic_structures import (MarkupContent, MarkupKind, Model, Range, - TextDocumentPositionParams, WorkDoneProgressOptions, - WorkDoneProgressParams) - - -class HoverClientCapabilities(Model): - dynamic_registration: Optional[bool] - content_format: Optional[List[MarkupKind]] - - -class HoverOptions(WorkDoneProgressOptions): - pass - - -class HoverParams(TextDocumentPositionParams, WorkDoneProgressParams): - pass - - -class MarkedString(Model): - language: str - value: str - - -MarkedStringType = Union[str, MarkedString] - - -class Hover(Model): - contents: Union[MarkedStringType, List[MarkedStringType], MarkupContent] - range: Optional[Range] diff --git a/pygls/lsp/types/language_features/implementation.py b/pygls/lsp/types/language_features/implementation.py deleted file mode 100644 index d03102b4..00000000 --- a/pygls/lsp/types/language_features/implementation.py +++ /dev/null @@ -1,52 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Implementation -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, - StaticRegistrationOptions, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class ImplementationClientCapabilities(Model): - dynamic_registration: Optional[bool] - link_support: Optional[bool] - - -class ImplementationOptions(WorkDoneProgressOptions): - pass - - -class ImplementationRegistrationOptions(ImplementationOptions, - TextDocumentRegistrationOptions, - StaticRegistrationOptions): - pass - - -class ImplementationParams(TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams): - pass diff --git a/pygls/lsp/types/language_features/linked_editing_range.py b/pygls/lsp/types/language_features/linked_editing_range.py deleted file mode 100644 index ed19b24d..00000000 --- a/pygls/lsp/types/language_features/linked_editing_range.py +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Linked Editing Range -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import List, Optional - -from pygls.lsp.types.basic_structures import (Model, Range, StaticRegistrationOptions, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class LinkedEditingRangeClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class LinkedEditingRangeOptions(WorkDoneProgressOptions): - pass - - -class LinkedEditingRangeRegistrationOptions(TextDocumentRegistrationOptions, LinkedEditingRangeOptions, StaticRegistrationOptions): - pass - - -class LinkedEditingRangeParams(TextDocumentPositionParams, WorkDoneProgressParams): - pass - - -class LinkedEditingRanges(Model): - ranges: List[Range] - word_pattern: Optional[str] diff --git a/pygls/lsp/types/language_features/monikers.py b/pygls/lsp/types/language_features/monikers.py deleted file mode 100644 index 45fa1fec..00000000 --- a/pygls/lsp/types/language_features/monikers.py +++ /dev/null @@ -1,70 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Monikers -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class MonikerClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class MonikerOptions(WorkDoneProgressOptions): - pass - - -class MonikerRegistrationOptions(TextDocumentRegistrationOptions, MonikerOptions): - pass - - -class MonikerParams(TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams): - pass - - -class UniquenessLevel(str, enum.Enum): - Document = 'document' - Project = 'project' - Group = 'group' - Scheme = 'scheme' - Global = 'global' - - -class MonikerKind(str, enum.Enum): - Import = 'import' - Export = 'export' - Local = 'local' - - -class Moniker(Model): - scheme: str - identifier: str - unique: UniquenessLevel - kind: Optional[MonikerKind] diff --git a/pygls/lsp/types/language_features/on_type_formatting.py b/pygls/lsp/types/language_features/on_type_formatting.py deleted file mode 100644 index 24d2c36e..00000000 --- a/pygls/lsp/types/language_features/on_type_formatting.py +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - On Type Formatting -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import List, Optional - -from pygls.lsp.types.basic_structures import (Model, TextDocumentPositionParams, - WorkDoneProgressOptions) -from pygls.lsp.types.language_features.formatting import FormattingOptions - - -class DocumentOnTypeFormattingClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class DocumentOnTypeFormattingOptions(WorkDoneProgressOptions): - first_trigger_character: str - more_trigger_character: Optional[List[str]] - - -class DocumentOnTypeFormattingParams(TextDocumentPositionParams): - ch: str - options: FormattingOptions diff --git a/pygls/lsp/types/language_features/prepare_rename.py b/pygls/lsp/types/language_features/prepare_rename.py deleted file mode 100644 index c8fd5c66..00000000 --- a/pygls/lsp/types/language_features/prepare_rename.py +++ /dev/null @@ -1,37 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Prepare Rename -- - -Class attributes are named with camel case notation because client is expecting -that. -""" - -from pygls.lsp.types.basic_structures import Model, Range, TextDocumentPositionParams - - -class PrepareRenameParams(TextDocumentPositionParams): - pass - - -class PrepareRename(Model): - range: Range - placeholder: str diff --git a/pygls/lsp/types/language_features/range_formatting.py b/pygls/lsp/types/language_features/range_formatting.py deleted file mode 100644 index 346b4a9b..00000000 --- a/pygls/lsp/types/language_features/range_formatting.py +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Range Formatting -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, Range, TextDocumentIdentifier, - WorkDoneProgressOptions, WorkDoneProgressParams) -from pygls.lsp.types.language_features.formatting import FormattingOptions - - -class DocumentRangeFormattingClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class DocumentRangeFormattingOptions(WorkDoneProgressOptions): - pass - - -class DocumentRangeFormattingParams(WorkDoneProgressParams): - text_document: TextDocumentIdentifier - range: Range - options: FormattingOptions diff --git a/pygls/lsp/types/language_features/references.py b/pygls/lsp/types/language_features/references.py deleted file mode 100644 index 51d22042..00000000 --- a/pygls/lsp/types/language_features/references.py +++ /dev/null @@ -1,47 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - References -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, - TextDocumentPositionParams, WorkDoneProgressOptions, - WorkDoneProgressParams) - - -class ReferenceClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class ReferenceOptions(WorkDoneProgressOptions): - pass - - -class ReferenceContext(Model): - include_declaration: bool - - -class ReferenceParams(TextDocumentPositionParams, WorkDoneProgressParams, PartialResultParams): - context: ReferenceContext diff --git a/pygls/lsp/types/language_features/rename.py b/pygls/lsp/types/language_features/rename.py deleted file mode 100644 index d927efe1..00000000 --- a/pygls/lsp/types/language_features/rename.py +++ /dev/null @@ -1,50 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Rename -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, TextDocumentPositionParams, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class PrepareSupportDefaultBehavior(enum.IntEnum): - Identifier = 1 - - -class RenameClientCapabilities(Model): - dynamic_registration: Optional[bool] - prepare_support: Optional[bool] - prepare_support_default_behavior: Optional[PrepareSupportDefaultBehavior] - honors_change_annotations: Optional[bool] - - -class RenameOptions(WorkDoneProgressOptions): - prepare_provider: Optional[bool] - - -class RenameParams(TextDocumentPositionParams, WorkDoneProgressParams): - new_name: str diff --git a/pygls/lsp/types/language_features/selection_range.py b/pygls/lsp/types/language_features/selection_range.py deleted file mode 100644 index c17c4844..00000000 --- a/pygls/lsp/types/language_features/selection_range.py +++ /dev/null @@ -1,60 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Selection Range -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import List, Optional - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Position, Range, - StaticRegistrationOptions, TextDocumentIdentifier, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class SelectionRangeClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class SelectionRangeOptions(WorkDoneProgressOptions): - pass - - -class SelectionRangeRegistrationOptions(SelectionRangeOptions, - TextDocumentRegistrationOptions, - StaticRegistrationOptions): - pass - - -class SelectionRangeParams(WorkDoneProgressParams, PartialResultParams): - query: str - text_document: TextDocumentIdentifier - positions: List[Position] - - -class SelectionRange(Model): - range: Range - parent: Optional['SelectionRange'] - - -SelectionRange.update_forward_refs() diff --git a/pygls/lsp/types/language_features/semantic_tokens.py b/pygls/lsp/types/language_features/semantic_tokens.py deleted file mode 100644 index 9540fb89..00000000 --- a/pygls/lsp/types/language_features/semantic_tokens.py +++ /dev/null @@ -1,151 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Semantic Tokens -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Dict, List, Optional, Union - -from pygls.lsp.types.basic_structures import (Model, PartialResultParams, Range, - StaticRegistrationOptions, TextDocumentIdentifier, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class SemanticTokensWorkspaceClientCapabilities(Model): - refresh_support: Optional[bool] - - -class SemanticTokenTypes(str, enum.Enum): - Namespace = 'namespace' - Type = 'type' - Class = 'class' - Enum = 'enum' - Interface = 'interface' - Struct = 'struct' - TypeParameter = 'typeParameter' - Parameter = 'parameter' - Variable = 'variable' - Property = 'property' - EnumMember = 'enumMember' - Event = 'event' - Function = 'function' - Method = 'method' - Macro = 'macro' - Keyword = 'keyword' - Modifier = 'modifier' - Comment = 'comment' - String = 'string' - Number = 'number' - Regexp = 'regexp' - Operator = 'operator' - - -class SemanticTokenModifiers(str, enum.Enum): - Declaration = 'declaration' - Definition = 'definition' - Readonly = 'readonly' - Static = 'static' - Deprecated = 'deprecated' - Abstract = 'abstract' - Async = 'async' - Modification = 'modification' - Documentation = 'documentation' - DefaultLibrary = 'defaultLibrary' - - -class TokenFormat(str, enum.Enum): - Relative = 'relative' - - -class SemanticTokensLegend(Model): - token_types: List[str] - token_modifiers: List[str] - - -class SemanticTokensRequestsFull(Model): - delta: Optional[bool] - - -class SemanticTokensRequests(Model): - range: Optional[Union[bool, Dict]] - full: Optional[Union[bool, SemanticTokensRequestsFull]] - - -class SemanticTokensClientCapabilities(Model): - requests: SemanticTokensRequests - token_types: List[str] - token_modifiers: List[str] - formats: List[TokenFormat] - overlapping_token_support: Optional[bool] - multiline_token_support: Optional[bool] - dynamic_registration: Optional[bool] - - -class SemanticTokensOptions(WorkDoneProgressOptions): - legend: SemanticTokensLegend - range: Optional[Union[bool, Dict]] - full: Optional[Union[bool, SemanticTokensRequestsFull]] - - -class SemanticTokensRegistrationOptions(TextDocumentRegistrationOptions, SemanticTokensOptions, StaticRegistrationOptions): - pass - - -class SemanticTokensParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - - -class SemanticTokens(Model): - data: List[int] - result_id: Optional[str] - - -class SemanticTokensPartialResult(Model): - data: List[int] - - -class SemanticTokensDeltaParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - previous_result_id: str - - -class SemanticTokensEdit(Model): - start: int - delete_count: int - data: Optional[List[int]] - - -class SemanticTokensDelta(Model): - edits: List[SemanticTokensEdit] - result_id: Optional[str] - - -class SemanticTokensDeltaPartialResult(Model): - edits: List[SemanticTokensEdit] - - -class SemanticTokensRangeParams(WorkDoneProgressParams, PartialResultParams): - text_document: TextDocumentIdentifier - range: Range diff --git a/pygls/lsp/types/language_features/signature_help.py b/pygls/lsp/types/language_features/signature_help.py deleted file mode 100644 index 79c7b943..00000000 --- a/pygls/lsp/types/language_features/signature_help.py +++ /dev/null @@ -1,88 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Signature Help -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import List, Optional, Tuple, Union - -from pygls.lsp.types.basic_structures import (MarkupContent, MarkupKind, Model, NumType, - TextDocumentPositionParams, WorkDoneProgressOptions, - WorkDoneProgressParams) - - -class SignatureHelpInformationParameterInformationClientCapabilities(Model): - label_offset_support: Optional[bool] - - -class SignatureHelpInformationClientCapabilities(Model): - documentation_format: Optional[List[MarkupKind]] - parameter_information: Optional[SignatureHelpInformationParameterInformationClientCapabilities] - active_parameter_support: Optional[bool] - - -class SignatureHelpClientCapabilities(Model): - dynamic_registration: Optional[bool] - signature_information: Optional[SignatureHelpInformationClientCapabilities] - context_support: Optional[bool] - - -class SignatureHelpOptions(WorkDoneProgressOptions): - trigger_characters: Optional[List[str]] - retrigger_characters: Optional[List[str]] - - -class SignatureHelpTriggerKind(enum.IntEnum): - Invoked = 1 - TriggerCharacter = 2 - ContentChange = 3 - - -class ParameterInformation(Model): - label: Union[str, Tuple[int, int]] - documentation: Optional[Union[str, MarkupContent]] - - -class SignatureInformation(Model): - label: str - documentation: Optional[Union[str, MarkupContent]] - parameters: Optional[List[ParameterInformation]] - active_parameter: Optional[int] - - -class SignatureHelp(Model): - signatures: List[SignatureInformation] - active_signature: Optional[NumType] - active_parameter: Optional[NumType] - - -class SignatureHelpContext(Model): - trigger_kind: SignatureHelpTriggerKind - is_retrigger: bool - trigger_character: Optional[str] - active_signature_help: Optional[SignatureHelp] - - -class SignatureHelpParams(TextDocumentPositionParams, WorkDoneProgressParams): - context: Optional[SignatureHelpContext] diff --git a/pygls/lsp/types/language_features/type_definition.py b/pygls/lsp/types/language_features/type_definition.py deleted file mode 100644 index acaea913..00000000 --- a/pygls/lsp/types/language_features/type_definition.py +++ /dev/null @@ -1,51 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Language Features - Type Definition -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -from typing import Optional - -from pygls.lsp.types.basic_structures import (Model, StaticRegistrationOptions, - TextDocumentPositionParams, - TextDocumentRegistrationOptions, - WorkDoneProgressOptions, WorkDoneProgressParams) - - -class TypeDefinitionClientCapabilities(Model): - dynamic_registration: Optional[bool] - link_support: Optional[bool] - - -class TypeDefinitionOptions(WorkDoneProgressOptions): - pass - - -class TypeDefinitionRegistrationOptions(TypeDefinitionOptions, - TextDocumentRegistrationOptions, - StaticRegistrationOptions): - pass - - -class TypeDefinitionParams(TextDocumentPositionParams, WorkDoneProgressParams): - pass diff --git a/pygls/lsp/types/text_synchronization.py b/pygls/lsp/types/text_synchronization.py deleted file mode 100644 index 3011a266..00000000 --- a/pygls/lsp/types/text_synchronization.py +++ /dev/null @@ -1,46 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Text Synchronization -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Optional - -from pygls.lsp.types import TextDocumentRegistrationOptions -from pygls.lsp.types.basic_structures import Model - - -class TextDocumentSyncKind(enum.IntEnum): - NONE = 0 - FULL = 1 - INCREMENTAL = 2 - - -class TextDocumentSyncOptions(Model): - open_close: Optional[bool] - change: Optional[TextDocumentSyncKind] - - -class TextDocumentSaveRegistrationOptions(TextDocumentRegistrationOptions): - include_text: Optional[bool] diff --git a/pygls/lsp/types/window.py b/pygls/lsp/types/window.py deleted file mode 100644 index a88115a5..00000000 --- a/pygls/lsp/types/window.py +++ /dev/null @@ -1,91 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Window -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Callable, List, Optional - -from pygls.lsp.types.basic_structures import URI, Model, NumType, ProgressToken, Range - - -class MessageType(enum.IntEnum): - Error = 1 - Warning = 2 - Info = 3 - Log = 4 - - -class ShowMessageParams(Model): - type: MessageType - message: str - - -class MessageActionItem(Model): - title: str - - -class ShowMessageRequestParams(Model): - type: MessageType - message: str - actions: Optional[List[MessageActionItem]] - - -class ShowDocumentClientCapabilities(Model): - support: Optional[bool] - - -class ShowDocumentParams(Model): - uri: URI - external: Optional[bool] - take_focus: Optional[bool] - selection: Optional[Range] - - -class ShowDocumentResult(Model): - success: bool - - -class ShowMessageRequestActionItem(Model): - additional_properties_support: Optional[bool] - - -class ShowMessageRequestClientCapabilities(Model): - message_action_item: Optional[ShowMessageRequestActionItem] - - -class LogMessageParams(Model): - type: NumType - message: str - - -class WorkDoneProgressCreateParams(Model): - token: ProgressToken - - -class WorkDoneProgressCancelParams(Model): - token: ProgressToken - - -ShowDocumentCallbackType = Callable[[ShowDocumentResult], None] diff --git a/pygls/lsp/types/workspace.py b/pygls/lsp/types/workspace.py deleted file mode 100644 index 63111e41..00000000 --- a/pygls/lsp/types/workspace.py +++ /dev/null @@ -1,202 +0,0 @@ -############################################################################ -# Original work Copyright 2017 Palantir Technologies, Inc. # -# Original work licensed under the MIT License. # -# See ThirdPartyNotices.txt in the project root for license information. # -# All modifications Copyright (c) Open Law Library. All rights reserved. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -"""This module contains Language Server Protocol types -https://microsoft.github.io/language-server-protocol/specification - --- Workspace -- - -Class attributes are named with camel case notation because client is expecting -that. -""" -import enum -from typing import Any, List, Optional, Union - -from pygls.lsp.types.basic_structures import (Model, NumType, PartialResultParams, Range, - TextDocumentIdentifier, TextDocumentItem, - VersionedTextDocumentIdentifier, - WorkDoneProgressOptions, WorkDoneProgressParams, - WorkspaceEdit) -from pygls.lsp.types.language_features.document_symbol import (WorkspaceCapabilitiesSymbolKind, - WorkspaceCapabilitiesTagSupport) - - -class WorkspaceFoldersServerCapabilities(Model): - supported: Optional[bool] - change_notifications: Optional[Union[bool, str]] - - -class WorkspaceFolder(Model): - uri: str - name: str - - -class WorkspaceFoldersChangeEvent(Model): - added: List[WorkspaceFolder] - removed: List[WorkspaceFolder] - - -class DidChangeWorkspaceFoldersParams(Model): - event: WorkspaceFoldersChangeEvent - - -class DidChangeConfigurationClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class DidChangeConfigurationParams(Model): - settings: Any - - -class ConfigurationItem(Model): - scope_uri: Optional[str] - section: Optional[str] - - -class ConfigurationParams(Model): - items: List[ConfigurationItem] - - -class DidChangeWatchedFilesClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class WatchKind(enum.IntFlag): - Create = 1 - Change = 2 - Delete = 4 - - -class FileSystemWatcher(Model): - glob_pattern: str - kind: Optional[WatchKind] - - -class DidChangeWatchedFilesRegistrationOptions(Model): - watchers: List[FileSystemWatcher] - - -class FileChangeType(enum.IntEnum): - Created = 1 - Changed = 2 - Deleted = 3 - - -class FileEvent(Model): - uri: str - type: FileChangeType - - -class DidChangeWatchedFilesParams(Model): - changes: List[FileEvent] - - -class WorkspaceSymbolClientCapabilities(Model): - dynamic_registration: Optional[bool] - symbol_kind: Optional[WorkspaceCapabilitiesSymbolKind] - tag_support: Optional[WorkspaceCapabilitiesTagSupport] - - -class WorkspaceSymbolOptions(WorkDoneProgressOptions): - pass - - -class WorkspaceSymbolRegistrationOptions(WorkspaceSymbolOptions): - pass - - -class WorkspaceSymbolParams(WorkDoneProgressParams, PartialResultParams): - query: str - - -class ExecuteCommandClientCapabilities(Model): - dynamic_registration: Optional[bool] - - -class ExecuteCommandOptions(WorkDoneProgressOptions): - commands: List[str] - - -class ExecuteCommandRegistrationOptions(ExecuteCommandOptions): - pass - - -class ExecuteCommandParams(WorkDoneProgressParams): - command: str - arguments: Optional[List[Any]] - - -class ApplyWorkspaceEditParams(Model): - edit: WorkspaceEdit - label: Optional[str] - - -class ApplyWorkspaceEditResponse(Model): - applied: bool - failure_reason: Optional[str] - - -class DidOpenTextDocumentParams(Model): - text_document: TextDocumentItem - - -class TextDocumentContentChangeEvent(Model): - range: Optional[Range] - range_length: Optional[NumType] - text: str - - -class TextDocumentContentChangeTextEvent(Model): - text: str - - -class DidChangeTextDocumentParams(Model): - text_document: VersionedTextDocumentIdentifier - content_changes: Union[List[TextDocumentContentChangeEvent], - List[TextDocumentContentChangeTextEvent]] - - -class TextDocumentSaveReason(enum.IntEnum): - Manual = 1 - AfterDelay = 2 - FocusOut = 3 - - -class WillSaveTextDocumentParams(Model): - text_document: TextDocumentIdentifier - reason: TextDocumentSaveReason - - -class SaveOptions(Model): - include_text: Optional[bool] - - -class DidSaveTextDocumentParams(Model): - text_document: TextDocumentIdentifier - text: Optional[str] - - -class DidCloseTextDocumentParams(Model): - text_document: TextDocumentIdentifier - - -class TextDocumentSyncClientCapabilities(Model): - dynamic_registration: Optional[bool] - will_save: Optional[bool] - will_save_wait_until: Optional[bool] - did_save: Optional[bool] From d349d06aebaafe5f6960ac3fe7656146b6894713 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 14 Aug 2022 16:05:30 +0100 Subject: [PATCH 2/9] Drop pydantic, use lsprotocol. The `lsprotocol.types` module is re-exported through the `pygls.lsp.types` module hopefully minimsing the number of broken imports. This also drops pygls' `LSP_METHODS_MAP` in favour of the `METHOD_TO_TYPES` map provided by `lsprotocol`. The `get_method_xxx_type` functions have been adjusted to use the new mapping. As far as I can tell `lsprotocol` doesn't provide generic JSON RPC message types (except for `ResponseErrorMessage`) so the old `JsonRPCNotification`, `JsonRPCResponseMessage` and `JsonRPCRequestMessage` types have been preserved and converted to `attrs`. --- pygls/lsp/__init__.py | 316 ++++-------------------------------------- pygls/lsp/types.py | 24 ++++ setup.cfg | 6 +- 3 files changed, 55 insertions(+), 291 deletions(-) create mode 100644 pygls/lsp/types.py diff --git a/pygls/lsp/__init__.py b/pygls/lsp/__init__.py index ff50c1e8..c7d8dbf3 100644 --- a/pygls/lsp/__init__.py +++ b/pygls/lsp/__init__.py @@ -14,316 +14,60 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -from typing import Any, List, Union +from typing import Any, Union +import attrs +from lsprotocol.types import METHOD_TO_TYPES from typeguard import check_type from pygls.exceptions import MethodTypeNotRegisteredError -from pygls.lsp.methods import * -from pygls.lsp.types import * -__LSP_VERSION__ = "3.15" +@attrs.define +class JsonRPCNotification: + """A class that represents json rpc notification message.""" -# Holds lsp methods and their appropriate types. It is used for type-checking. -# { -# 'COMPLETION': (CompletionOptions, CompletionParams, Union[List[CompletionItem], CompletionList, None]) -# } -# where: -# - CompletionOptions is used when registering a method: -# - CompletionParams are received from the client -# - Union[List[CompletionItem], CompletionList, None] should be returned by the server (result field of ResponseMessage) -# -# @json_server.feature(COMPLETION, CompletionOptions(trigger_characters=[','])) -# def completions(params: CompletionParams = None) -> Union[List[CompletionItem], CompletionList, None]: -# """Returns completion items.""" + jsonrpc: str + method: str + params: Any -# TODO: support partial-results types -LSP_METHODS_MAP = { - # Special methods - CANCEL_REQUEST: (None, CancelParams, None, ), - PROGRESS_NOTIFICATION: (None, ProgressParams, None, ), - LOG_TRACE_NOTIFICATION: (None, None, LogTraceParams, ), - SET_TRACE_NOTIFICATION: (None, SetTraceParams, None, ), - # General messages - INITIALIZE: (None, InitializeParams, InitializeResult, ), - INITIALIZED: (None, InitializedParams, None, ), - SHUTDOWN: (None, None, None, ), - EXIT: (None, None, None, ), - # Window - WINDOW_SHOW_MESSAGE: (None, None, ShowMessageParams, ), - WINDOW_SHOW_DOCUMENT: (None, ShowDocumentParams, ShowDocumentResult, ), - WINDOW_SHOW_MESSAGE_REQUEST: (None, None, ShowMessageRequestParams, ), - WINDOW_LOG_MESSAGE: (None, None, LogMessageParams, ), - WINDOW_WORK_DONE_PROGRESS_CREATE: (None, None, WorkDoneProgressCreateParams, ), - WINDOW_WORK_DONE_PROGRESS_CANCEL: (None, None, WorkDoneProgressCancelParams, ), - # Telemetry - TELEMETRY_EVENT: (None, None, Any, ), - # Client - (un)register capabilities - CLIENT_REGISTER_CAPABILITY: (None, None, RegistrationParams, ), - CLIENT_UNREGISTER_CAPABILITY: (None, None, UnregistrationParams, ), - # Workspace - WORKSPACE_APPLY_EDIT: (None, ApplyWorkspaceEditResponse, ApplyWorkspaceEditParams, ), - WORKSPACE_CODE_LENS_REFRESH: (None, None, None), - WORKSPACE_CONFIGURATION: (None, List[Any], ConfigurationParams, ), - WORKSPACE_DID_CHANGE_CONFIGURATION: (None, DidChangeConfigurationParams, None, ), - WORKSPACE_DID_CHANGE_WATCHED_FILES: (None, DidChangeWatchedFilesParams, None, ), - WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS: (None, DidChangeWorkspaceFoldersParams, None, ), - WORKSPACE_EXECUTE_COMMAND: (None, ExecuteCommandParams, Optional[Any], ), - WORKSPACE_FOLDERS: (None, Optional[List[WorkspaceFolder]], None, ), - WORKSPACE_SEMANTIC_TOKENS_REFRESH: (None, None, None), - WORKSPACE_SYMBOL: (None, WorkspaceSymbolParams, Optional[List[SymbolInformation]], ), - # Text Document Synchronization - TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE: ( - Union[CallHierarchyOptions, CallHierarchyRegistrationOptions], - CallHierarchyPrepareParams, - Optional[List[CallHierarchyItem]], - ), - TEXT_DOCUMENT_CALL_HIERARCHY_INCOMING_CALLS: ( - None, - CallHierarchyIncomingCallsParams, - Optional[List[CallHierarchyIncomingCall]], - ), - TEXT_DOCUMENT_CALL_HIERARCHY_OUTGOING_CALLS: ( - None, - CallHierarchyOutgoingCallsParams, - Optional[List[CallHierarchyOutgoingCall]], - ), - TEXT_DOCUMENT_DID_OPEN: (None, DidOpenTextDocumentParams, None, ), - TEXT_DOCUMENT_DID_CHANGE: (None, DidChangeTextDocumentParams, None, ), - TEXT_DOCUMENT_WILL_SAVE: (None, WillSaveTextDocumentParams, None, ), - TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL: (None, WillSaveTextDocumentParams, None, ), - TEXT_DOCUMENT_DID_SAVE: ( - TextDocumentSaveRegistrationOptions, - DidSaveTextDocumentParams, - None, - ), - TEXT_DOCUMENT_LINKED_EDITING_RANGE: ( - Union[LinkedEditingRangeOptions, LinkedEditingRangeRegistrationOptions], - LinkedEditingRangeParams, - Optional[LinkedEditingRanges], - ), - TEXT_DOCUMENT_MONIKER: ( - Union[MonikerOptions, MonikerRegistrationOptions], - MonikerParams, - Optional[List[Moniker]], - ), - TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL: ( - Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], - SemanticTokensParams, - Union[SemanticTokensPartialResult, Optional[SemanticTokens]], - ), - TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA: ( - Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], - SemanticTokensDeltaParams, - Union[SemanticTokensDeltaPartialResult, Optional[Union[SemanticTokens, SemanticTokensDelta]]], - ), - TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE: ( - Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], - SemanticTokensRangeParams, - Union[SemanticTokensPartialResult, Optional[SemanticTokens]], +@attrs.define +class JsonRPCRequestMessage: + """A class that represents json rpc request message.""" - ), - TEXT_DOCUMENT_DID_CLOSE: (None, DidCloseTextDocumentParams, None, ), - # File operations - WORKSPACE_WILL_CREATE_FILES: ( - FileOperationRegistrationOptions, - CreateFilesParams, - Optional[WorkspaceEdit], - ), - WORKSPACE_DID_CREATE_FILES: ( - FileOperationRegistrationOptions, - CreateFilesParams, - None, - ), - WORKSPACE_WILL_RENAME_FILES: ( - FileOperationRegistrationOptions, - RenameFilesParams, - Optional[WorkspaceEdit], - ), - WORKSPACE_DID_RENAME_FILES: ( - FileOperationRegistrationOptions, - RenameFilesParams, - None, - ), - WORKSPACE_WILL_DELETE_FILES: ( - FileOperationRegistrationOptions, - DeleteFilesParams, - Optional[WorkspaceEdit], - ), - WORKSPACE_DID_DELETE_FILES: ( - FileOperationRegistrationOptions, - DeleteFilesParams, - None, - ), - # Diagnostics notification - TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS: (None, None, PublishDiagnosticsParams, ), - # Language features - COMPLETION: ( - CompletionOptions, - CompletionParams, - Union[List[CompletionItem], CompletionList, None], - ), - COMPLETION_ITEM_RESOLVE: ( - None, - CompletionItem, - CompletionItem, - ), - HOVER: ( - HoverOptions, - HoverParams, - Optional[Hover], - ), - SIGNATURE_HELP: ( - SignatureHelpOptions, - SignatureHelpParams, - Optional[SignatureHelp], - ), - DECLARATION: ( - DeclarationOptions, - DeclarationParams, - Union[Location, List[Location], List[LocationLink], None], - ), - DEFINITION: ( - DefinitionOptions, - DefinitionParams, - Union[Location, List[Location], List[LocationLink], None], - ), - TYPE_DEFINITION: ( - TypeDefinitionOptions, - TypeDefinitionParams, - Union[Location, List[Location], List[LocationLink], None], - ), - IMPLEMENTATION: ( - ImplementationOptions, - ImplementationParams, - Union[Location, List[Location], List[LocationLink], None], - ), - REFERENCES: ( - ReferenceOptions, - ReferenceParams, - Optional[List[Location]], - ), - DOCUMENT_HIGHLIGHT: ( - DocumentHighlightOptions, - DocumentHighlightParams, - Optional[List[DocumentHighlight]], - ), - DOCUMENT_SYMBOL: ( - DocumentSymbolOptions, - DocumentSymbolParams, - Union[List[DocumentSymbol], List[SymbolInformation], None], - ), - CODE_ACTION: ( - Union[CodeActionOptions, CodeActionRegistrationOptions], - CodeActionParams, - Optional[List[Union[Command, CodeAction]]], - ), - CODE_ACTION_RESOLVE: ( - None, - CodeAction, - CodeAction, - ), - CODE_LENS: ( - CodeLensOptions, - CodeLensParams, - Optional[List[CodeLens]], - ), - CODE_LENS_RESOLVE: ( - None, - CodeLens, - CodeLens, - ), - DOCUMENT_LINK: ( - DocumentLinkOptions, - DocumentLinkParams, - Optional[List[DocumentLink]], - ), - DOCUMENT_LINK_RESOLVE: ( - None, - DocumentLink, - DocumentLink, - ), - DOCUMENT_COLOR: ( - DocumentColorOptions, - DocumentColorParams, - List[ColorInformation], - ), - COLOR_PRESENTATION: ( - None, - ColorPresentationParams, - List[ColorPresentation], - ), - FORMATTING: ( - DocumentFormattingOptions, - DocumentFormattingParams, - Optional[List[TextEdit]], - ), - RANGE_FORMATTING: ( - DocumentRangeFormattingOptions, - DocumentRangeFormattingParams, - Optional[List[TextEdit]], - ), - ON_TYPE_FORMATTING: ( - DocumentOnTypeFormattingOptions, - DocumentOnTypeFormattingParams, - Optional[List[TextEdit]], - ), - RENAME: ( - RenameOptions, - RenameParams, - Optional[WorkspaceEdit], - ), - PREPARE_RENAME: ( - None, - PrepareRenameParams, - Union[Range, PrepareRename, None], - ), - FOLDING_RANGE: ( - FoldingRangeOptions, - FoldingRangeParams, - Optional[List[FoldingRange]], - ), - SELECTION_RANGE: ( - SelectionRangeOptions, - SelectionRangeParams, - Optional[List[SelectionRange]], - ), -} + jsonrpc: str + id: Union[int, str] + method: str + params: Any -def get_method_registration_options_type(method_name, lsp_methods_map=LSP_METHODS_MAP): - try: - return lsp_methods_map[method_name][0] - except KeyError: - raise MethodTypeNotRegisteredError(method_name) +@attrs.define +class JsonRPCResponseMessage: + """A class that represents json rpc response message.""" + jsonrpc: str + id: Union[int, str] + result: Union[Any, None] = attrs.field(default=None) -def get_method_params_type(method_name, lsp_methods_map=LSP_METHODS_MAP): + +def get_method_registration_options_type(method_name, lsp_methods_map=METHOD_TO_TYPES): try: - return lsp_methods_map[method_name][1] + return lsp_methods_map[method_name][3] except KeyError: raise MethodTypeNotRegisteredError(method_name) -def get_method_return_type(method_name, lsp_methods_map=LSP_METHODS_MAP): +def get_method_params_type(method_name, lsp_methods_map=METHOD_TO_TYPES): try: return lsp_methods_map[method_name][2] except KeyError: raise MethodTypeNotRegisteredError(method_name) -def _get_origin(t): +def get_method_return_type(method_name, lsp_methods_map=METHOD_TO_TYPES): try: - return t.__origin__ - except AttributeError: - return None - - -def _get_args(t): - try: - return t.__args__ - except AttributeError: - return None + return lsp_methods_map[method_name][1] + except KeyError: + raise MethodTypeNotRegisteredError(method_name) def is_instance(o, t): diff --git a/pygls/lsp/types.py b/pygls/lsp/types.py new file mode 100644 index 00000000..f36b6e37 --- /dev/null +++ b/pygls/lsp/types.py @@ -0,0 +1,24 @@ +############################################################################ +# Copyright(c) Open Law Library. All rights reserved. # +# See ThirdPartyNotices.txt in the project root for additional notices. # +# # +# Licensed under the Apache License, Version 2.0 (the "License") # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http: // www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +############################################################################ +# flake8: noqa +from typing import Any, Callable, List + +from lsprotocol.types import * + + +ConfigCallbackType = Callable[[List[Any]], None] +ShowDocumentCallbackType = Callable[[ShowDocumentResult], None] diff --git a/setup.cfg b/setup.cfg index 0da96ff3..e5ce00bf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,7 +32,7 @@ python_requires = >=3.7,<4 packages = find: zip_safe = False install_requires = - pydantic>=1.9.1,<1.10 + lsprotocol typeguard>=2.10.0,<3 include_package_data = True tests_require = @@ -70,7 +70,3 @@ max-line-length = 99 [mypy] ignore_missing_imports = True -plugins = pydantic.mypy - -[pydantic-mypy] -init_forbid_extra = True From dd404c414884e91b5e692aa6750d16c95130cd39 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 14 Aug 2022 16:15:36 +0100 Subject: [PATCH 3/9] Fix `Options` type checking The machine readable version of the LSP spec (and therefore `lsprotocol`) provides a mapping from an LSP method's name to its `RegistrationOptions` type, which is an extension of the method's `Options` type used when computing a server's capabilities. This means the `RegistrationOptions` type includes additional fields that are not valid within the `ServerCapabilities` response. This commit introduces a new `get_method_options_type` function that returns the correct `Options` type for a given method, automatically deriving the type name from the result of the existing `get_method_registration_options_type` function when appropriate. --- pygls/feature_manager.py | 4 +-- pygls/lsp/__init__.py | 65 +++++++++++++++++++++++++++++++++-- tests/test_feature_manager.py | 2 +- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/pygls/feature_manager.py b/pygls/feature_manager.py index fb249523..dc02ae40 100644 --- a/pygls/feature_manager.py +++ b/pygls/feature_manager.py @@ -25,7 +25,7 @@ ATTR_REGISTERED_NAME, ATTR_REGISTERED_TYPE, PARAM_LS) from pygls.exceptions import (CommandAlreadyRegisteredError, FeatureAlreadyRegisteredError, ThreadDecoratorError, ValidationError) -from pygls.lsp import get_method_registration_options_type, is_instance +from pygls.lsp import get_method_options_type, is_instance logger = logging.getLogger(__name__) @@ -169,7 +169,7 @@ def decorator(f): self._features[feature_name] = wrapped if options: - options_type = get_method_registration_options_type(feature_name) + options_type = get_method_options_type(feature_name) if options_type and not is_instance(options, options_type): raise TypeError( (f'Options of method "{feature_name}"' diff --git a/pygls/lsp/__init__.py b/pygls/lsp/__init__.py index c7d8dbf3..5a810c7b 100644 --- a/pygls/lsp/__init__.py +++ b/pygls/lsp/__init__.py @@ -14,14 +14,28 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -from typing import Any, Union +from typing import Any, Optional, Union import attrs -from lsprotocol.types import METHOD_TO_TYPES +from lsprotocol.types import ( + ALL_TYPES_MAP, + METHOD_TO_TYPES, + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA, + TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE, + SemanticTokensLegend, + SemanticTokensRegistrationOptions +) from typeguard import check_type from pygls.exceptions import MethodTypeNotRegisteredError +METHOD_TO_OPTIONS = { + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], + TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], +} + @attrs.define class JsonRPCNotification: """A class that represents json rpc notification message.""" @@ -49,13 +63,58 @@ class JsonRPCResponseMessage: result: Union[Any, None] = attrs.field(default=None) -def get_method_registration_options_type(method_name, lsp_methods_map=METHOD_TO_TYPES): +def get_method_registration_options_type( + method_name, lsp_methods_map=METHOD_TO_TYPES +) -> Optional[Any]: + """The type corresponding with a method's options when dynamically registering + capability for it.""" + try: return lsp_methods_map[method_name][3] except KeyError: raise MethodTypeNotRegisteredError(method_name) +def get_method_options_type( + method_name, lsp_options_map=METHOD_TO_OPTIONS, lsp_methods_map=METHOD_TO_TYPES +) -> Optional[Any]: + """Return the type corresponding with a method's ``ServerCapabilities`` fields. + + In the majority of cases this simply means returning the ``Options`` + type, which we can easily derive from the method's + ``RegistrationOptions`` type. + + However, where the options are more involved (such as semantic tokens) and + ``pygls`` does some extra work to help derive the options for the user the type + has to be provided via the ``lsp_options_map`` + + Arguments: + method_name: + The lsp method name to retrieve the options for + + lsp_options_map: + The map used to override the default options type finding behavior + + lsp_methods_map: + The standard map used to look up the various method types. + """ + + options_type = lsp_options_map.get(method_name, None) + if options_type is not None: + return options_type + + registration_type = get_method_registration_options_type(method_name, lsp_methods_map) + if registration_type is None: + return None + + type_name = registration_type.__name__.replace('Registration', '') + options_type = ALL_TYPES_MAP.get(type_name, None) + + if options_type is None: + raise MethodTypeNotRegisteredError(method_name) + + return options_type + def get_method_params_type(method_name, lsp_methods_map=METHOD_TO_TYPES): try: return lsp_methods_map[method_name][2] diff --git a/tests/test_feature_manager.py b/tests/test_feature_manager.py index 682ef4f7..764b3e86 100644 --- a/tests/test_feature_manager.py +++ b/tests/test_feature_manager.py @@ -96,7 +96,7 @@ class Options: TypeError, match=( f'Options of method "{methods.COMPLETION}" should be instance of type ' - "" + "" ), # noqa ): From 6f6b9a08acf675d41cd00aa0027fcff18fd97ab4 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 14 Aug 2022 16:26:19 +0100 Subject: [PATCH 4/9] Use lsprotocol's converter for (de)serialization This simplifies much of the (de)serialization code by relying on the converter provided by `lsprotocol`. We use the `METHOD_TO_TYPES` mapping to determine which type definition to use for any given message. If a method is not known (as in the case of custom lsp commands) we fall back to pygls's existing generic RPC message classes. The following changes to the base `JsonRPCProtocol` class have also been made - server and client futures have been unified into a single `_request_futures` dict. - upon sending a request, the corresponding result type is looked up and stored in an internal `_result_types` dict. - (de)serialization code has been moved to a method on the `JsonRPCProtocol` class itself so that it has access to the required internal state. - subclasses (such as the `LanguageServerProtocol` class) are now required to implement the `get_message_type` and `get_result_type` methods to provide the type definitions corresponding with the given RPC method name. --- pygls/exceptions.py | 9 +- pygls/lsp/__init__.py | 26 ---- pygls/protocol.py | 291 +++++++++++++++++++++++------------------- pygls/server.py | 4 +- 4 files changed, 169 insertions(+), 161 deletions(-) diff --git a/pygls/exceptions.py b/pygls/exceptions.py index 00611d94..d1be92f5 100644 --- a/pygls/exceptions.py +++ b/pygls/exceptions.py @@ -40,11 +40,12 @@ def __hash__(self): return hash((self.code, self.message)) @staticmethod - def from_dict(error): + def from_error(error): for exc_class in _EXCEPTIONS: - if exc_class.supports_code(error['code']): - return exc_class(**error) - return JsonRpcException(**error) + if exc_class.supports_code(error.code): + return exc_class(code=error.code, message=error.message, data=error.data) + + return JsonRpcException(code=error.code, message=error.message, data=error.data) @classmethod def supports_code(cls, code): diff --git a/pygls/lsp/__init__.py b/pygls/lsp/__init__.py index 5a810c7b..0b92ec3b 100644 --- a/pygls/lsp/__init__.py +++ b/pygls/lsp/__init__.py @@ -36,32 +36,6 @@ TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], } -@attrs.define -class JsonRPCNotification: - """A class that represents json rpc notification message.""" - - jsonrpc: str - method: str - params: Any - -@attrs.define -class JsonRPCRequestMessage: - """A class that represents json rpc request message.""" - - jsonrpc: str - id: Union[int, str] - method: str - params: Any - - -@attrs.define -class JsonRPCResponseMessage: - """A class that represents json rpc response message.""" - - jsonrpc: str - id: Union[int, str] - result: Union[Any, None] = attrs.field(default=None) - def get_method_registration_options_type( method_name, lsp_methods_map=METHOD_TO_TYPES diff --git a/pygls/protocol.py b/pygls/protocol.py index 38d49b0b..d1756d85 100644 --- a/pygls/protocol.py +++ b/pygls/protocol.py @@ -25,22 +25,23 @@ import uuid from collections import namedtuple from concurrent.futures import Future -from functools import partial +from functools import lru_cache, partial from itertools import zip_longest -from typing import Callable, List, Optional +from typing import Any, Dict, Callable, List, Optional, Type, Union + +import attrs +from cattrs.errors import ClassValidationError +from lsprotocol import converters from pygls.capabilities import ServerCapabilitiesBuilder from pygls.constants import ATTR_FEATURE_TYPE from pygls.exceptions import (JsonRpcException, JsonRpcInternalError, JsonRpcInvalidParams, - JsonRpcMethodNotFound, JsonRpcRequestCancelled, - MethodTypeNotRegisteredError) -from pygls.feature_manager import (FeatureManager, assign_help_attrs, get_help_attrs, - is_thread_function) -from pygls.lsp import (JsonRPCNotification, JsonRPCRequestMessage, JsonRPCResponseMessage, - get_method_params_type, get_method_return_type, is_instance) -from pygls.lsp.methods import (CANCEL_REQUEST, CLIENT_REGISTER_CAPABILITY, + JsonRpcMethodNotFound, JsonRpcRequestCancelled) +from pygls.feature_manager import (FeatureManager, assign_help_attrs, is_thread_function) +from pygls.lsp import (ConfigCallbackType, ShowDocumentCallbackType) +from lsprotocol.types import (CANCEL_REQUEST, CLIENT_REGISTER_CAPABILITY, CLIENT_UNREGISTER_CAPABILITY, EXIT, INITIALIZE, INITIALIZED, - LOG_TRACE_NOTIFICATION, SET_TRACE_NOTIFICATION, SHUTDOWN, + METHOD_TO_TYPES, LOG_TRACE, SET_TRACE, SHUTDOWN, TEXT_DOCUMENT_DID_CHANGE, TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, WINDOW_LOG_MESSAGE, WINDOW_SHOW_DOCUMENT, WINDOW_SHOW_MESSAGE, @@ -62,7 +63,7 @@ from pygls.workspace import Workspace logger = logging.getLogger(__name__) - +converter = converters.get_converter() def call_user_feature(base_func, method_name): """Wraps generic LSP features and calls user registered feature @@ -86,8 +87,15 @@ def decorator(self, *args, **kwargs): return decorator -def dict_to_object(**d): +def dict_to_object(d: Any): """Create nested objects (namedtuple) from dict.""" + + if d is None: + return None + + if not isinstance(d, dict): + return d + type_name = d.pop('type_name', 'Object') return json.loads( json.dumps(d), @@ -95,73 +103,48 @@ def dict_to_object(**d): ) -def default_serializer(o): - """JSON serializer for complex objects that do not extend pydantic BaseModel class.""" - if isinstance(o, enum.Enum): - return o.value - return o.__dict__ - - -def deserialize_command(params): - """Function used to deserialize command arguments to a specific class - or a namedtuple.""" - # TODO: Register/Look up custom command arguments' types - # Currently command parameters are type of 'any', but eventually we would - # want to register an argument type of our custom command and to - # deserialize it properly. - temp_obj = dict_to_object(**params, type_name='CommandParams') - - params['arguments'] = getattr(temp_obj, 'arguments', None) - return params - +@attrs.define +class JsonRPCNotification: + """A class that represents a generic json rpc notification message. + Used as a fallback for unknown types. + """ -def deserialize_params(data, get_params_type): - """Function used to deserialize params to a specific class.""" - try: - method = data['method'] - params = data['params'] + method: str + jsonrpc: str + params: Any = attrs.field(converter=dict_to_object) - if not isinstance(params, dict): - return data +@attrs.define +class JsonRPCRequestMessage: + """A class that represents a generic json rpc request message. + Used as a fallback for unknown types. + """ - try: - params_type = get_params_type(method) - if params_type is None: - params_type = dict_to_object - elif params_type.__name__ == ExecuteCommandParams.__name__: - params = deserialize_command(params) + id: Union[int, str] + method: str + jsonrpc: str + params: Any = attrs.field(converter=dict_to_object) - except MethodTypeNotRegisteredError: - params_type = dict_to_object - try: - data['params'] = params_type(**params) - except TypeError: - raise ValueError( - f'Could not instantiate "{params_type.__name__}" from params: {params}') - except KeyError: - pass +@attrs.define +class JsonRPCResponseMessage: + """A class that represents a generic json rpc response message. + Used as a fallback for unknown types. + """ - return data + id: Union[int, str] + jsonrpc: str + result: Any = attrs.field(converter=dict_to_object) +def default_serializer(o): + """JSON serializer for complex objects that do not extend pydantic BaseModel class.""" -def deserialize_message(data, get_params_type=get_method_params_type): - """Function used to deserialize data received from client.""" - if 'jsonrpc' in data: - try: - deserialize_params(data, get_params_type) - except ValueError: - raise JsonRpcInvalidParams() + if hasattr(o, '__attrs_attrs__'): + return converter.unstructure(o) - if 'id' in data: - if 'method' in data: - return JsonRPCRequestMessage(**data) - else: - return JsonRPCResponseMessage(**data) - else: - return JsonRPCNotification(**data) + if isinstance(o, enum.Enum): + return o.value - return data + return o.__dict__ class JsonRPCProtocol(asyncio.Protocol): @@ -189,8 +172,9 @@ def __init__(self, server): self._server = server self._shutdown = False - self._client_request_futures = {} - self._server_request_futures = {} + # Book keeping for in-flight requests + self._request_futures = {} + self._result_types = {} self.fm = FeatureManager(server) self.transport = None @@ -201,16 +185,6 @@ def __init__(self, server): def __call__(self): return self - def _check_ret_type_and_send_response(self, method_name, method_type, msg_id, result): - """Check if registered feature returns appropriate result type.""" - if method_type == ATTR_FEATURE_TYPE: - return_type = get_method_return_type(method_name) - if not is_instance(result, return_type): - error = JsonRpcInternalError().to_dict() - self._send_response(msg_id, error=error) - - self._send_response(msg_id, result=result) - def _execute_notification(self, handler, *params): """Executes notification message handler.""" if asyncio.iscoroutinefunction(handler): @@ -238,39 +212,34 @@ def _execute_notification_callback(self, future): def _execute_request(self, msg_id, handler, params): """Executes request message handler.""" - method_name, method_type = get_help_attrs(handler) if asyncio.iscoroutinefunction(handler): future = asyncio.ensure_future(handler(params)) - self._client_request_futures[msg_id] = future - future.add_done_callback(partial(self._execute_request_callback, - method_name, method_type, msg_id)) + self._request_futures[msg_id] = future + future.add_done_callback(partial(self._execute_request_callback, msg_id)) else: # Can't be canceled if is_thread_function(handler): self._server.thread_pool.apply_async( handler, (params, ), callback=partial( - self._check_ret_type_and_send_response, - method_name, method_type, msg_id, + self._send_response, msg_id, ), error_callback=partial(self._execute_request_err_callback, msg_id)) else: - self._check_ret_type_and_send_response( - method_name, method_type, msg_id, handler(params)) + self._send_response(msg_id, handler(params)) - def _execute_request_callback(self, method_name, method_type, msg_id, future): + def _execute_request_callback(self, msg_id, future): """Success callback used for coroutine request message.""" try: if not future.cancelled(): - self._check_ret_type_and_send_response( - method_name, method_type, msg_id, result=future.result()) + self._send_response(msg_id, result=future.result()) else: self._send_response( msg_id, error=JsonRpcRequestCancelled(f'Request with id "{msg_id}" is canceled') ) - self._client_request_futures.pop(msg_id, None) + self._request_futures.pop(msg_id, None) except Exception: error = JsonRpcInternalError.of(sys.exc_info()).to_dict() logger.exception('Exception occurred for message "%s": %s', msg_id, error) @@ -295,7 +264,7 @@ def _get_handler(self, feature_name): def _handle_cancel_notification(self, msg_id): """Handles a cancel notification from the client.""" - future = self._client_request_futures.pop(msg_id, None) + future = self._request_futures.pop(msg_id, None) if not future: logger.warning('Cancel notification for unknown message id "%s"', msg_id) @@ -340,7 +309,7 @@ def _handle_request(self, msg_id, method_name, params): def _handle_response(self, msg_id, result=None, error=None): """Handles a response from the client.""" - future = self._server_request_futures.pop(msg_id, None) + future = self._request_futures.pop(msg_id, None) if not future: logger.warning('Received response to unknown message id "%s"', msg_id) @@ -348,11 +317,47 @@ def _handle_response(self, msg_id, result=None, error=None): if error is not None: logger.debug('Received error response to message "%s": %s', msg_id, error) - future.set_exception(JsonRpcException.from_dict(error)) + future.set_exception(JsonRpcException.from_error(error)) else: logger.debug('Received result for message "%s": %s', msg_id, result) future.set_result(result) + def _deserialize_message(self, data): + """Function used to deserialize data recevied from the client.""" + + if 'jsonrpc' not in data: + return data + + try: + if 'id' in data: + if 'error' in data: + return converter.structure(data, ResponseErrorMessage) + elif 'method' in data: + request_type = ( + self.get_message_type(data['method']) or JsonRPCRequestMessage + ) + return converter.structure(data, request_type) + else: + response_type = ( + self._result_types.pop(data['id']) or JsonRPCResponseMessage + ) + return converter.structure(data, response_type) + + else: + method = data.get('method', '') + notification_type = self.get_message_type(method) or JsonRPCNotification + return converter.structure(data, notification_type) + + except ClassValidationError as exc: + logger.error("Unable to deserialize message\n%s", traceback.format_exc()) + raise JsonRpcInvalidParams() from exc + + except Exception as exc: + logger.error("Unable to deserialize message\n%s", traceback.format_exc()) + raise JsonRpcInternalError() from exc + + return data + def _procedure_handler(self, message): """Delegates message to handlers depending on message type.""" if message.jsonrpc != JsonRPCProtocol.VERSION: @@ -363,15 +368,20 @@ def _procedure_handler(self, message): logger.warning('Server shutting down. No more requests!') return - if isinstance(message, JsonRPCNotification): - logger.debug('Notification message received.') - self._handle_notification(message.method, message.params) - elif isinstance(message, JsonRPCResponseMessage): - logger.debug('Response message received.') - self._handle_response(message.id, message.result, message.error) - elif isinstance(message, JsonRPCRequestMessage): - logger.debug('Request message received.') - self._handle_request(message.id, message.method, message.params) + if hasattr(message, 'method'): + if hasattr(message, 'id'): + logger.debug('Request message received.') + self._handle_request(message.id, message.method, message.params) + else: + logger.debug('Notification message received.') + self._handle_notification(message.method, message.params) + else: + if hasattr(message, 'error'): + logger.debug('Error message received.') + self._handle_response(message.id, None, message.error) + else: + logger.debug('Response message received.') + self._handle_response(message.id, message.result) def _send_data(self, data): """Sends data to the client.""" @@ -379,7 +389,7 @@ def _send_data(self, data): return try: - body = data.json(by_alias=True, exclude_unset=True, encoder=default_serializer) + body = json.dumps(data, default=default_serializer) logger.info('Sending data: %s', body) body = body.encode(self.CHARSET) @@ -403,15 +413,15 @@ def _send_response(self, msg_id, result=None, error=None): result(any): Result returned by handler error(any): Error returned by handler """ - response = JsonRPCResponseMessage(id=msg_id, - jsonrpc=JsonRPCProtocol.VERSION, - result=result, - error=error) - if error is None: - del response.error + if error is not None: + response = ResponseErrorMessage(id=msg_id, error=error) + else: - del response.result + response_type = self._result_types.pop(msg_id, JsonRPCResponseMessage) + response = response_type( + id=msg_id, result=result, jsonrpc=JsonRPCProtocol.VERSION + ) self._send_data(response) @@ -454,19 +464,29 @@ def data_received(self, data: bytes): # Parse the body self._procedure_handler( json.loads(body.decode(self.CHARSET), - object_hook=deserialize_message)) + object_hook=self._deserialize_message)) + + def get_message_type(self, method: str) -> Optional[Type]: + """Return the type definition of the message associated with the given method.""" + return None + + def get_result_type(self, method: str) -> Optional[Type]: + """Return the type definition of the result associated with the given method.""" + return None def notify(self, method: str, params=None): """Sends a JSON RPC notification to the client.""" - logger.debug('Sending notification: "%s" %s', method, params) - request = JsonRPCNotification( - jsonrpc=JsonRPCProtocol.VERSION, + logger.debug("Sending notification: '%s' %s", method, params) + + notification_type = self.get_message_type(method) or JsonRPCNotification + notification = notification_type( method=method, - params=params + params=params, + jsonrpc=JsonRPCProtocol.VERSION ) - self._send_data(request) + self._send_data(notification) def send_request(self, method, params=None, callback=None): """Sends a JSON RPC request to the client. @@ -478,14 +498,16 @@ def send_request(self, method, params=None, callback=None): Returns: Future that will be resolved once a response has been received """ + msg_id = str(uuid.uuid4()) + request_type = self.get_message_type(method) or JsonRPCRequestMessage logger.debug('Sending request with id "%s": %s %s', msg_id, method, params) - request = JsonRPCRequestMessage( + request = request_type( id=msg_id, - jsonrpc=JsonRPCProtocol.VERSION, method=method, - params=params + params=params, + jsonrpc=JsonRPCProtocol.VERSION, ) future = Future() @@ -497,7 +519,9 @@ def wrapper(future: Future): callback(result) future.add_done_callback(wrapper) - self._server_request_futures[msg_id] = future + self._request_futures[msg_id] = future + self._result_types[msg_id] = self.get_result_type(method) + self._send_data(request) return future @@ -573,7 +597,16 @@ 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: + @lru_cache() + def get_message_type(self, method: str) -> Optional[Type]: + """Return LSP type definitions, as provided by `lsprotocol`""" + return METHOD_TO_TYPES.get(method, (None,))[0] + + @lru_cache() + def get_result_type(self, method: str) -> Optional[Type]: + return METHOD_TO_TYPES.get(method, (None, None))[1] + + 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)) @@ -603,7 +636,10 @@ def lsp_initialize(self, params: InitializeParams) -> InitializeResult: list(self.fm.commands.keys()), self._server.sync_kind, ).build() - logger.debug('Server capabilities: %s', self.server_capabilities.dict()) + logger.debug( + 'Server capabilities: %s', + json.dumps(self.server_capabilities, default=default_serializer) + ) root_path = params.root_path root_uri = params.root_uri or from_fs_path(root_path) @@ -624,10 +660,7 @@ def lsp_initialized(self, *args) -> None: @lsp_method(SHUTDOWN) def lsp_shutdown(self, *args) -> None: """Request from client which asks server to shutdown.""" - for future in self._client_request_futures.values(): - future.cancel() - - for future in self._server_request_futures.values(): + for future in self._request_futures.values(): future.cancel() self._shutdown = True diff --git a/pygls/server.py b/pygls/server.py index da9c4892..127f7684 100644 --- a/pygls/server.py +++ b/pygls/server.py @@ -30,7 +30,7 @@ WorkspaceEdit) from pygls.lsp.types.window import ShowDocumentCallbackType, ShowDocumentParams from pygls.progress import Progress -from pygls.protocol import LanguageServerProtocol, deserialize_message +from pygls.protocol import LanguageServerProtocol from pygls.workspace import Workspace if not IS_PYODIDE: @@ -278,7 +278,7 @@ async def connection_made(websocket, _): self.lsp.transport = WebSocketTransportAdapter(websocket, self.loop) async for message in websocket: self.lsp._procedure_handler( - json.loads(message, object_hook=deserialize_message) + json.loads(message, object_hook=self.lsp._deserialize_message) ) start_server = websockets.serve(connection_made, host, port) From 8f1d7190c2b1223d369edebccd4b3466725c7937 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 14 Aug 2022 16:40:34 +0100 Subject: [PATCH 5/9] Make it possible to disable the testsuite timeout The timeouts can get in the way when trying to debug the code under test. This commit makes it possible to disable the timeout by running the testsuite with the `DISABLE_TIMEOUT` environment variable set e.g. $ DISABLE_TIMEOUT=1 pytest -x tests/ --- tests/_init_server_stall_fix_hack.py | 5 +++++ tests/ls_setup.py | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/_init_server_stall_fix_hack.py b/tests/_init_server_stall_fix_hack.py index 89045a51..c7fa4513 100644 --- a/tests/_init_server_stall_fix_hack.py +++ b/tests/_init_server_stall_fix_hack.py @@ -4,12 +4,17 @@ fix to actually guarantee it doesn't generate false negatives in the test suite. """ +import os import concurrent RETRIES = 3 def retry_stalled_init_fix_hack(): + + if 'DISABLE_TIMEOUT' in os.environ: + return lambda f: f + def decorator(func): def newfn(*args, **kwargs): attempt = 0 diff --git a/tests/ls_setup.py b/tests/ls_setup.py index e5d9bbfe..5df29b55 100644 --- a/tests/ls_setup.py +++ b/tests/ls_setup.py @@ -164,6 +164,8 @@ def stop(self): @retry_stalled_init_fix_hack() def initialize(self): + + timeout = None if 'DISABLE_TIMEOUT' in os.environ else 1 response = self.client.lsp.send_request( INITIALIZE, InitializeParams( @@ -171,7 +173,7 @@ def initialize(self): root_uri="file://", capabilities=ClientCapabilities() ), - ).result(timeout=1) + ).result(timeout=timeout) assert "capabilities" in response def __iter__(self): From d0e7ab50b2032cbbf469548ad323d49e7cbab6c9 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 14 Aug 2022 16:47:31 +0100 Subject: [PATCH 6/9] Align to breaking changes Nothing too interesting in this one, just updating imports, class names etc to align `pygls` to the definitions in `lsprotocol` --- examples/fountain-extension/src/server.py | 6 +- examples/json-extension/server/server.py | 25 ++- .../server/tests/unit/test_features.py | 2 +- pygls/capabilities.py | 161 +++++++++------- pygls/lsp/__init__.py | 16 +- pygls/lsp/types.py | 24 --- pygls/progress.py | 18 +- pygls/protocol.py | 68 ++++--- pygls/server.py | 23 ++- pygls/workspace.py | 49 ++--- tests/ls_setup.py | 20 +- .../test_delta_missing_legend.py | 12 +- .../test_delta_missing_legend_none.py | 4 +- .../test_full_missing_legend.py | 4 +- tests/lsp/semantic_tokens/test_range.py | 6 +- .../test_range_missing_legends.py | 4 +- .../test_semantic_tokens_full.py | 6 +- tests/lsp/test_call_hierarchy.py | 75 ++++---- tests/lsp/test_code_action.py | 22 +-- tests/lsp/test_code_lens.py | 24 +-- tests/lsp/test_color_presentation.py | 50 ++--- tests/lsp/test_completion.py | 44 ++--- tests/lsp/test_declaration.py | 60 +++--- tests/lsp/test_definition.py | 60 +++--- tests/lsp/test_document_color.py | 24 +-- tests/lsp/test_document_highlight.py | 30 +-- tests/lsp/test_document_link.py | 24 +-- tests/lsp/test_document_symbol.py | 80 ++++---- tests/lsp/test_folding_range.py | 20 +- tests/lsp/test_formatting.py | 20 +- tests/lsp/test_hover.py | 56 +++--- tests/lsp/test_implementation.py | 60 +++--- tests/lsp/test_linked_editing_range.py | 22 +-- tests/lsp/test_moniker.py | 12 +- tests/lsp/test_on_type_formatting.py | 20 +- tests/lsp/test_prepare_rename.py | 37 ++-- tests/lsp/test_progress.py | 22 +-- tests/lsp/test_range_formatting.py | 20 +- tests/lsp/test_references.py | 20 +- tests/lsp/test_rename.py | 86 ++++----- tests/lsp/test_selection_range.py | 34 ++-- tests/lsp/test_signature_help.py | 14 +- tests/lsp/test_type_definition.py | 60 +++--- tests/test_document.py | 30 +-- tests/test_feature_manager.py | 35 ++-- tests/test_language_server.py | 16 +- tests/test_protocol.py | 174 ++++++++++-------- tests/test_types.py | 2 +- tests/test_workspace.py | 2 +- 49 files changed, 882 insertions(+), 821 deletions(-) delete mode 100644 pygls/lsp/types.py diff --git a/examples/fountain-extension/src/server.py b/examples/fountain-extension/src/server.py index e946ad6c..ba8fa3b3 100644 --- a/examples/fountain-extension/src/server.py +++ b/examples/fountain-extension/src/server.py @@ -1,7 +1,7 @@ import re from pygls.server import LanguageServer -from pygls.lsp.methods import COMPLETION -from pygls.lsp.types import (CompletionItem, CompletionParams, CompletionList, CompletionOptions) +from lsprotocol.types import TEXT_DOCUMENT_COMPLETION +from lsprotocol.types import (CompletionItem, CompletionParams, CompletionList, CompletionOptions) # The following imports are required for the glue code in 'server.ts' import json @@ -12,7 +12,7 @@ CHARACTER = re.compile(r"^[A-Z][A-Z ]+$", re.MULTILINE) -@server.feature(COMPLETION, CompletionOptions(trigger_characters=['.'])) +@server.feature(TEXT_DOCUMENT_COMPLETION, CompletionOptions(trigger_characters=['.'])) def on_completion(ls: LanguageServer, params: CompletionParams) -> CompletionList: """Completion suggestions for character names.""" diff --git a/examples/json-extension/server/server.py b/examples/json-extension/server/server.py index 3e63a363..27367285 100644 --- a/examples/json-extension/server/server.py +++ b/examples/json-extension/server/server.py @@ -22,10 +22,10 @@ from json import JSONDecodeError from typing import Optional -from pygls.lsp.methods import (COMPLETION, TEXT_DOCUMENT_DID_CHANGE, - TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN, +from lsprotocol.types import (TEXT_DOCUMENT_COMPLETION, TEXT_DOCUMENT_DID_CHANGE, + TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL) -from pygls.lsp.types import (CompletionItem, CompletionList, CompletionOptions, +from lsprotocol.types import (CompletionItem, CompletionList, CompletionOptions, CompletionParams, ConfigurationItem, ConfigurationParams, Diagnostic, DidChangeTextDocumentParams, @@ -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 @@ -98,7 +97,7 @@ def _validate_json(source): return diagnostics -@json_server.feature(COMPLETION, CompletionOptions(trigger_characters=[','])) +@json_server.feature(TEXT_DOCUMENT_COMPLETION, CompletionOptions(trigger_characters=[','])) def completions(params: Optional[CompletionParams] = None) -> CompletionList: """Returns completion items.""" return CompletionList( @@ -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) @@ -184,7 +183,7 @@ def semantic_tokens(ls: JsonLanguageServer, params: SemanticTokensParams): (lineno - last_line), (start - last_start), (end - start), - 0, + 0, 0 ] @@ -220,7 +219,7 @@ async def register_completions(ls: JsonLanguageServer, *args): params = RegistrationParams(registrations=[ Registration( id=str(uuid.uuid4()), - method=COMPLETION, + method=TEXT_DOCUMENT_COMPLETION, register_options={"triggerCharacters": "[':']"}) ]) response = await ls.register_capability_async(params) @@ -292,7 +291,7 @@ def show_configuration_thread(ls: JsonLanguageServer, *args): async def unregister_completions(ls: JsonLanguageServer, *args): """Unregister completions method on the client.""" params = UnregistrationParams(unregisterations=[ - Unregistration(id=str(uuid.uuid4()), method=COMPLETION) + Unregistration(id=str(uuid.uuid4()), method=TEXT_DOCUMENT_COMPLETION) ]) response = await ls.unregister_capability_async(params) if response is None: diff --git a/examples/json-extension/server/tests/unit/test_features.py b/examples/json-extension/server/tests/unit/test_features.py index 6453c513..ee0182bf 100644 --- a/examples/json-extension/server/tests/unit/test_features.py +++ b/examples/json-extension/server/tests/unit/test_features.py @@ -19,7 +19,7 @@ import pytest from mock import Mock -from pygls.lsp.types import (DidCloseTextDocumentParams, +from lsprotocol.types import (DidCloseTextDocumentParams, DidOpenTextDocumentParams, TextDocumentIdentifier, TextDocumentItem) from pygls.workspace import Document, Workspace diff --git a/pygls/capabilities.py b/pygls/capabilities.py index 8540ee30..030e1ac7 100644 --- a/pygls/capabilities.py +++ b/pygls/capabilities.py @@ -14,30 +14,56 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -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, - ON_TYPE_FORMATTING, RANGE_FORMATTING, REFERENCES, RENAME, - SELECTION_RANGE, SIGNATURE_HELP, - TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE, TEXT_DOCUMENT_DID_CLOSE, - TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_DID_SAVE, - TEXT_DOCUMENT_LINKED_EDITING_RANGE, TEXT_DOCUMENT_MONIKER, - TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, - TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA, - TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE, TEXT_DOCUMENT_WILL_SAVE, - TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL, TYPE_DEFINITION, - WORKSPACE_DID_CREATE_FILES, WORKSPACE_DID_DELETE_FILES, - 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, - ServerCapabilities, SignatureHelpOptions, - TextDocumentSyncOptionsServerCapabilities, TypeDefinitionOptions, - WorkspaceFileOperationsServerCapabilities, - WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities) +from functools import reduce +from typing import Any + +from lsprotocol.types import ( + TEXT_DOCUMENT_CODE_ACTION, TEXT_DOCUMENT_CODE_LENS, + TEXT_DOCUMENT_COMPLETION, TEXT_DOCUMENT_DECLARATION, + TEXT_DOCUMENT_DEFINITION, TEXT_DOCUMENT_DOCUMENT_COLOR, + TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT, TEXT_DOCUMENT_DOCUMENT_LINK, + TEXT_DOCUMENT_DOCUMENT_SYMBOL, TEXT_DOCUMENT_FOLDING_RANGE, + TEXT_DOCUMENT_FORMATTING, TEXT_DOCUMENT_HOVER, + TEXT_DOCUMENT_IMPLEMENTATION, TEXT_DOCUMENT_ON_TYPE_FORMATTING, + TEXT_DOCUMENT_RANGE_FORMATTING, TEXT_DOCUMENT_REFERENCES, + TEXT_DOCUMENT_RENAME, TEXT_DOCUMENT_SELECTION_RANGE, + TEXT_DOCUMENT_SIGNATURE_HELP, TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, + TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN, + TEXT_DOCUMENT_DID_SAVE, TEXT_DOCUMENT_LINKED_EDITING_RANGE, + TEXT_DOCUMENT_MONIKER, TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA, TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE, + TEXT_DOCUMENT_WILL_SAVE, TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL, + TEXT_DOCUMENT_TYPE_DEFINITION, WORKSPACE_DID_CREATE_FILES, + WORKSPACE_DID_DELETE_FILES, WORKSPACE_DID_RENAME_FILES, + WORKSPACE_SYMBOL, WORKSPACE_WILL_CREATE_FILES, + WORKSPACE_WILL_DELETE_FILES, WORKSPACE_WILL_RENAME_FILES +) +from lsprotocol.types import ( + ClientCapabilities, CodeLensOptions, CompletionOptions, + DocumentLinkOptions, ExecuteCommandOptions, ImplementationOptions, + SaveOptions, SemanticTokensOptions, SemanticTokensRegistrationOptions, + SemanticTokensOptionsFullType1, ServerCapabilities, + ServerCapabilitiesWorkspaceType, SignatureHelpOptions, + 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: @@ -71,13 +97,17 @@ def _with_text_doc_sync(self): or TEXT_DOCUMENT_DID_CLOSE in self.features ) will_save = ( - self.client_capabilities.get_capability( - 'text_document.synchronization.will_save') + 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( - 'text_document.synchronization.will_save_wait_until') + get_capability( + self.client_capabilities, + 'text_document.synchronization.will_save_wait_until' + ) and TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL in self.features ) if TEXT_DOCUMENT_DID_SAVE in self.features: @@ -89,7 +119,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, @@ -100,115 +130,121 @@ def _with_text_doc_sync(self): return self def _with_completion(self): - value = self._provider_options(COMPLETION, default=CompletionOptions()) + value = self._provider_options(TEXT_DOCUMENT_COMPLETION, default=CompletionOptions()) if value is not None: self.server_cap.completion_provider = value return self def _with_hover(self): - value = self._provider_options(HOVER) + value = self._provider_options(TEXT_DOCUMENT_HOVER) if value is not None: self.server_cap.hover_provider = value return self def _with_signature_help(self): - value = self._provider_options(SIGNATURE_HELP, default=SignatureHelpOptions()) + value = self._provider_options( + TEXT_DOCUMENT_SIGNATURE_HELP, default=SignatureHelpOptions() + ) if value is not None: self.server_cap.signature_help_provider = value return self def _with_declaration(self): - value = self._provider_options(DECLARATION) + value = self._provider_options(TEXT_DOCUMENT_DECLARATION) if value is not None: self.server_cap.declaration_provider = value return self def _with_definition(self): - value = self._provider_options(DEFINITION) + value = self._provider_options(TEXT_DOCUMENT_DEFINITION) if value is not None: self.server_cap.definition_provider = value return self def _with_type_definition(self): - value = self._provider_options(TYPE_DEFINITION, default=TypeDefinitionOptions()) + value = self._provider_options( + TEXT_DOCUMENT_TYPE_DEFINITION, default=TypeDefinitionOptions() + ) if value is not None: self.server_cap.type_definition_provider = value return self def _with_implementation(self): - value = self._provider_options(IMPLEMENTATION, default=ImplementationOptions()) + value = self._provider_options( + TEXT_DOCUMENT_IMPLEMENTATION, default=ImplementationOptions() + ) if value is not None: self.server_cap.implementation_provider = value return self def _with_references(self): - value = self._provider_options(REFERENCES) + value = self._provider_options(TEXT_DOCUMENT_REFERENCES) if value is not None: self.server_cap.references_provider = value return self def _with_document_highlight(self): - value = self._provider_options(DOCUMENT_HIGHLIGHT) + value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT) if value is not None: self.server_cap.document_highlight_provider = value return self def _with_document_symbol(self): - value = self._provider_options(DOCUMENT_SYMBOL) + value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_SYMBOL) if value is not None: self.server_cap.document_symbol_provider = value return self def _with_code_action(self): - value = self._provider_options(CODE_ACTION) + value = self._provider_options(TEXT_DOCUMENT_CODE_ACTION) if value is not None: self.server_cap.code_action_provider = value return self def _with_code_lens(self): - value = self._provider_options(CODE_LENS, default=CodeLensOptions()) + value = self._provider_options(TEXT_DOCUMENT_CODE_LENS, default=CodeLensOptions()) if value is not None: self.server_cap.code_lens_provider = value return self def _with_document_link(self): - value = self._provider_options(DOCUMENT_LINK, default=DocumentLinkOptions()) + value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_LINK, default=DocumentLinkOptions()) if value is not None: self.server_cap.document_link_provider = value return self def _with_color(self): - value = self._provider_options(DOCUMENT_COLOR) + value = self._provider_options(TEXT_DOCUMENT_DOCUMENT_COLOR) if value is not None: self.server_cap.color_provider = value return self def _with_document_formatting(self): - value = self._provider_options(FORMATTING) + value = self._provider_options(TEXT_DOCUMENT_FORMATTING) if value is not None: self.server_cap.document_formatting_provider = value return self def _with_document_range_formatting(self): - value = self._provider_options(RANGE_FORMATTING) + value = self._provider_options(TEXT_DOCUMENT_RANGE_FORMATTING) if value is not None: self.server_cap.document_range_formatting_provider = value return self def _with_document_on_type_formatting(self): - value = self._provider_options(ON_TYPE_FORMATTING) + value = self._provider_options(TEXT_DOCUMENT_ON_TYPE_FORMATTING) if value is not None: self.server_cap.document_on_type_formatting_provider = value return self def _with_rename(self): - value = self._provider_options(RENAME) + value = self._provider_options(TEXT_DOCUMENT_RENAME) if value is not None: self.server_cap.rename_provider = value return self def _with_folding_range(self): - value = self._provider_options(FOLDING_RANGE) + value = self._provider_options(TEXT_DOCUMENT_FOLDING_RANGE) if value is not None: self.server_cap.folding_range_provider = value return self @@ -219,13 +255,13 @@ def _with_execute_command(self): return self def _with_selection_range(self): - value = self._provider_options(SELECTION_RANGE) + value = self._provider_options(TEXT_DOCUMENT_SELECTION_RANGE) if value is not None: self.server_cap.selection_range_provider = value return self def _with_call_hierarchy(self): - value = self._provider_options(TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE) + value = self._provider_options(TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY) if value is not None: self.server_cap.call_hierarchy_provider = value return self @@ -250,11 +286,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 = SemanticTokensOptionsFullType1(delta=True) + else: + full_support = TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL in self.features options = SemanticTokensOptions( legend=value, @@ -287,10 +322,10 @@ 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 ) @@ -298,7 +333,7 @@ def _with_workspace_capabilities(self): 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 ) @@ -306,7 +341,7 @@ def _with_workspace_capabilities(self): 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 ) @@ -314,7 +349,7 @@ def _with_workspace_capabilities(self): 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 ) @@ -322,7 +357,7 @@ def _with_workspace_capabilities(self): 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 ) @@ -330,14 +365,14 @@ def _with_workspace_capabilities(self): 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( + self.server_cap.workspace = ServerCapabilitiesWorkspaceType( workspace_folders=WorkspaceFoldersServerCapabilities( supported=True, change_notifications=True, diff --git a/pygls/lsp/__init__.py b/pygls/lsp/__init__.py index 0b92ec3b..11ea0b12 100644 --- a/pygls/lsp/__init__.py +++ b/pygls/lsp/__init__.py @@ -14,9 +14,8 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -from typing import Any, Optional, Union +from typing import Any, Callable, List, Optional, Union -import attrs from lsprotocol.types import ( ALL_TYPES_MAP, METHOD_TO_TYPES, @@ -24,16 +23,20 @@ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA, TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE, SemanticTokensLegend, - SemanticTokensRegistrationOptions + SemanticTokensRegistrationOptions, + ShowDocumentResult ) from typeguard import check_type from pygls.exceptions import MethodTypeNotRegisteredError +ConfigCallbackType = Callable[[List[Any]], None] +ShowDocumentCallbackType = Callable[[ShowDocumentResult], None] + METHOD_TO_OPTIONS = { - TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], - TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], - TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], + TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], + TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE: Union[SemanticTokensLegend, SemanticTokensRegistrationOptions], } @@ -89,6 +92,7 @@ def get_method_options_type( return options_type + def get_method_params_type(method_name, lsp_methods_map=METHOD_TO_TYPES): try: return lsp_methods_map[method_name][2] diff --git a/pygls/lsp/types.py b/pygls/lsp/types.py deleted file mode 100644 index f36b6e37..00000000 --- a/pygls/lsp/types.py +++ /dev/null @@ -1,24 +0,0 @@ -############################################################################ -# Copyright(c) Open Law Library. All rights reserved. # -# See ThirdPartyNotices.txt in the project root for additional notices. # -# # -# Licensed under the Apache License, Version 2.0 (the "License") # -# you may not use this file except in compliance with the License. # -# You may obtain a copy of the License at # -# # -# http: // www.apache.org/licenses/LICENSE-2.0 # -# # -# Unless required by applicable law or agreed to in writing, software # -# distributed under the License is distributed on an "AS IS" BASIS, # -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -# See the License for the specific language governing permissions and # -# limitations under the License. # -############################################################################ -# flake8: noqa -from typing import Any, Callable, List - -from lsprotocol.types import * - - -ConfigCallbackType = Callable[[List[Any]], None] -ShowDocumentCallbackType = Callable[[ShowDocumentResult], None] diff --git a/pygls/progress.py b/pygls/progress.py index 3cbd5d15..34e55619 100644 --- a/pygls/progress.py +++ b/pygls/progress.py @@ -2,11 +2,13 @@ from concurrent.futures import Future from typing import Dict -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 lsprotocol.types import ( + PROGRESS, WINDOW_WORK_DONE_PROGRESS_CANCEL, + WINDOW_WORK_DONE_PROGRESS_CREATE, + ProgressParams, ProgressToken, WorkDoneProgressBegin, + WorkDoneProgressEnd, WorkDoneProgressReport, + WorkDoneProgressCancelParams, WorkDoneProgressCreateParams +) from pygls.protocol import LanguageServerProtocol @@ -70,7 +72,7 @@ def cancel_async(self, token: ProgressToken) -> asyncio.Future: def begin(self, token: ProgressToken, value: WorkDoneProgressBegin) -> None: return self._lsp.notify( - PROGRESS_NOTIFICATION, + PROGRESS, ProgressParams( token=token, value=value @@ -78,7 +80,7 @@ def begin(self, token: ProgressToken, value: WorkDoneProgressBegin) -> None: ) def report(self, token: ProgressToken, value: WorkDoneProgressReport) -> None: - self._lsp.notify(PROGRESS_NOTIFICATION, ProgressParams(token=token, value=value)) + self._lsp.notify(PROGRESS, ProgressParams(token=token, value=value)) def end(self, token: ProgressToken, value: WorkDoneProgressEnd) -> None: - self._lsp.notify(PROGRESS_NOTIFICATION, ProgressParams(token=token, value=value)) + self._lsp.notify(PROGRESS, ProgressParams(token=token, value=value)) diff --git a/pygls/protocol.py b/pygls/protocol.py index d1756d85..c6bd737b 100644 --- a/pygls/protocol.py +++ b/pygls/protocol.py @@ -27,7 +27,7 @@ from concurrent.futures import Future from functools import lru_cache, partial from itertools import zip_longest -from typing import Any, Dict, Callable, List, Optional, Type, Union +from typing import Any, Callable, List, Optional, Type, Union import attrs from cattrs.errors import ClassValidationError @@ -35,36 +35,42 @@ from pygls.capabilities import ServerCapabilitiesBuilder from pygls.constants import ATTR_FEATURE_TYPE -from pygls.exceptions import (JsonRpcException, JsonRpcInternalError, JsonRpcInvalidParams, - JsonRpcMethodNotFound, JsonRpcRequestCancelled) -from pygls.feature_manager import (FeatureManager, assign_help_attrs, is_thread_function) -from pygls.lsp import (ConfigCallbackType, ShowDocumentCallbackType) -from lsprotocol.types import (CANCEL_REQUEST, CLIENT_REGISTER_CAPABILITY, - CLIENT_UNREGISTER_CAPABILITY, EXIT, INITIALIZE, INITIALIZED, - METHOD_TO_TYPES, LOG_TRACE, SET_TRACE, SHUTDOWN, - TEXT_DOCUMENT_DID_CHANGE, TEXT_DOCUMENT_DID_CLOSE, - TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, - WINDOW_LOG_MESSAGE, WINDOW_SHOW_DOCUMENT, WINDOW_SHOW_MESSAGE, - 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, - DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams, - DidCloseTextDocumentParams, DidOpenTextDocumentParams, - ExecuteCommandParams, InitializeParams, InitializeResult, - LogMessageParams, MessageType, PublishDiagnosticsParams, - RegistrationParams, ShowMessageParams, UnregistrationParams, - 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.exceptions import ( + JsonRpcException, JsonRpcInternalError, JsonRpcInvalidParams, + JsonRpcMethodNotFound, JsonRpcRequestCancelled +) +from pygls.feature_manager import FeatureManager, assign_help_attrs, is_thread_function +from pygls.lsp import ConfigCallbackType, ShowDocumentCallbackType +from lsprotocol.types import ( + CANCEL_REQUEST, CLIENT_REGISTER_CAPABILITY, + CLIENT_UNREGISTER_CAPABILITY, EXIT, INITIALIZE, INITIALIZED, + METHOD_TO_TYPES, LOG_TRACE, SET_TRACE, SHUTDOWN, + TEXT_DOCUMENT_DID_CHANGE, TEXT_DOCUMENT_DID_CLOSE, + TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, + WINDOW_LOG_MESSAGE, WINDOW_SHOW_DOCUMENT, WINDOW_SHOW_MESSAGE, + WORKSPACE_APPLY_EDIT, WORKSPACE_CONFIGURATION, + WORKSPACE_DID_CHANGE_WORKSPACE_FOLDERS, WORKSPACE_EXECUTE_COMMAND, + WORKSPACE_SEMANTIC_TOKENS_REFRESH +) +from lsprotocol.types import ( + ApplyWorkspaceEditParams, + ConfigurationParams, Diagnostic, + DidChangeTextDocumentParams, DidChangeWorkspaceFoldersParams, + DidCloseTextDocumentParams, DidOpenTextDocumentParams, + ExecuteCommandParams, InitializeParams, InitializeResult, + LogMessageParams, LogTraceParams, MessageType, PublishDiagnosticsParams, + RegistrationParams, ResponseErrorMessage, SetTraceParams, + ShowDocumentParams, ShowMessageParams, + TraceValues, UnregistrationParams, WorkspaceApplyEditResponse, + WorkspaceEdit +) from pygls.uris import from_fs_path from pygls.workspace import Workspace logger = logging.getLogger(__name__) converter = converters.get_converter() + def call_user_feature(base_func, method_name): """Wraps generic LSP features and calls user registered feature immediately after it. @@ -113,6 +119,7 @@ class JsonRPCNotification: jsonrpc: str params: Any = attrs.field(converter=dict_to_object) + @attrs.define class JsonRPCRequestMessage: """A class that represents a generic json rpc request message. @@ -135,6 +142,7 @@ class JsonRPCResponseMessage: jsonrpc: str result: Any = attrs.field(converter=dict_to_object) + def default_serializer(o): """JSON serializer for complex objects that do not extend pydantic BaseModel class.""" @@ -648,7 +656,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) @@ -684,7 +692,7 @@ def lsp_text_document__did_open(self, params: DidOpenTextDocumentParams) -> None """Puts document to the workspace.""" self.workspace.put_document(params.text_document) - @lsp_method(SET_TRACE_NOTIFICATION) + @lsp_method(SET_TRACE) def lsp_set_trace(self, params: SetTraceParams) -> None: """Changes server trace value.""" self.trace = params.value @@ -736,14 +744,14 @@ 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) + self.notify(LOG_TRACE, params) def publish_diagnostics(self, doc_uri: str, diagnostics: List[Diagnostic]) -> None: """Sends diagnostic notification to the client.""" diff --git a/pygls/server.py b/pygls/server.py index 127f7684..d410d7a8 100644 --- a/pygls/server.py +++ b/pygls/server.py @@ -24,11 +24,14 @@ from typing import Any, Callable, List, Optional, TypeVar from pygls import IS_WIN, IS_PYODIDE -from pygls.lsp.types import (ApplyWorkspaceEditResponse, ClientCapabilities, ConfigCallbackType, - ConfigurationParams, Diagnostic, MessageType, RegistrationParams, - ServerCapabilities, TextDocumentSyncKind, UnregistrationParams, - WorkspaceEdit) -from pygls.lsp.types.window import ShowDocumentCallbackType, ShowDocumentParams +from pygls.lsp import ConfigCallbackType, ShowDocumentCallbackType +from lsprotocol.types import ( + ClientCapabilities, + ConfigurationParams, Diagnostic, MessageType, RegistrationParams, + ServerCapabilities, ShowDocumentParams, + TextDocumentSyncKind, UnregistrationParams, + WorkspaceApplyEditResponse, WorkspaceEdit +) from pygls.progress import Progress from pygls.protocol import LanguageServerProtocol from pygls.workspace import Workspace @@ -150,9 +153,9 @@ class Server: `ThreadPoolExecutor` sync_kind(TextDocumentSyncKind): Text document synchronization option - - NONE(0): no synchronization - - FULL(1): replace whole text - - INCREMENTAL(2): replace text within a given range + - None(0): no synchronization + - Full(1): replace whole text + - Incremental(2): replace text within a given range Attributes: _max_workers(int): Number of workers for thread pool executor @@ -166,7 +169,7 @@ class Server: """ def __init__(self, protocol_cls, loop=None, max_workers=2, - sync_kind=TextDocumentSyncKind.INCREMENTAL): + sync_kind=TextDocumentSyncKind.Incremental): if not issubclass(protocol_cls, asyncio.Protocol): raise TypeError('Protocol class should be subclass of asyncio.Protocol') @@ -330,7 +333,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) diff --git a/pygls/workspace.py b/pygls/workspace.py index 8e73625f..dda2a0b0 100644 --- a/pygls/workspace.py +++ b/pygls/workspace.py @@ -22,9 +22,11 @@ import re from typing import List, Optional, Pattern -from pygls.lsp.types import (NumType, Position, Range, TextDocumentContentChangeEvent, - TextDocumentItem, TextDocumentSyncKind, - VersionedTextDocumentIdentifier, WorkspaceFolder) +from lsprotocol.types import ( + Position, Range, TextDocumentContentChangeEvent, + TextDocumentItem, TextDocumentSyncKind, + VersionedTextDocumentIdentifier, WorkspaceFolder +) from pygls.uris import to_fs_path, uri_scheme # TODO: this is not the best e.g. we capture numbers @@ -164,10 +166,10 @@ 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 + sync_kind: TextDocumentSyncKind = TextDocumentSyncKind.Incremental ): self.uri = uri self.version = version @@ -178,21 +180,24 @@ def __init__( self._local = local self._source = source - self._is_sync_kind_full = sync_kind == TextDocumentSyncKind.FULL - self._is_sync_kind_incremental = sync_kind == TextDocumentSyncKind.INCREMENTAL - self._is_sync_kind_none = sync_kind == TextDocumentSyncKind.NONE + self._is_sync_kind_full = sync_kind == TextDocumentSyncKind.Full + self._is_sync_kind_incremental = sync_kind == TextDocumentSyncKind.Incremental + self._is_sync_kind_none = sync_kind == TextDocumentSyncKind.None_ def __str__(self): return str(self.uri) def _apply_incremental_change(self, change: TextDocumentContentChangeEvent) -> None: - """Apply an INCREMENTAL text change to the document""" + """Apply an ``Incremental`` text change to the document""" lines = self.lines 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): @@ -223,11 +228,11 @@ def _apply_incremental_change(self, change: TextDocumentContentChangeEvent) -> N self._source = new.getvalue() def _apply_full_change(self, change: TextDocumentContentChangeEvent) -> None: - """Apply a FULL text change to the document.""" + """Apply a ``Full`` text change to the document.""" self._source = change.text def _apply_none_change(self, change: TextDocumentContentChangeEvent) -> None: - """Apply a NONE text change to the document + """Apply a ``None`` text change to the document Currently does nothing, provided for consistency. """ @@ -236,14 +241,14 @@ def _apply_none_change(self, change: TextDocumentContentChangeEvent) -> None: def apply_change(self, change: TextDocumentContentChangeEvent) -> None: """Apply a text change to a document, considering TextDocumentSyncKind - Performs either INCREMENTAL, FULL, or NONE synchronization based on + Performs either ``Incremental``, ``Full``, or ``None`` synchronization based on both the Client request and server capabilities. - INCREMENTAL versus FULL synchronization: - Even if a server accepts INCREMENTAL SyncKinds, clients may request - a FULL SyncKind. In LSP 3.x, clients make this request by omitting + ``Incremental`` versus ``Full`` synchronization: + Even if a server accepts ``Incremantal`` SyncKinds, clients may request + a ``Full`` SyncKind. In LSP 3.x, clients make this request by omitting both Range and RangeLength from their request. Consequently, the - attributes "range" and "rangeLength" will be missing from FULL + attributes "range" and "rangeLength" will be missing from ``Full`` content update client requests in the pygls Python library. NOTE: After adding pydantic models, "range" and "rangeLength" fileds @@ -274,7 +279,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 @@ -313,7 +319,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] @@ -345,7 +352,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( diff --git a/tests/ls_setup.py b/tests/ls_setup.py index 5df29b55..48dcfa89 100644 --- a/tests/ls_setup.py +++ b/tests/ls_setup.py @@ -20,10 +20,13 @@ import threading import pytest -from pygls.lsp.methods import EXIT, INITIALIZE, SHUTDOWN -from pygls.lsp.types import ClientCapabilities, InitializeParams -from pygls.protocol import deserialize_message - +from lsprotocol.types import ( + EXIT, + INITIALIZE, + SHUTDOWN, + ClientCapabilities, + InitializeParams, +) from pygls.server import LanguageServer @@ -60,8 +63,9 @@ def close(self): ... def write(self, data): + object_hook = self.dest.lsp._deserialize_message self.dest.lsp._procedure_handler( - json.loads(data, object_hook=deserialize_message) + json.loads(data, object_hook=object_hook) ) @@ -104,7 +108,7 @@ def initialize(self): ) ).result(timeout=CALL_TIMEOUT) - assert 'capabilities' in response + assert response.capabilities is not None def __iter__(self): yield self.client @@ -121,6 +125,7 @@ def __init__(self): # Setup Server self.server = LanguageServer() self.server_thread = threading.Thread( + name='Server Thread', target=self.server.start_io, args=(os.fdopen(csr, "rb"), os.fdopen(scw, "wb")), ) @@ -129,6 +134,7 @@ def __init__(self): # Setup client self.client = LanguageServer(asyncio.new_event_loop()) self.client_thread = threading.Thread( + name='Client Thread', target=self.client.start_io, args=(os.fdopen(scr, "rb"), os.fdopen(csw, "wb")), ) @@ -174,7 +180,7 @@ def initialize(self): capabilities=ClientCapabilities() ), ).result(timeout=timeout) - assert "capabilities" in response + assert response.capabilities is not None def __iter__(self): yield self.client diff --git a/tests/lsp/semantic_tokens/test_delta_missing_legend.py b/tests/lsp/semantic_tokens/test_delta_missing_legend.py index daf49aec..b7a5c010 100644 --- a/tests/lsp/semantic_tokens/test_delta_missing_legend.py +++ b/tests/lsp/semantic_tokens/test_delta_missing_legend.py @@ -16,15 +16,15 @@ ############################################################################ from typing import Optional, Union -from pygls.lsp.methods import ( +from lsprotocol.types import ( TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA, ) -from pygls.lsp.types import ( +from lsprotocol.types import ( SemanticTokens, SemanticTokensDeltaParams, SemanticTokensLegend, SemanticTokensPartialResult, - SemanticTokensRequestsFull, + SemanticTokensOptionsFullType1, TextDocumentIdentifier, ) @@ -55,9 +55,7 @@ def test_capabilities(client_server): capabilities = server.server_capabilities provider = capabilities.semantic_tokens_provider - assert provider.full == SemanticTokensRequestsFull( - delta=True - ) + assert provider.full == SemanticTokensOptionsFullType1(delta=True) assert provider.legend.token_types == [ "keyword", "operator", @@ -81,7 +79,7 @@ def test_semantic_tokens_full_delta_return_tokens(client_server): assert response - assert response["data"] == [0, 0, 3, 0, 0] + assert response.data == [0, 0, 3, 0, 0] @ConfiguredLS.decorate() diff --git a/tests/lsp/semantic_tokens/test_delta_missing_legend_none.py b/tests/lsp/semantic_tokens/test_delta_missing_legend_none.py index 71c759fb..6f4fa17d 100644 --- a/tests/lsp/semantic_tokens/test_delta_missing_legend_none.py +++ b/tests/lsp/semantic_tokens/test_delta_missing_legend_none.py @@ -16,12 +16,12 @@ ############################################################################ from typing import Optional, Union -from pygls.lsp.types import ( +from lsprotocol.types import ( SemanticTokens, SemanticTokensDeltaParams, SemanticTokensPartialResult, ) -from pygls.lsp.methods import ( +from lsprotocol.types import ( TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL_DELTA, ) diff --git a/tests/lsp/semantic_tokens/test_full_missing_legend.py b/tests/lsp/semantic_tokens/test_full_missing_legend.py index e2e1f747..76c00e4b 100644 --- a/tests/lsp/semantic_tokens/test_full_missing_legend.py +++ b/tests/lsp/semantic_tokens/test_full_missing_legend.py @@ -16,10 +16,10 @@ ############################################################################ from typing import Optional, Union -from pygls.lsp.methods import ( +from lsprotocol.types import ( TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, ) -from pygls.lsp.types import ( +from lsprotocol.types import ( SemanticTokens, SemanticTokensPartialResult, SemanticTokensParams diff --git a/tests/lsp/semantic_tokens/test_range.py b/tests/lsp/semantic_tokens/test_range.py index d990a947..8099e92e 100644 --- a/tests/lsp/semantic_tokens/test_range.py +++ b/tests/lsp/semantic_tokens/test_range.py @@ -16,10 +16,10 @@ ############################################################################ from typing import Optional, Union -from pygls.lsp.methods import ( +from lsprotocol.types import ( TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE, ) -from pygls.lsp.types import ( +from lsprotocol.types import ( Position, Range, SemanticTokens, @@ -90,7 +90,7 @@ def test_semantic_tokens_range_return_tokens(client_server): assert response - assert response["data"] == [0, 0, 3, 0, 0] + assert response.data == [0, 0, 3, 0, 0] @ConfiguredLS.decorate() diff --git a/tests/lsp/semantic_tokens/test_range_missing_legends.py b/tests/lsp/semantic_tokens/test_range_missing_legends.py index 1df1e50b..69780efa 100644 --- a/tests/lsp/semantic_tokens/test_range_missing_legends.py +++ b/tests/lsp/semantic_tokens/test_range_missing_legends.py @@ -16,10 +16,10 @@ ############################################################################ from typing import Optional, Union -from pygls.lsp.methods import ( +from lsprotocol.types import ( TEXT_DOCUMENT_SEMANTIC_TOKENS_RANGE, ) -from pygls.lsp.types import ( +from lsprotocol.types import ( SemanticTokens, SemanticTokensParams, SemanticTokensPartialResult, diff --git a/tests/lsp/semantic_tokens/test_semantic_tokens_full.py b/tests/lsp/semantic_tokens/test_semantic_tokens_full.py index 0341d284..41c3c85c 100644 --- a/tests/lsp/semantic_tokens/test_semantic_tokens_full.py +++ b/tests/lsp/semantic_tokens/test_semantic_tokens_full.py @@ -16,10 +16,10 @@ ############################################################################ from typing import Optional, Union -from pygls.lsp.methods import ( +from lsprotocol.types import ( TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, ) -from pygls.lsp.types import ( +from lsprotocol.types import ( SemanticTokens, SemanticTokensLegend, SemanticTokensParams, @@ -84,7 +84,7 @@ def test_semantic_tokens_full_return_tokens(client_server): assert response - assert response["data"] == [0, 0, 3, 0, 0] + assert response.data == [0, 0, 3, 0, 0] @ConfiguredLS.decorate() diff --git a/tests/lsp/test_call_hierarchy.py b/tests/lsp/test_call_hierarchy.py index 721aaa4a..c86d0d59 100644 --- a/tests/lsp/test_call_hierarchy.py +++ b/tests/lsp/test_call_hierarchy.py @@ -16,12 +16,12 @@ ############################################################################ from typing import List, Optional -from pygls.lsp.methods import ( - TEXT_DOCUMENT_CALL_HIERARCHY_INCOMING_CALLS, - TEXT_DOCUMENT_CALL_HIERARCHY_OUTGOING_CALLS, - TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE +from lsprotocol.types import ( + CALL_HIERARCHY_INCOMING_CALLS, + CALL_HIERARCHY_OUTGOING_CALLS, + TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY ) -from pygls.lsp.types import ( +from lsprotocol.types import ( CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, CallHierarchyOptions, CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, @@ -49,21 +49,21 @@ def check_call_hierarchy_item_response(item): - assert item['name'] == 'test_name' - assert item['kind'] == SymbolKind.File - assert item['uri'] == 'test_uri' - assert item['range']['start']['line'] == 0 - assert item['range']['start']['character'] == 0 - assert item['range']['end']['line'] == 1 - assert item['range']['end']['character'] == 1 - assert item['selectionRange']['start']['line'] == 1 - assert item['selectionRange']['start']['character'] == 1 - assert item['selectionRange']['end']['line'] == 2 - assert item['selectionRange']['end']['character'] == 2 - assert len(item['tags']) == 1 - assert item['tags'][0] == SymbolTag.Deprecated - assert item['detail'] == 'test_detail' - assert item['data'] == 'test_data' + assert item.name == 'test_name' + assert item.kind == SymbolKind.File + assert item.uri == 'test_uri' + assert item.range.start.line == 0 + assert item.range.start.character == 0 + assert item.range.end.line == 1 + assert item.range.end.character == 1 + assert item.selection_range.start.line == 1 + assert item.selection_range.start.character == 1 + assert item.selection_range.end.line == 2 + assert item.selection_range.end.character == 2 + assert len(item.tags) == 1 + assert item.tags[0] == SymbolTag.Deprecated + assert item.detail == 'test_detail' + assert item.data == 'test_data' class ConfiguredLS(ClientServer): @@ -71,7 +71,7 @@ def __init__(self): super().__init__() @self.server.feature( - TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE, + TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, CallHierarchyOptions(), ) def f1( @@ -82,7 +82,7 @@ def f1( else: return None - @self.server.feature(TEXT_DOCUMENT_CALL_HIERARCHY_INCOMING_CALLS) + @self.server.feature(CALL_HIERARCHY_INCOMING_CALLS) def f2( params: CallHierarchyIncomingCallsParams ) -> Optional[List[CallHierarchyIncomingCall]]: @@ -98,7 +98,7 @@ def f2( ), ] - @self.server.feature(TEXT_DOCUMENT_CALL_HIERARCHY_OUTGOING_CALLS) + @self.server.feature(CALL_HIERARCHY_OUTGOING_CALLS) def f3( params: CallHierarchyOutgoingCallsParams ) -> Optional[List[CallHierarchyOutgoingCall]]: @@ -126,7 +126,7 @@ def test_capabilities(client_server): def test_call_hierarchy_prepare_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE, + TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, CallHierarchyPrepareParams( text_document=TextDocumentIdentifier(uri='file://return.list'), position=Position(line=0, character=0), @@ -140,7 +140,7 @@ def test_call_hierarchy_prepare_return_list(client_server): def test_call_hierarchy_prepare_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE, + TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, CallHierarchyPrepareParams( text_document=TextDocumentIdentifier(uri='file://return.none'), position=Position(line=0, character=0), @@ -154,33 +154,34 @@ def test_call_hierarchy_prepare_return_none(client_server): def test_call_hierarchy_incoming_calls_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - TEXT_DOCUMENT_CALL_HIERARCHY_INCOMING_CALLS, + CALL_HIERARCHY_INCOMING_CALLS, CallHierarchyIncomingCallsParams(item=CALL_HIERARCHY_ITEM) ).result() item = response[0] - check_call_hierarchy_item_response(item['from']) + check_call_hierarchy_item_response(item.from_) - assert item['fromRanges'][0]['start']['line'] == 2 - assert item['fromRanges'][0]['start']['character'] == 2 - assert item['fromRanges'][0]['end']['line'] == 3 - assert item['fromRanges'][0]['end']['character'] == 3 + assert item.from_ranges[0].start.line == 2 + assert item.from_ranges[0].start.character == 2 + assert item.from_ranges[0].end.line == 3 + assert item.from_ranges[0].end.character == 3 @ConfiguredLS.decorate() def test_call_hierarchy_outgoing_calls_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - TEXT_DOCUMENT_CALL_HIERARCHY_OUTGOING_CALLS, + CALL_HIERARCHY_OUTGOING_CALLS, CallHierarchyOutgoingCallsParams(item=CALL_HIERARCHY_ITEM) ).result() item = response[0] - check_call_hierarchy_item_response(item['to']) + check_call_hierarchy_item_response(item.to) + + assert item.from_ranges[0].start.line == 3 + assert item.from_ranges[0].start.character == 3 + assert item.from_ranges[0].end.line == 4 + assert item.from_ranges[0].end.character == 4 - assert item['fromRanges'][0]['start']['line'] == 3 - assert item['fromRanges'][0]['start']['character'] == 3 - assert item['fromRanges'][0]['end']['line'] == 4 - assert item['fromRanges'][0]['end']['character'] == 4 diff --git a/tests/lsp/test_code_action.py b/tests/lsp/test_code_action.py index 31946cd8..033ba5ed 100644 --- a/tests/lsp/test_code_action.py +++ b/tests/lsp/test_code_action.py @@ -16,8 +16,8 @@ ############################################################################ from typing import List, Optional, Union -from pygls.lsp.methods import CODE_ACTION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_CODE_ACTION +from lsprotocol.types import ( CodeAction, CodeActionContext, CodeActionKind, @@ -38,7 +38,7 @@ def __init__(self): super().__init__() @self.server.feature( - CODE_ACTION, + TEXT_DOCUMENT_CODE_ACTION, CodeActionOptions(code_action_kinds=[CodeActionKind.Refactor]) ) def f( @@ -72,7 +72,7 @@ def test_capabilities(client_server): def test_code_action_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - CODE_ACTION, + TEXT_DOCUMENT_CODE_ACTION, CodeActionParams( text_document=TextDocumentIdentifier(uri="file://return.list"), range=Range( @@ -94,19 +94,19 @@ def test_code_action_return_list(client_server): ), ).result() - assert response[0]["title"] == "action1" - assert response[1]["title"] == "action2" - assert response[1]["kind"] == CodeActionKind.Refactor - assert response[2]["title"] == "cmd1" - assert response[2]["command"] == "cmd1" - assert response[2]["arguments"] == [1, "two"] + assert response[0].title == "action1" + assert response[1].title == "action2" + assert response[1].kind == CodeActionKind.Refactor + assert response[2].title == "cmd1" + assert response[2].command == "cmd1" + assert response[2].arguments == [1, "two"] @ConfiguredLS.decorate() def test_code_action_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - CODE_ACTION, + TEXT_DOCUMENT_CODE_ACTION, CodeActionParams( text_document=TextDocumentIdentifier(uri="file://return.none"), range=Range( diff --git a/tests/lsp/test_code_lens.py b/tests/lsp/test_code_lens.py index db2b5146..2b728bf4 100644 --- a/tests/lsp/test_code_lens.py +++ b/tests/lsp/test_code_lens.py @@ -16,8 +16,8 @@ ############################################################################ from typing import List, Optional -from pygls.lsp.methods import CODE_LENS -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_CODE_LENS +from lsprotocol.types import ( CodeLens, CodeLensOptions, CodeLensParams, @@ -35,7 +35,7 @@ def __init__(self): super().__init__() @self.server.feature( - CODE_LENS, + TEXT_DOCUMENT_CODE_LENS, CodeLensOptions(resolve_provider=False), ) def f(params: CodeLensParams) -> Optional[List[CodeLens]]: @@ -70,26 +70,26 @@ def test_capabilities(client_server): def test_code_lens_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - CODE_LENS, + TEXT_DOCUMENT_CODE_LENS, CodeLensParams( text_document=TextDocumentIdentifier(uri="file://return.list") ), ).result() - assert response[0]["data"] == "some data" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 - assert response[0]["command"]["title"] == "cmd1" - assert response[0]["command"]["command"] == "cmd1" + assert response[0].data == "some data" + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 + assert response[0].command.title == "cmd1" + assert response[0].command.command == "cmd1" @ConfiguredLS.decorate() def test_code_lens_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - CODE_LENS, + TEXT_DOCUMENT_CODE_LENS, CodeLensParams( text_document=TextDocumentIdentifier(uri="file://return.none") ), diff --git a/tests/lsp/test_color_presentation.py b/tests/lsp/test_color_presentation.py index ffd64c01..6748e66f 100644 --- a/tests/lsp/test_color_presentation.py +++ b/tests/lsp/test_color_presentation.py @@ -17,8 +17,8 @@ from typing import List -from pygls.lsp.methods import COLOR_PRESENTATION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_COLOR_PRESENTATION +from lsprotocol.types import ( Color, ColorPresentation, ColorPresentationParams, @@ -35,7 +35,7 @@ class ConfiguredLS(ClientServer): def __init__(self): super().__init__() - @self.server.feature(COLOR_PRESENTATION) + @self.server.feature(TEXT_DOCUMENT_COLOR_PRESENTATION) def f(params: ColorPresentationParams) -> List[ColorPresentation]: return [ ColorPresentation( @@ -67,21 +67,11 @@ def f(params: ColorPresentationParams) -> List[ColorPresentation]: ] -@ConfiguredLS.decorate() -def test_capabilities(): - """From specs: - - This request has no special capabilities and registration options since - it is send as a resolve request for the textDocument/documentColor - request. - """ - - @ConfiguredLS.decorate() def test_color_presentation(client_server): client, _ = client_server response = client.lsp.send_request( - COLOR_PRESENTATION, + TEXT_DOCUMENT_COLOR_PRESENTATION, ColorPresentationParams( text_document=TextDocumentIdentifier(uri="file://return.list"), color=Color(red=0.6, green=0.2, blue=0.3, alpha=0.5), @@ -92,22 +82,22 @@ def test_color_presentation(client_server): ), ).result() - assert response[0]["label"] == "label1" - assert response[0]["textEdit"]["newText"] == "te" + assert response[0].label == "label1" + assert response[0].text_edit.new_text == "te" - assert response[0]["textEdit"]["range"]["start"]["line"] == 0 - assert response[0]["textEdit"]["range"]["start"]["character"] == 0 - assert response[0]["textEdit"]["range"]["end"]["line"] == 1 - assert response[0]["textEdit"]["range"]["end"]["character"] == 1 + assert response[0].text_edit.range.start.line == 0 + assert response[0].text_edit.range.start.character == 0 + assert response[0].text_edit.range.end.line == 1 + assert response[0].text_edit.range.end.character == 1 - range = response[0]["additionalTextEdits"][0]["range"] - assert range["start"]["line"] == 1 - assert range["start"]["character"] == 1 - assert range["end"]["line"] == 2 - assert range["end"]["character"] == 2 + range = response[0].additional_text_edits[0].range + assert range.start.line == 1 + assert range.start.character == 1 + assert range.end.line == 2 + assert range.end.character == 2 - range = response[0]["additionalTextEdits"][1]["range"] - assert range["start"]["line"] == 2 - assert range["start"]["character"] == 2 - assert range["end"]["line"] == 3 - assert range["end"]["character"] == 3 + range = response[0].additional_text_edits[1].range + assert range.start.line == 2 + assert range.start.character == 2 + assert range.end.line == 3 + assert range.end.character == 3 diff --git a/tests/lsp/test_completion.py b/tests/lsp/test_completion.py index 59c70946..2cd7c182 100644 --- a/tests/lsp/test_completion.py +++ b/tests/lsp/test_completion.py @@ -14,8 +14,8 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -from pygls.lsp.methods import COMPLETION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_COMPLETION +from lsprotocol.types import ( CompletionItem, CompletionItemKind, CompletionList, @@ -33,7 +33,7 @@ def __init__(self): super().__init__() @self.server.feature( - COMPLETION, + TEXT_DOCUMENT_COMPLETION, CompletionOptions( trigger_characters=[","], all_commit_characters=[":"], @@ -68,28 +68,28 @@ def test_capabilities(client_server): def test_completions(client_server): client, _ = client_server response = client.lsp.send_request( - COMPLETION, + TEXT_DOCUMENT_COMPLETION, CompletionParams( text_document=TextDocumentIdentifier(uri="file://test.test"), position=Position(line=0, character=0), ), ).result() - assert not response["isIncomplete"] - assert response["items"][0]["label"] == "test1" - assert response["items"][0]["kind"] == CompletionItemKind.Method - assert response["items"][0]["preselect"] - assert "deprecated" not in response["items"][0] - assert "tags" not in response["items"][0] - assert "detail" not in response["items"][0] - assert "documentation" not in response["items"][0] - assert "sort_text" not in response["items"][0] - assert "filter_text" not in response["items"][0] - assert "insert_text" not in response["items"][0] - assert "insert_text_format" not in response["items"][0] - assert "insert_text_mode" not in response["items"][0] - assert "text_edit" not in response["items"][0] - assert "additional_text_edits" not in response["items"][0] - assert "commit_characters" not in response["items"][0] - assert "command" not in response["items"][0] - assert "data" not in response["items"][0] + assert not response.is_incomplete + assert response.items[0].label == "test1" + assert response.items[0].kind == CompletionItemKind.Method + assert response.items[0].preselect + assert response.items[0].deprecated is None + assert response.items[0].tags is None + assert response.items[0].detail is None + assert response.items[0].documentation is None + assert response.items[0].sort_text is None + assert response.items[0].filter_text is None + assert response.items[0].insert_text is None + assert response.items[0].insert_text_format is None + assert response.items[0].insert_text_mode is None + assert response.items[0].text_edit is None + assert response.items[0].additional_text_edits is None + assert response.items[0].commit_characters is None + assert response.items[0].command is None + assert response.items[0].data is None diff --git a/tests/lsp/test_declaration.py b/tests/lsp/test_declaration.py index a1a1849b..4a8c3de9 100644 --- a/tests/lsp/test_declaration.py +++ b/tests/lsp/test_declaration.py @@ -17,8 +17,8 @@ from typing import List, Optional, Union -from pygls.lsp.methods import DECLARATION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_DECLARATION +from lsprotocol.types import ( DeclarationOptions, DeclarationParams, Location, @@ -35,7 +35,7 @@ class ConfiguredLS(ClientServer): def __init__(self): super().__init__() - @self.server.feature(DECLARATION, DeclarationOptions()) + @self.server.feature(TEXT_DOCUMENT_DECLARATION, DeclarationOptions()) def f( params: DeclarationParams, ) -> Optional[Union[Location, List[Location], List[LocationLink]]]: @@ -82,7 +82,7 @@ def test_capabilities(client_server): def test_declaration_return_location(client_server): client, _ = client_server response = client.lsp.send_request( - DECLARATION, + TEXT_DOCUMENT_DECLARATION, DeclarationParams( text_document=TextDocumentIdentifier( uri="file://return.location" @@ -91,19 +91,19 @@ def test_declaration_return_location(client_server): ), ).result() - assert response["uri"] == "uri" + assert response.uri == "uri" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 @ConfiguredLS.decorate() def test_declaration_return_location_list(client_server): client, _ = client_server response = client.lsp.send_request( - DECLARATION, + TEXT_DOCUMENT_DECLARATION, DeclarationParams( text_document=TextDocumentIdentifier( uri="file://return.location_list"), @@ -111,19 +111,19 @@ def test_declaration_return_location_list(client_server): ), ).result() - assert response[0]["uri"] == "uri" + assert response[0].uri == "uri" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_declaration_return_location_link_list(client_server): client, _ = client_server response = client.lsp.send_request( - DECLARATION, + TEXT_DOCUMENT_DECLARATION, DeclarationParams( text_document=TextDocumentIdentifier( uri="file://return.location_link_list" @@ -132,29 +132,29 @@ def test_declaration_return_location_link_list(client_server): ), ).result() - assert response[0]["targetUri"] == "uri" + assert response[0].target_uri == "uri" - assert response[0]["targetRange"]["start"]["line"] == 0 - assert response[0]["targetRange"]["start"]["character"] == 0 - assert response[0]["targetRange"]["end"]["line"] == 1 - assert response[0]["targetRange"]["end"]["character"] == 1 + assert response[0].target_range.start.line == 0 + assert response[0].target_range.start.character == 0 + assert response[0].target_range.end.line == 1 + assert response[0].target_range.end.character == 1 - assert response[0]["targetSelectionRange"]["start"]["line"] == 0 - assert response[0]["targetSelectionRange"]["start"]["character"] == 0 - assert response[0]["targetSelectionRange"]["end"]["line"] == 2 - assert response[0]["targetSelectionRange"]["end"]["character"] == 2 + assert response[0].target_selection_range.start.line == 0 + assert response[0].target_selection_range.start.character == 0 + assert response[0].target_selection_range.end.line == 2 + assert response[0].target_selection_range.end.character == 2 - assert response[0]["originSelectionRange"]["start"]["line"] == 0 - assert response[0]["originSelectionRange"]["start"]["character"] == 0 - assert response[0]["originSelectionRange"]["end"]["line"] == 3 - assert response[0]["originSelectionRange"]["end"]["character"] == 3 + assert response[0].origin_selection_range.start.line == 0 + assert response[0].origin_selection_range.start.character == 0 + assert response[0].origin_selection_range.end.line == 3 + assert response[0].origin_selection_range.end.character == 3 @ConfiguredLS.decorate() def test_declaration_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - DECLARATION, + TEXT_DOCUMENT_DECLARATION, DeclarationParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_definition.py b/tests/lsp/test_definition.py index ae8f3f57..d101efb5 100644 --- a/tests/lsp/test_definition.py +++ b/tests/lsp/test_definition.py @@ -17,8 +17,8 @@ from typing import List, Optional, Union -from pygls.lsp.methods import DEFINITION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_DEFINITION +from lsprotocol.types import ( DefinitionOptions, DefinitionParams, Location, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - DEFINITION, + TEXT_DOCUMENT_DEFINITION, DefinitionOptions(), ) def f( @@ -85,7 +85,7 @@ def test_capabilities(client_server): def test_definition_return_location(client_server): client, _ = client_server response = client.lsp.send_request( - DEFINITION, + TEXT_DOCUMENT_DEFINITION, DefinitionParams( text_document=TextDocumentIdentifier( uri="file://return.location"), @@ -93,19 +93,19 @@ def test_definition_return_location(client_server): ), ).result() - assert response["uri"] == "uri" + assert response.uri == "uri" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 @ConfiguredLS.decorate() def test_definition_return_location_list(client_server): client, _ = client_server response = client.lsp.send_request( - DEFINITION, + TEXT_DOCUMENT_DEFINITION, DefinitionParams( text_document=TextDocumentIdentifier( uri="file://return.location_list"), @@ -113,19 +113,19 @@ def test_definition_return_location_list(client_server): ), ).result() - assert response[0]["uri"] == "uri" + assert response[0].uri == "uri" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_definition_return_location_link_list(client_server): client, _ = client_server response = client.lsp.send_request( - DEFINITION, + TEXT_DOCUMENT_DEFINITION, DefinitionParams( text_document=TextDocumentIdentifier( uri="file://return.location_link_list" @@ -134,29 +134,29 @@ def test_definition_return_location_link_list(client_server): ), ).result() - assert response[0]["targetUri"] == "uri" + assert response[0].target_uri == "uri" - assert response[0]["targetRange"]["start"]["line"] == 0 - assert response[0]["targetRange"]["start"]["character"] == 0 - assert response[0]["targetRange"]["end"]["line"] == 1 - assert response[0]["targetRange"]["end"]["character"] == 1 + assert response[0].target_range.start.line == 0 + assert response[0].target_range.start.character == 0 + assert response[0].target_range.end.line == 1 + assert response[0].target_range.end.character == 1 - assert response[0]["targetSelectionRange"]["start"]["line"] == 0 - assert response[0]["targetSelectionRange"]["start"]["character"] == 0 - assert response[0]["targetSelectionRange"]["end"]["line"] == 2 - assert response[0]["targetSelectionRange"]["end"]["character"] == 2 + assert response[0].target_selection_range.start.line == 0 + assert response[0].target_selection_range.start.character == 0 + assert response[0].target_selection_range.end.line == 2 + assert response[0].target_selection_range.end.character == 2 - assert response[0]["originSelectionRange"]["start"]["line"] == 0 - assert response[0]["originSelectionRange"]["start"]["character"] == 0 - assert response[0]["originSelectionRange"]["end"]["line"] == 3 - assert response[0]["originSelectionRange"]["end"]["character"] == 3 + assert response[0].origin_selection_range.start.line == 0 + assert response[0].origin_selection_range.start.character == 0 + assert response[0].origin_selection_range.end.line == 3 + assert response[0].origin_selection_range.end.character == 3 @ConfiguredLS.decorate() def test_definition_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - DEFINITION, + TEXT_DOCUMENT_DEFINITION, DefinitionParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_document_color.py b/tests/lsp/test_document_color.py index 2c872202..460a60b4 100644 --- a/tests/lsp/test_document_color.py +++ b/tests/lsp/test_document_color.py @@ -17,8 +17,8 @@ from typing import List -from pygls.lsp.methods import DOCUMENT_COLOR -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_DOCUMENT_COLOR +from lsprotocol.types import ( Color, ColorInformation, DocumentColorOptions, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - DOCUMENT_COLOR, + TEXT_DOCUMENT_DOCUMENT_COLOR, DocumentColorOptions(), ) def f(params: DocumentColorParams) -> List[ColorInformation]: @@ -63,19 +63,19 @@ def test_capabilities(client_server): def test_document_color(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_COLOR, + TEXT_DOCUMENT_DOCUMENT_COLOR, DocumentColorParams( text_document=TextDocumentIdentifier(uri="file://return.list") ), ).result() assert response - assert response[0]["color"]["red"] == 0.5 - assert response[0]["color"]["green"] == 0.5 - assert response[0]["color"]["blue"] == 0.5 - assert response[0]["color"]["alpha"] == 0.5 + assert response[0].color.red == 0.5 + assert response[0].color.green == 0.5 + assert response[0].color.blue == 0.5 + assert response[0].color.alpha == 0.5 - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 diff --git a/tests/lsp/test_document_highlight.py b/tests/lsp/test_document_highlight.py index 6d76ce41..dcfc0162 100644 --- a/tests/lsp/test_document_highlight.py +++ b/tests/lsp/test_document_highlight.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import DOCUMENT_HIGHLIGHT -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT +from lsprotocol.types import ( DocumentHighlight, DocumentHighlightKind, DocumentHighlightOptions, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - DOCUMENT_HIGHLIGHT, + TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT, DocumentHighlightOptions(), ) def f( @@ -74,7 +74,7 @@ def test_capabilities(client_server): def test_document_highlight_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_HIGHLIGHT, + TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT, DocumentHighlightParams( text_document=TextDocumentIdentifier(uri="file://return.list"), position=Position(line=0, character=0), @@ -83,24 +83,24 @@ def test_document_highlight_return_list(client_server): assert response - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 - assert "kind" not in response[0] + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 + assert response[0].kind is None - assert response[1]["range"]["start"]["line"] == 1 - assert response[1]["range"]["start"]["character"] == 1 - assert response[1]["range"]["end"]["line"] == 2 - assert response[1]["range"]["end"]["character"] == 2 - assert response[1]["kind"] == DocumentHighlightKind.Write + assert response[1].range.start.line == 1 + assert response[1].range.start.character == 1 + assert response[1].range.end.line == 2 + assert response[1].range.end.character == 2 + assert response[1].kind == DocumentHighlightKind.Write @ConfiguredLS.decorate() def test_document_highlight_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_HIGHLIGHT, + TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT, DocumentHighlightParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_document_link.py b/tests/lsp/test_document_link.py index f208392c..0602773d 100644 --- a/tests/lsp/test_document_link.py +++ b/tests/lsp/test_document_link.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import DOCUMENT_LINK -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_DOCUMENT_LINK +from lsprotocol.types import ( DocumentLink, DocumentLinkOptions, DocumentLinkParams, @@ -35,7 +35,7 @@ def __init__(self): super().__init__() @self.server.feature( - DOCUMENT_LINK, + TEXT_DOCUMENT_DOCUMENT_LINK, DocumentLinkOptions(resolve_provider=True), ) def f(params: DocumentLinkParams) -> Optional[List[DocumentLink]]: @@ -68,7 +68,7 @@ def test_capabilities(client_server): def test_document_link_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_LINK, + TEXT_DOCUMENT_DOCUMENT_LINK, DocumentLinkParams( text_document=TextDocumentIdentifier(uri="file://return.list"), ), @@ -76,20 +76,20 @@ def test_document_link_return_list(client_server): assert response - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 - assert response[0]["target"] == "target" - assert response[0]["tooltip"] == "tooltip" - assert response[0]["data"] == "data" + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 + assert response[0].target == "target" + assert response[0].tooltip == "tooltip" + assert response[0].data == "data" @ConfiguredLS.decorate() def test_document_link_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_LINK, + TEXT_DOCUMENT_DOCUMENT_LINK, DocumentLinkParams( text_document=TextDocumentIdentifier(uri="file://return.none"), ), diff --git a/tests/lsp/test_document_symbol.py b/tests/lsp/test_document_symbol.py index 9dd97c4e..251c8fb8 100644 --- a/tests/lsp/test_document_symbol.py +++ b/tests/lsp/test_document_symbol.py @@ -17,8 +17,8 @@ from typing import List, Union -from pygls.lsp.methods import DOCUMENT_SYMBOL -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_DOCUMENT_SYMBOL +from lsprotocol.types import ( DocumentSymbol, DocumentSymbolOptions, DocumentSymbolParams, @@ -38,7 +38,7 @@ def __init__(self): super().__init__() @self.server.feature( - DOCUMENT_SYMBOL, + TEXT_DOCUMENT_DOCUMENT_SYMBOL, DocumentSymbolOptions(), ) def f( @@ -105,7 +105,7 @@ def test_capabilities(client_server): def test_document_symbol_return_symbol_information_list(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_SYMBOL, + TEXT_DOCUMENT_DOCUMENT_SYMBOL, DocumentSymbolParams( text_document=TextDocumentIdentifier( uri="file://return.symbol_information_list" @@ -115,22 +115,22 @@ def test_document_symbol_return_symbol_information_list(client_server): assert response - assert response[0]["name"] == "symbol" - assert response[0]["kind"] == SymbolKind.Namespace - assert response[0]["location"]["uri"] == "uri" - assert response[0]["location"]["range"]["start"]["line"] == 0 - assert response[0]["location"]["range"]["start"]["character"] == 0 - assert response[0]["location"]["range"]["end"]["line"] == 1 - assert response[0]["location"]["range"]["end"]["character"] == 1 - assert response[0]["containerName"] == "container" - assert not response[0]["deprecated"] + assert response[0].name == "symbol" + assert response[0].kind == SymbolKind.Namespace + assert response[0].location.uri == "uri" + assert response[0].location.range.start.line == 0 + assert response[0].location.range.start.character == 0 + assert response[0].location.range.end.line == 1 + assert response[0].location.range.end.character == 1 + assert response[0].container_name == "container" + assert not response[0].deprecated @ConfiguredLS.decorate() def test_document_symbol_return_document_symbol_list(client_server): client, _ = client_server response = client.lsp.send_request( - DOCUMENT_SYMBOL, + TEXT_DOCUMENT_DOCUMENT_SYMBOL, DocumentSymbolParams( text_document=TextDocumentIdentifier( uri="file://return.document_symbol_list" @@ -140,29 +140,29 @@ def test_document_symbol_return_document_symbol_list(client_server): assert response - assert response[0]["name"] == "symbol" - assert response[0]["kind"] == SymbolKind.Object - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 10 - assert response[0]["range"]["end"]["character"] == 10 - assert response[0]["selectionRange"]["start"]["line"] == 0 - assert response[0]["selectionRange"]["start"]["character"] == 0 - assert response[0]["selectionRange"]["end"]["line"] == 10 - assert response[0]["selectionRange"]["end"]["character"] == 10 - assert response[0]["detail"] == "detail" - assert response[0]["deprecated"] - - assert response[0]["children"][0]["name"] == "inner_symbol" - assert response[0]["children"][0]["kind"] == SymbolKind.Number - assert response[0]["children"][0]["range"]["start"]["line"] == 0 - assert response[0]["children"][0]["range"]["start"]["character"] == 0 - assert response[0]["children"][0]["range"]["end"]["line"] == 1 - assert response[0]["children"][0]["range"]["end"]["character"] == 1 - range = response[0]["children"][0]["selectionRange"] - assert range["start"]["line"] == 0 - assert range["start"]["character"] == 0 - assert range["end"]["line"] == 1 - assert range["end"]["character"] == 1 - - assert "children" not in response[0]["children"][0] + assert response[0].name == "symbol" + assert response[0].kind == SymbolKind.Object + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 10 + assert response[0].range.end.character == 10 + assert response[0].selection_range.start.line == 0 + assert response[0].selection_range.start.character == 0 + assert response[0].selection_range.end.line == 10 + assert response[0].selection_range.end.character == 10 + assert response[0].detail == "detail" + assert response[0].deprecated + + assert response[0].children[0].name == "inner_symbol" + assert response[0].children[0].kind == SymbolKind.Number + assert response[0].children[0].range.start.line == 0 + assert response[0].children[0].range.start.character == 0 + assert response[0].children[0].range.end.line == 1 + assert response[0].children[0].range.end.character == 1 + range = response[0].children[0].selection_range + assert range.start.line == 0 + assert range.start.character == 0 + assert range.end.line == 1 + assert range.end.character == 1 + + assert response[0].children[0].children is None diff --git a/tests/lsp/test_folding_range.py b/tests/lsp/test_folding_range.py index b2bdfef6..8f9c749a 100644 --- a/tests/lsp/test_folding_range.py +++ b/tests/lsp/test_folding_range.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import FOLDING_RANGE -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_FOLDING_RANGE +from lsprotocol.types import ( FoldingRange, FoldingRangeKind, FoldingRangeOptions, @@ -34,7 +34,7 @@ def __init__(self): super().__init__() @self.server.feature( - FOLDING_RANGE, + TEXT_DOCUMENT_FOLDING_RANGE, FoldingRangeOptions(), ) def f(params: FoldingRangeParams) -> Optional[List[FoldingRange]]: @@ -64,7 +64,7 @@ def test_capabilities(client_server): def test_folding_range_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - FOLDING_RANGE, + TEXT_DOCUMENT_FOLDING_RANGE, FoldingRangeParams( text_document=TextDocumentIdentifier(uri="file://return.list"), ), @@ -72,18 +72,18 @@ def test_folding_range_return_list(client_server): assert response - assert response[0]["startLine"] == 0 - assert response[0]["endLine"] == 0 - assert response[0]["startCharacter"] == 1 - assert response[0]["endCharacter"] == 1 - assert response[0]["kind"] == FoldingRangeKind.Comment + assert response[0].start_line == 0 + assert response[0].end_line == 0 + assert response[0].start_character == 1 + assert response[0].end_character == 1 + assert response[0].kind == FoldingRangeKind.Comment @ConfiguredLS.decorate() def test_folding_range_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - FOLDING_RANGE, + TEXT_DOCUMENT_FOLDING_RANGE, FoldingRangeParams( text_document=TextDocumentIdentifier(uri="file://return.none"), ), diff --git a/tests/lsp/test_formatting.py b/tests/lsp/test_formatting.py index 6f0caa60..0c3fbd66 100644 --- a/tests/lsp/test_formatting.py +++ b/tests/lsp/test_formatting.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import FORMATTING -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_FORMATTING +from lsprotocol.types import ( DocumentFormattingOptions, DocumentFormattingParams, FormattingOptions, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - FORMATTING, + TEXT_DOCUMENT_FORMATTING, DocumentFormattingOptions(), ) def f(params: DocumentFormattingParams) -> Optional[List[TextEdit]]: @@ -66,7 +66,7 @@ def test_capabilities(client_server): def test_document_formatting_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - FORMATTING, + TEXT_DOCUMENT_FORMATTING, DocumentFormattingParams( text_document=TextDocumentIdentifier(uri="file://return.list"), options=FormattingOptions( @@ -81,18 +81,18 @@ def test_document_formatting_return_list(client_server): assert response - assert response[0]["newText"] == "text" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].new_text == "text" + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_document_formatting_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - FORMATTING, + TEXT_DOCUMENT_FORMATTING, DocumentFormattingParams( text_document=TextDocumentIdentifier(uri="file://return.none"), options=FormattingOptions( diff --git a/tests/lsp/test_hover.py b/tests/lsp/test_hover.py index 3adae7ad..7e320a8b 100644 --- a/tests/lsp/test_hover.py +++ b/tests/lsp/test_hover.py @@ -17,12 +17,12 @@ from typing import Optional -from pygls.lsp.methods import HOVER -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_HOVER +from lsprotocol.types import ( Hover, HoverOptions, HoverParams, - MarkedString, + MarkedString_Type1, MarkupContent, MarkupKind, Position, @@ -38,7 +38,7 @@ def __init__(self): super().__init__() @self.server.feature( - HOVER, + TEXT_DOCUMENT_HOVER, HoverOptions(), ) def f(params: HoverParams) -> Optional[Hover]: @@ -50,7 +50,7 @@ def f(params: HoverParams) -> Optional[Hover]: return { "file://return.marked_string": Hover( range=range, - contents=MarkedString( + contents=MarkedString_Type1( language="language", value="value", ), @@ -58,7 +58,7 @@ def f(params: HoverParams) -> Optional[Hover]: "file://return.marked_string_list": Hover( range=range, contents=[ - MarkedString( + MarkedString_Type1( language="language", value="value", ), @@ -85,7 +85,7 @@ def test_capabilities(client_server): def test_hover_return_marked_string(client_server): client, _ = client_server response = client.lsp.send_request( - HOVER, + TEXT_DOCUMENT_HOVER, HoverParams( text_document=TextDocumentIdentifier( uri="file://return.marked_string"), @@ -95,20 +95,20 @@ def test_hover_return_marked_string(client_server): assert response - assert response["contents"]["language"] == "language" - assert response["contents"]["value"] == "value" + assert response.contents.language == "language" + assert response.contents.value == "value" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 @ConfiguredLS.decorate() def test_hover_return_marked_string_list(client_server): client, _ = client_server response = client.lsp.send_request( - HOVER, + TEXT_DOCUMENT_HOVER, HoverParams( text_document=TextDocumentIdentifier( uri="file://return.marked_string_list" @@ -119,21 +119,21 @@ def test_hover_return_marked_string_list(client_server): assert response - assert response["contents"][0]["language"] == "language" - assert response["contents"][0]["value"] == "value" - assert response["contents"][1] == "str type" + assert response.contents[0].language == "language" + assert response.contents[0].value == "value" + assert response.contents[1] == "str type" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 @ConfiguredLS.decorate() def test_hover_return_markup_content(client_server): client, _ = client_server response = client.lsp.send_request( - HOVER, + TEXT_DOCUMENT_HOVER, HoverParams( text_document=TextDocumentIdentifier( uri="file://return.markup_content" @@ -144,10 +144,10 @@ def test_hover_return_markup_content(client_server): assert response - assert response["contents"]["kind"] == MarkupKind.Markdown - assert response["contents"]["value"] == "value" + assert response.contents.kind == MarkupKind.Markdown + assert response.contents.value == "value" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 diff --git a/tests/lsp/test_implementation.py b/tests/lsp/test_implementation.py index 88014124..9a8e690c 100644 --- a/tests/lsp/test_implementation.py +++ b/tests/lsp/test_implementation.py @@ -17,8 +17,8 @@ from typing import List, Optional, Union -from pygls.lsp.methods import IMPLEMENTATION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_IMPLEMENTATION +from lsprotocol.types import ( ImplementationOptions, ImplementationParams, Location, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - IMPLEMENTATION, + TEXT_DOCUMENT_IMPLEMENTATION, ImplementationOptions(), ) def f( @@ -85,7 +85,7 @@ def test_capabilities(client_server): def test_type_definition_return_location(client_server): client, _ = client_server response = client.lsp.send_request( - IMPLEMENTATION, + TEXT_DOCUMENT_IMPLEMENTATION, ImplementationParams( text_document=TextDocumentIdentifier( uri="file://return.location"), @@ -93,19 +93,19 @@ def test_type_definition_return_location(client_server): ), ).result() - assert response["uri"] == "uri" + assert response.uri == "uri" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 @ConfiguredLS.decorate() def test_type_definition_return_location_list(client_server): client, _ = client_server response = client.lsp.send_request( - IMPLEMENTATION, + TEXT_DOCUMENT_IMPLEMENTATION, ImplementationParams( text_document=TextDocumentIdentifier( uri="file://return.location_list"), @@ -113,19 +113,19 @@ def test_type_definition_return_location_list(client_server): ), ).result() - assert response[0]["uri"] == "uri" + assert response[0].uri == "uri" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_type_definition_return_location_link_list(client_server): client, _ = client_server response = client.lsp.send_request( - IMPLEMENTATION, + TEXT_DOCUMENT_IMPLEMENTATION, ImplementationParams( text_document=TextDocumentIdentifier( uri="file://return.location_link_list" @@ -134,29 +134,29 @@ def test_type_definition_return_location_link_list(client_server): ), ).result() - assert response[0]["targetUri"] == "uri" + assert response[0].target_uri == "uri" - assert response[0]["targetRange"]["start"]["line"] == 0 - assert response[0]["targetRange"]["start"]["character"] == 0 - assert response[0]["targetRange"]["end"]["line"] == 1 - assert response[0]["targetRange"]["end"]["character"] == 1 + assert response[0].target_range.start.line == 0 + assert response[0].target_range.start.character == 0 + assert response[0].target_range.end.line == 1 + assert response[0].target_range.end.character == 1 - assert response[0]["targetSelectionRange"]["start"]["line"] == 0 - assert response[0]["targetSelectionRange"]["start"]["character"] == 0 - assert response[0]["targetSelectionRange"]["end"]["line"] == 2 - assert response[0]["targetSelectionRange"]["end"]["character"] == 2 + assert response[0].target_selection_range.start.line == 0 + assert response[0].target_selection_range.start.character == 0 + assert response[0].target_selection_range.end.line == 2 + assert response[0].target_selection_range.end.character == 2 - assert response[0]["originSelectionRange"]["start"]["line"] == 0 - assert response[0]["originSelectionRange"]["start"]["character"] == 0 - assert response[0]["originSelectionRange"]["end"]["line"] == 3 - assert response[0]["originSelectionRange"]["end"]["character"] == 3 + assert response[0].origin_selection_range.start.line == 0 + assert response[0].origin_selection_range.start.character == 0 + assert response[0].origin_selection_range.end.line == 3 + assert response[0].origin_selection_range.end.character == 3 @ConfiguredLS.decorate() def test_type_definition_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - IMPLEMENTATION, + TEXT_DOCUMENT_IMPLEMENTATION, ImplementationParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_linked_editing_range.py b/tests/lsp/test_linked_editing_range.py index 7da35029..8b00644c 100644 --- a/tests/lsp/test_linked_editing_range.py +++ b/tests/lsp/test_linked_editing_range.py @@ -17,8 +17,8 @@ from typing import Optional -from pygls.lsp.methods import TEXT_DOCUMENT_LINKED_EDITING_RANGE -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_LINKED_EDITING_RANGE +from lsprotocol.types import ( LinkedEditingRangeOptions, LinkedEditingRangeParams, LinkedEditingRanges, @@ -81,15 +81,15 @@ def test_linked_editing_ranges_return_ranges(client_server): assert response - assert response["ranges"][0]["start"]["line"] == 0 - assert response["ranges"][0]["start"]["character"] == 0 - assert response["ranges"][0]["end"]["line"] == 1 - assert response["ranges"][0]["end"]["character"] == 1 - assert response["ranges"][1]["start"]["line"] == 1 - assert response["ranges"][1]["start"]["character"] == 1 - assert response["ranges"][1]["end"]["line"] == 2 - assert response["ranges"][1]["end"]["character"] == 2 - assert response["wordPattern"] == "pattern" + assert response.ranges[0].start.line == 0 + assert response.ranges[0].start.character == 0 + assert response.ranges[0].end.line == 1 + assert response.ranges[0].end.character == 1 + assert response.ranges[1].start.line == 1 + assert response.ranges[1].start.character == 1 + assert response.ranges[1].end.line == 2 + assert response.ranges[1].end.character == 2 + assert response.word_pattern == "pattern" @ConfiguredLS.decorate() diff --git a/tests/lsp/test_moniker.py b/tests/lsp/test_moniker.py index 3784a9af..09b962d6 100644 --- a/tests/lsp/test_moniker.py +++ b/tests/lsp/test_moniker.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import TEXT_DOCUMENT_MONIKER -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_MONIKER +from lsprotocol.types import ( Moniker, MonikerKind, MonikerOptions, @@ -74,10 +74,10 @@ def test_moniker_return_list(client_server): assert response - assert response[0]["scheme"] == "test_scheme" - assert response[0]["identifier"] == "test_identifier" - assert response[0]["unique"] == "global" - assert response[0]["kind"] == "local" + assert response[0].scheme == "test_scheme" + assert response[0].identifier == "test_identifier" + assert response[0].unique == UniquenessLevel.Global + assert response[0].kind == MonikerKind.Local @ConfiguredLS.decorate() diff --git a/tests/lsp/test_on_type_formatting.py b/tests/lsp/test_on_type_formatting.py index 42494a9c..b0f041e8 100644 --- a/tests/lsp/test_on_type_formatting.py +++ b/tests/lsp/test_on_type_formatting.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import ON_TYPE_FORMATTING -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_ON_TYPE_FORMATTING +from lsprotocol.types import ( DocumentOnTypeFormattingOptions, DocumentOnTypeFormattingParams, FormattingOptions, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - ON_TYPE_FORMATTING, + TEXT_DOCUMENT_ON_TYPE_FORMATTING, DocumentOnTypeFormattingOptions( first_trigger_character=":", more_trigger_character=[",", "."], @@ -83,7 +83,7 @@ def test_capabilities(client_server): def test_on_type_formatting_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - ON_TYPE_FORMATTING, + TEXT_DOCUMENT_ON_TYPE_FORMATTING, DocumentOnTypeFormattingParams( text_document=TextDocumentIdentifier(uri="file://return.list"), position=Position(line=0, character=0), @@ -100,18 +100,18 @@ def test_on_type_formatting_return_list(client_server): assert response - assert response[0]["newText"] == "text" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].new_text == "text" + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_on_type_formatting_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - ON_TYPE_FORMATTING, + TEXT_DOCUMENT_ON_TYPE_FORMATTING, DocumentOnTypeFormattingParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_prepare_rename.py b/tests/lsp/test_prepare_rename.py index 7a6e13f8..11dae9c4 100644 --- a/tests/lsp/test_prepare_rename.py +++ b/tests/lsp/test_prepare_rename.py @@ -17,10 +17,11 @@ from typing import Optional, Union -from pygls.lsp.methods import PREPARE_RENAME -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_PREPARE_RENAME +from lsprotocol.types import ( Position, - PrepareRename, + PrepareRenameResult, + PrepareRenameResult_Type1, PrepareRenameParams, Range, TextDocumentIdentifier, @@ -33,16 +34,16 @@ class ConfiguredLS(ClientServer): def __init__(self): super().__init__() - @self.server.feature(PREPARE_RENAME) + @self.server.feature(TEXT_DOCUMENT_PREPARE_RENAME) def f( params: PrepareRenameParams - ) -> Optional[Union[Range, PrepareRename]]: + ) -> Optional[Union[Range, PrepareRenameResult]]: return { # type: ignore "file://return.range": Range( start=Position(line=0, character=0), end=Position(line=1, character=1), ), - "file://return.prepare_rename": PrepareRename( + "file://return.prepare_rename": PrepareRenameResult_Type1( range=Range( start=Position(line=0, character=0), end=Position(line=1, character=1), @@ -61,7 +62,7 @@ def test_capabilities(client_server): def test_prepare_rename_return_range(client_server): client, _ = client_server response = client.lsp.send_request( - PREPARE_RENAME, + TEXT_DOCUMENT_PREPARE_RENAME, PrepareRenameParams( text_document=TextDocumentIdentifier( uri="file://return.range"), @@ -71,17 +72,17 @@ def test_prepare_rename_return_range(client_server): assert response - assert response["start"]["line"] == 0 - assert response["start"]["character"] == 0 - assert response["end"]["line"] == 1 - assert response["end"]["character"] == 1 + assert response.start.line == 0 + assert response.start.character == 0 + assert response.end.line == 1 + assert response.end.character == 1 @ConfiguredLS.decorate() def test_prepare_rename_return_prepare_rename(client_server): client, _ = client_server response = client.lsp.send_request( - PREPARE_RENAME, + TEXT_DOCUMENT_PREPARE_RENAME, PrepareRenameParams( text_document=TextDocumentIdentifier( uri="file://return.prepare_rename" @@ -92,18 +93,18 @@ def test_prepare_rename_return_prepare_rename(client_server): assert response - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 - assert response["placeholder"] == "placeholder" + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 + assert response.placeholder == "placeholder" @ConfiguredLS.decorate() def test_prepare_rename_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - PREPARE_RENAME, + TEXT_DOCUMENT_PREPARE_RENAME, PrepareRenameParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_progress.py b/tests/lsp/test_progress.py index e58117cc..2f27fa9c 100644 --- a/tests/lsp/test_progress.py +++ b/tests/lsp/test_progress.py @@ -18,17 +18,17 @@ from typing import List, Optional import time -from pygls.lsp.methods import CODE_LENS, PROGRESS_NOTIFICATION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_CODE_LENS, PROGRESS +from lsprotocol.types import ( CodeLens, CodeLensParams, CodeLensOptions, + ProgressParams, TextDocumentIdentifier, WorkDoneProgressBegin, WorkDoneProgressEnd, WorkDoneProgressReport, ) -from pygls.lsp.types.basic_structures import ProgressParams from ..conftest import ClientServer @@ -41,25 +41,25 @@ def __init__(self): self.client.notifications: List[ProgressParams] = [] @self.server.feature( - CODE_LENS, + TEXT_DOCUMENT_CODE_LENS, CodeLensOptions(resolve_provider=False, - work_done_progress=PROGRESS_TOKEN), + work_done_progress=True), ) def f1(params: CodeLensParams) -> Optional[List[CodeLens]]: self.server.lsp.progress.begin( PROGRESS_TOKEN, WorkDoneProgressBegin( - title="starting", percentage=0) + kind='begin', title="starting", percentage=0) ) self.server.lsp.progress.report( PROGRESS_TOKEN, - WorkDoneProgressReport(message="doing", percentage=50), + WorkDoneProgressReport(kind='report', message="doing", percentage=50), ) self.server.lsp.progress.end( - PROGRESS_TOKEN, WorkDoneProgressEnd(message="done") + PROGRESS_TOKEN, WorkDoneProgressEnd(kind='end', message="done") ) return None - @self.client.feature(PROGRESS_NOTIFICATION) + @self.client.feature(PROGRESS) def f2(params): self.client.notifications.append(params) @@ -71,14 +71,14 @@ def test_capabilities(client_server): provider = capabilities.code_lens_provider assert provider - assert provider.work_done_progress == PROGRESS_TOKEN + assert provider.work_done_progress @ConfiguredLS.decorate() def test_progress_notifications(client_server): client, _ = client_server client.lsp.send_request( - CODE_LENS, + TEXT_DOCUMENT_CODE_LENS, CodeLensParams( text_document=TextDocumentIdentifier(uri="file://return.none"), work_done_token=PROGRESS_TOKEN, diff --git a/tests/lsp/test_range_formatting.py b/tests/lsp/test_range_formatting.py index 64cdb677..7e8c480b 100644 --- a/tests/lsp/test_range_formatting.py +++ b/tests/lsp/test_range_formatting.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import RANGE_FORMATTING -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_RANGE_FORMATTING +from lsprotocol.types import ( DocumentRangeFormattingOptions, DocumentRangeFormattingParams, FormattingOptions, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - RANGE_FORMATTING, + TEXT_DOCUMENT_RANGE_FORMATTING, DocumentRangeFormattingOptions(), ) def f( @@ -68,7 +68,7 @@ def test_capabilities(client_server): def test_range_formatting_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - RANGE_FORMATTING, + TEXT_DOCUMENT_RANGE_FORMATTING, DocumentRangeFormattingParams( text_document=TextDocumentIdentifier(uri="file://return.list"), range=Range( @@ -87,18 +87,18 @@ def test_range_formatting_return_list(client_server): assert response - assert response[0]["newText"] == "text" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].new_text == "text" + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_range_formatting_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - RANGE_FORMATTING, + TEXT_DOCUMENT_RANGE_FORMATTING, DocumentRangeFormattingParams( text_document=TextDocumentIdentifier(uri="file://return.none"), range=Range( diff --git a/tests/lsp/test_references.py b/tests/lsp/test_references.py index e874c0d6..5867e35d 100644 --- a/tests/lsp/test_references.py +++ b/tests/lsp/test_references.py @@ -17,8 +17,8 @@ from typing import List, Optional -from pygls.lsp.methods import REFERENCES -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_REFERENCES +from lsprotocol.types import ( Location, Position, Range, @@ -36,7 +36,7 @@ def __init__(self): super().__init__() @self.server.feature( - REFERENCES, + TEXT_DOCUMENT_REFERENCES, ReferenceOptions(), ) def f(params: ReferenceParams) -> Optional[List[Location]]: @@ -66,7 +66,7 @@ def test_capabilities(client_server): def test_references_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - REFERENCES, + TEXT_DOCUMENT_REFERENCES, ReferenceParams( text_document=TextDocumentIdentifier(uri="file://return.list"), position=Position(line=0, character=0), @@ -78,19 +78,19 @@ def test_references_return_list(client_server): assert response - assert response[0]["uri"] == "uri" + assert response[0].uri == "uri" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_references_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - REFERENCES, + TEXT_DOCUMENT_REFERENCES, ReferenceParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_rename.py b/tests/lsp/test_rename.py index 1db95bcb..a4e5952a 100644 --- a/tests/lsp/test_rename.py +++ b/tests/lsp/test_rename.py @@ -17,8 +17,8 @@ from typing import Optional -from pygls.lsp.methods import RENAME -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_RENAME +from lsprotocol.types import ( CreateFile, CreateFileOptions, DeleteFile, @@ -75,7 +75,7 @@ ], ), CreateFile( - kind=ResourceOperationKind.Create, + kind=ResourceOperationKind.Create.value, uri="create file", options=CreateFileOptions( overwrite=True, @@ -83,7 +83,7 @@ ), ), RenameFile( - kind=ResourceOperationKind.Rename, + kind=ResourceOperationKind.Rename.value, old_uri="rename old uri", new_uri="rename new uri", options=RenameFileOptions( @@ -92,11 +92,11 @@ ), ), DeleteFile( - kind=ResourceOperationKind.Delete, + kind=ResourceOperationKind.Delete.value, uri="delete file", options=DeleteFileOptions( recursive=True, - ignore_if_exists=True, + ignore_if_not_exists=True, ), ), ], } @@ -107,7 +107,7 @@ def __init__(self): super().__init__() @self.server.feature( - RENAME, + TEXT_DOCUMENT_RENAME, RenameOptions(prepare_provider=True), ) def f(params: RenameParams) -> Optional[WorkspaceEdit]: @@ -130,7 +130,7 @@ def test_capabilities(client_server): def test_rename_return_workspace_edit(client_server): client, _ = client_server response = client.lsp.send_request( - RENAME, + TEXT_DOCUMENT_RENAME, RenameParams( text_document=TextDocumentIdentifier( uri="file://return.workspace_edit" @@ -142,55 +142,55 @@ def test_rename_return_workspace_edit(client_server): assert response - changes = response["changes"]["uri1"] - assert changes[0]["newText"] == "text1" - assert changes[0]["range"]["start"]["line"] == 0 - assert changes[0]["range"]["start"]["character"] == 0 - assert changes[0]["range"]["end"]["line"] == 1 - assert changes[0]["range"]["end"]["character"] == 1 - - assert changes[1]["newText"] == "text2" - assert changes[1]["range"]["start"]["line"] == 1 - assert changes[1]["range"]["start"]["character"] == 1 - assert changes[1]["range"]["end"]["line"] == 2 - assert changes[1]["range"]["end"]["character"] == 2 - - changes = response["documentChanges"] - assert changes[0]["textDocument"]["uri"] == "uri" - assert changes[0]["textDocument"]["version"] == 3 - assert changes[0]["edits"][0]["newText"] == "text3" - assert changes[0]["edits"][0]["range"]["start"]["line"] == 2 + changes = response.changes["uri1"] + assert changes[0].new_text == "text1" + assert changes[0].range.start.line == 0 + assert changes[0].range.start.character == 0 + assert changes[0].range.end.line == 1 + assert changes[0].range.end.character == 1 + + assert changes[1].new_text == "text2" + assert changes[1].range.start.line == 1 + assert changes[1].range.start.character == 1 + assert changes[1].range.end.line == 2 + assert changes[1].range.end.character == 2 + + changes = response.document_changes + assert changes[0].text_document.uri == "uri" + assert changes[0].text_document.version == 3 + assert changes[0].edits[0].new_text == "text3" + assert changes[0].edits[0].range.start.line == 2 assert ( - changes[0]["edits"][0]["range"]["start"]["character"] + changes[0].edits[0].range.start.character == 2 ) - assert changes[0]["edits"][0]["range"]["end"]["line"] == 3 + assert changes[0].edits[0].range.end.line == 3 assert ( - changes[0]["edits"][0]["range"]["end"]["character"] == 3 + changes[0].edits[0].range.end.character == 3 ) - assert changes[1]["kind"] == ResourceOperationKind.Create - assert changes[1]["uri"] == "create file" - assert changes[1]["options"]["ignoreIfExists"] - assert changes[1]["options"]["overwrite"] + assert changes[1].kind == ResourceOperationKind.Create.value + assert changes[1].uri == "create file" + assert changes[1].options.ignore_if_exists + assert changes[1].options.overwrite - assert changes[2]["kind"] == ResourceOperationKind.Rename - assert changes[2]["newUri"] == "rename new uri" - assert changes[2]["oldUri"] == "rename old uri" - assert changes[2]["options"]["ignoreIfExists"] - assert changes[2]["options"]["overwrite"] + assert changes[2].kind == ResourceOperationKind.Rename.value + assert changes[2].new_uri == "rename new uri" + assert changes[2].old_uri == "rename old uri" + assert changes[2].options.ignore_if_exists + assert changes[2].options.overwrite - assert changes[3]["kind"] == ResourceOperationKind.Delete - assert changes[3]["uri"] == "delete file" - assert changes[3]["options"]["ignoreIfExists"] - assert changes[3]["options"]["recursive"] + assert changes[3].kind == ResourceOperationKind.Delete.value + assert changes[3].uri == "delete file" + assert changes[3].options.ignore_if_not_exists + assert changes[3].options.recursive @ConfiguredLS.decorate() def test_rename_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - RENAME, + TEXT_DOCUMENT_RENAME, RenameParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_selection_range.py b/tests/lsp/test_selection_range.py index 1beaea9e..5f669a20 100644 --- a/tests/lsp/test_selection_range.py +++ b/tests/lsp/test_selection_range.py @@ -16,8 +16,8 @@ ############################################################################ from typing import List, Optional -from pygls.lsp.methods import SELECTION_RANGE -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_SELECTION_RANGE +from lsprotocol.types import ( Position, Range, SelectionRange, @@ -34,7 +34,7 @@ def __init__(self): super().__init__() @self.server.feature( - SELECTION_RANGE, + TEXT_DOCUMENT_SELECTION_RANGE, SelectionRangeOptions(), ) def f(params: SelectionRangeParams) -> Optional[List[SelectionRange]]: @@ -71,9 +71,9 @@ def test_capabilities(client_server): def test_selection_range_return_list(client_server): client, _ = client_server response = client.lsp.send_request( - SELECTION_RANGE, + TEXT_DOCUMENT_SELECTION_RANGE, SelectionRangeParams( - query="query", + # query="query", text_document=TextDocumentIdentifier(uri="file://return.list"), positions=[Position(line=0, character=0)], ), @@ -82,26 +82,26 @@ def test_selection_range_return_list(client_server): assert response root = response[0] - assert root["range"]["start"]["line"] == 0 - assert root["range"]["start"]["character"] == 0 - assert root["range"]["end"]["line"] == 10 - assert root["range"]["end"]["character"] == 10 - assert "parent" not in root + assert root.range.start.line == 0 + assert root.range.start.character == 0 + assert root.range.end.line == 10 + assert root.range.end.character == 10 + assert root.parent is None - assert response[1]["range"]["start"]["line"] == 0 - assert response[1]["range"]["start"]["character"] == 0 - assert response[1]["range"]["end"]["line"] == 1 - assert response[1]["range"]["end"]["character"] == 1 - assert response[1]["parent"] == root + assert response[1].range.start.line == 0 + assert response[1].range.start.character == 0 + assert response[1].range.end.line == 1 + assert response[1].range.end.character == 1 + assert response[1].parent == root @ConfiguredLS.decorate() def test_selection_range_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - SELECTION_RANGE, + TEXT_DOCUMENT_SELECTION_RANGE, SelectionRangeParams( - query="query", + # query="query", text_document=TextDocumentIdentifier(uri="file://return.none"), positions=[Position(line=0, character=0)], ), diff --git a/tests/lsp/test_signature_help.py b/tests/lsp/test_signature_help.py index 350ea362..3c3292c4 100644 --- a/tests/lsp/test_signature_help.py +++ b/tests/lsp/test_signature_help.py @@ -17,8 +17,10 @@ from typing import Optional -from pygls.lsp.methods import SIGNATURE_HELP -from pygls.lsp.types import ( +import pytest + +from lsprotocol.types import TEXT_DOCUMENT_SIGNATURE_HELP +from lsprotocol.types import ( ParameterInformation, Position, SignatureHelp, @@ -38,7 +40,7 @@ def __init__(self): super().__init__() @self.server.feature( - SIGNATURE_HELP, + TEXT_DOCUMENT_SIGNATURE_HELP, SignatureHelpOptions( trigger_characters=["a", "b"], retrigger_characters=["c", "d"], @@ -78,10 +80,11 @@ def test_capabilities(client_server): @ConfiguredLS.decorate() +@pytest.mark.skip def test_signature_help_return_signature_help(client_server): client, _ = client_server response = client.lsp.send_request( - SIGNATURE_HELP, + TEXT_DOCUMENT_SIGNATURE_HELP, SignatureHelpParams( text_document=TextDocumentIdentifier( uri="file://return.signature_help" @@ -126,10 +129,11 @@ def test_signature_help_return_signature_help(client_server): @ConfiguredLS.decorate() +@pytest.mark.skip def test_signature_help_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - SIGNATURE_HELP, + TEXT_DOCUMENT_SIGNATURE_HELP, SignatureHelpParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/lsp/test_type_definition.py b/tests/lsp/test_type_definition.py index 37e1d1e6..da437b63 100644 --- a/tests/lsp/test_type_definition.py +++ b/tests/lsp/test_type_definition.py @@ -16,8 +16,8 @@ ############################################################################ from typing import List, Optional, Union -from pygls.lsp.methods import TYPE_DEFINITION -from pygls.lsp.types import ( +from lsprotocol.types import TEXT_DOCUMENT_TYPE_DEFINITION +from lsprotocol.types import ( Location, LocationLink, Position, @@ -35,7 +35,7 @@ def __init__(self): super().__init__() @self.server.feature( - TYPE_DEFINITION, + TEXT_DOCUMENT_TYPE_DEFINITION, TypeDefinitionOptions(), ) def f( @@ -84,7 +84,7 @@ def test_capabilities(client_server): def test_type_definition_return_location(client_server): client, _ = client_server response = client.lsp.send_request( - TYPE_DEFINITION, + TEXT_DOCUMENT_TYPE_DEFINITION, TypeDefinitionParams( text_document=TextDocumentIdentifier( uri="file://return.location"), @@ -92,19 +92,19 @@ def test_type_definition_return_location(client_server): ), ).result() - assert response["uri"] == "uri" + assert response.uri == "uri" - assert response["range"]["start"]["line"] == 0 - assert response["range"]["start"]["character"] == 0 - assert response["range"]["end"]["line"] == 1 - assert response["range"]["end"]["character"] == 1 + assert response.range.start.line == 0 + assert response.range.start.character == 0 + assert response.range.end.line == 1 + assert response.range.end.character == 1 @ConfiguredLS.decorate() def test_type_definition_return_location_list(client_server): client, _ = client_server response = client.lsp.send_request( - TYPE_DEFINITION, + TEXT_DOCUMENT_TYPE_DEFINITION, TypeDefinitionParams( text_document=TextDocumentIdentifier( uri="file://return.location_list"), @@ -112,19 +112,19 @@ def test_type_definition_return_location_list(client_server): ), ).result() - assert response[0]["uri"] == "uri" + assert response[0].uri == "uri" - assert response[0]["range"]["start"]["line"] == 0 - assert response[0]["range"]["start"]["character"] == 0 - assert response[0]["range"]["end"]["line"] == 1 - assert response[0]["range"]["end"]["character"] == 1 + assert response[0].range.start.line == 0 + assert response[0].range.start.character == 0 + assert response[0].range.end.line == 1 + assert response[0].range.end.character == 1 @ConfiguredLS.decorate() def test_type_definition_return_location_link_list(client_server): client, _ = client_server response = client.lsp.send_request( - TYPE_DEFINITION, + TEXT_DOCUMENT_TYPE_DEFINITION, TypeDefinitionParams( text_document=TextDocumentIdentifier( uri="file://return.location_link_list" @@ -133,29 +133,29 @@ def test_type_definition_return_location_link_list(client_server): ), ).result() - assert response[0]["targetUri"] == "uri" + assert response[0].target_uri == "uri" - assert response[0]["targetRange"]["start"]["line"] == 0 - assert response[0]["targetRange"]["start"]["character"] == 0 - assert response[0]["targetRange"]["end"]["line"] == 1 - assert response[0]["targetRange"]["end"]["character"] == 1 + assert response[0].target_range.start.line == 0 + assert response[0].target_range.start.character == 0 + assert response[0].target_range.end.line == 1 + assert response[0].target_range.end.character == 1 - assert response[0]["targetSelectionRange"]["start"]["line"] == 0 - assert response[0]["targetSelectionRange"]["start"]["character"] == 0 - assert response[0]["targetSelectionRange"]["end"]["line"] == 2 - assert response[0]["targetSelectionRange"]["end"]["character"] == 2 + assert response[0].target_selection_range.start.line == 0 + assert response[0].target_selection_range.start.character == 0 + assert response[0].target_selection_range.end.line == 2 + assert response[0].target_selection_range.end.character == 2 - assert response[0]["originSelectionRange"]["start"]["line"] == 0 - assert response[0]["originSelectionRange"]["start"]["character"] == 0 - assert response[0]["originSelectionRange"]["end"]["line"] == 3 - assert response[0]["originSelectionRange"]["end"]["character"] == 3 + assert response[0].origin_selection_range.start.line == 0 + assert response[0].origin_selection_range.start.character == 0 + assert response[0].origin_selection_range.end.line == 3 + assert response[0].origin_selection_range.end.character == 3 @ConfiguredLS.decorate() def test_type_definition_return_none(client_server): client, _ = client_server response = client.lsp.send_request( - TYPE_DEFINITION, + TEXT_DOCUMENT_TYPE_DEFINITION, TypeDefinitionParams( text_document=TextDocumentIdentifier(uri="file://return.none"), position=Position(line=0, character=0), diff --git a/tests/test_document.py b/tests/test_document.py index 046ea7c7..5c3c36b8 100644 --- a/tests/test_document.py +++ b/tests/test_document.py @@ -18,10 +18,10 @@ ############################################################################ import re -from pygls.lsp.types import ( +from lsprotocol.types import ( Position, Range, - TextDocumentContentChangeEvent, + TextDocumentContentChangeEvent_Type1, TextDocumentSyncKind, ) from pygls.workspace import ( @@ -36,7 +36,7 @@ def test_document_empty_edit(): doc = Document("file:///uri", "") - change = TextDocumentContentChangeEvent( + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=0, character=0), end=Position(line=0, character=0) @@ -52,7 +52,7 @@ def test_document_end_of_file_edit(): old = ["print 'a'\n", "print 'b'\n"] doc = Document("file:///uri", "".join(old)) - change = TextDocumentContentChangeEvent( + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=2, character=0), end=Position(line=2, character=0) @@ -72,8 +72,8 @@ def test_document_end_of_file_edit(): def test_document_full_edit(): old = ["def hello(a, b):\n", " print a\n", " print b\n"] doc = Document("file:///uri", "".join(old), - sync_kind=TextDocumentSyncKind.FULL) - change = TextDocumentContentChangeEvent( + sync_kind=TextDocumentSyncKind.Full) + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=1, character=4), end=Position(line=2, character=11) @@ -86,8 +86,8 @@ def test_document_full_edit(): assert doc.lines == ["print a, b"] doc = Document("file:///uri", "".join(old), - sync_kind=TextDocumentSyncKind.FULL) - change = TextDocumentContentChangeEvent(range=None, text="print a, b") + sync_kind=TextDocumentSyncKind.Full) + change = TextDocumentContentChangeEvent_Type1(range=None, text="print a, b") doc.apply_change(change) assert doc.lines == ["print a, b"] @@ -95,7 +95,7 @@ def test_document_full_edit(): def test_document_line_edit(): doc = Document("file:///uri", "itshelloworld") - change = TextDocumentContentChangeEvent( + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=0, character=3), end=Position(line=0, character=8) @@ -115,9 +115,9 @@ def test_document_lines(doc): def test_document_multiline_edit(): old = ["def hello(a, b):\n", " print a\n", " print b\n"] doc = Document( - "file:///uri", "".join(old), sync_kind=TextDocumentSyncKind.INCREMENTAL + "file:///uri", "".join(old), sync_kind=TextDocumentSyncKind.Incremental ) - change = TextDocumentContentChangeEvent( + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=1, character=4), end=Position(line=2, character=11) @@ -130,9 +130,9 @@ def test_document_multiline_edit(): assert doc.lines == ["def hello(a, b):\n", " print a, b\n"] doc = Document( - "file:///uri", "".join(old), sync_kind=TextDocumentSyncKind.INCREMENTAL + "file:///uri", "".join(old), sync_kind=TextDocumentSyncKind.Incremental ) - change = TextDocumentContentChangeEvent( + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=1, character=4), end=Position(line=2, character=11) @@ -147,8 +147,8 @@ def test_document_multiline_edit(): def test_document_no_edit(): old = ["def hello(a, b):\n", " print a\n", " print b\n"] doc = Document("file:///uri", "".join(old), - sync_kind=TextDocumentSyncKind.NONE) - change = TextDocumentContentChangeEvent( + sync_kind=TextDocumentSyncKind.None_) + change = TextDocumentContentChangeEvent_Type1( range=Range( start=Position(line=1, character=4), end=Position(line=2, character=11) diff --git a/tests/test_feature_manager.py b/tests/test_feature_manager.py index 764b3e86..020bf6bf 100644 --- a/tests/test_feature_manager.py +++ b/tests/test_feature_manager.py @@ -23,8 +23,7 @@ ValidationError, ) from pygls.feature_manager import has_ls_param_or_annotation, wrap_with_server -from pygls.lsp import methods -from pygls.lsp.types import CompletionOptions +from lsprotocol import types def test_has_ls_param_or_annotation(): @@ -72,20 +71,20 @@ def cmd2(): def test_register_feature_with_valid_options(feature_manager): - options = CompletionOptions(trigger_characters=["!"]) + options = types.CompletionOptions(trigger_characters=["!"]) - @feature_manager.feature(methods.COMPLETION, options) + @feature_manager.feature(types.TEXT_DOCUMENT_COMPLETION, options) def completions(): pass reg_features = feature_manager.features.keys() reg_feature_options = feature_manager.feature_options.keys() - assert methods.COMPLETION in reg_features - assert methods.COMPLETION in reg_feature_options + assert types.TEXT_DOCUMENT_COMPLETION in reg_features + assert types.TEXT_DOCUMENT_COMPLETION in reg_feature_options - assert feature_manager.features[methods.COMPLETION] is completions - assert feature_manager.feature_options[methods.COMPLETION] is options + assert feature_manager.features[types.TEXT_DOCUMENT_COMPLETION] is completions + assert feature_manager.feature_options[types.TEXT_DOCUMENT_COMPLETION] is options def test_register_feature_with_wrong_options(feature_manager): @@ -95,32 +94,32 @@ class Options: with pytest.raises( TypeError, match=( - f'Options of method "{methods.COMPLETION}" should be instance of type ' + f'Options of method "{types.TEXT_DOCUMENT_COMPLETION}" should be instance of type ' "" ), # noqa ): - @feature_manager.feature(methods.COMPLETION, Options()) + @feature_manager.feature(types.TEXT_DOCUMENT_COMPLETION, Options()) def completions(): pass def test_register_features(feature_manager): - @feature_manager.feature(methods.COMPLETION) + @feature_manager.feature(types.TEXT_DOCUMENT_COMPLETION) def completions(): pass - @feature_manager.feature(methods.CODE_LENS) + @feature_manager.feature(types.TEXT_DOCUMENT_CODE_LENS) def code_lens(): pass reg_features = feature_manager.features.keys() - assert methods.COMPLETION in reg_features - assert methods.CODE_LENS in reg_features + assert types.TEXT_DOCUMENT_COMPLETION in reg_features + assert types.TEXT_DOCUMENT_CODE_LENS in reg_features - assert feature_manager.features[methods.COMPLETION] is completions - assert feature_manager.features[methods.CODE_LENS] is code_lens + assert feature_manager.features[types.TEXT_DOCUMENT_COMPLETION] is completions + assert feature_manager.features[types.TEXT_DOCUMENT_CODE_LENS] is code_lens def test_register_same_command_twice_error(feature_manager): @@ -140,11 +139,11 @@ def test_register_same_feature_twice_error(feature_manager): with pytest.raises(FeatureAlreadyRegisteredError): - @feature_manager.feature(methods.CODE_ACTION) + @feature_manager.feature(types.TEXT_DOCUMENT_CODE_ACTION) def code_action1(): # pylint: disable=unused-variable pass - @feature_manager.feature(methods.CODE_ACTION) + @feature_manager.feature(types.TEXT_DOCUMENT_CODE_ACTION) def code_action2(): # pylint: disable=unused-variable pass diff --git a/tests/test_language_server.py b/tests/test_language_server.py index 98be7cbf..2a4a5684 100644 --- a/tests/test_language_server.py +++ b/tests/test_language_server.py @@ -20,12 +20,12 @@ import pytest from pygls import IS_PYODIDE -from pygls.lsp.methods import ( +from lsprotocol.types import ( INITIALIZE, TEXT_DOCUMENT_DID_OPEN, WORKSPACE_EXECUTE_COMMAND, ) -from pygls.lsp.types import ( +from lsprotocol.types import ( ClientCapabilities, DidOpenTextDocumentParams, ExecuteCommandParams, @@ -54,16 +54,16 @@ def test_bf_initialize(client_server): response = client.lsp.send_request( INITIALIZE, - { - "processId": process_id, - "rootUri": root_uri, - "capabilities": ClientCapabilities(), - }, + InitializeParams( + process_id=process_id, + root_uri=root_uri, + capabilities=ClientCapabilities(), + ), ).result() assert server.process_id == process_id assert server.workspace.root_uri == root_uri - assert "capabilities" in response + assert response.capabilities is not None def test_bf_text_document_did_open(client_server): diff --git a/tests/test_protocol.py b/tests/test_protocol.py index 54c4529f..860a6bbb 100644 --- a/tests/test_protocol.py +++ b/tests/test_protocol.py @@ -17,97 +17,120 @@ import io import json from concurrent.futures import Future -from functools import partial from pathlib import Path from typing import Optional from unittest.mock import Mock +import attrs import pytest from pygls.exceptions import JsonRpcException, JsonRpcInvalidParams -from pygls.lsp import Model, get_method_params_type -from pygls.lsp.types import ( +from lsprotocol.types import ( ClientCapabilities, CompletionItem, CompletionItemKind, InitializeParams, InitializeResult, ProgressParams, + ShutdownResponse, + TextDocumentCompletionResponse, WorkDoneProgressBegin, ) -from pygls.protocol import ( - JsonRPCNotification, - JsonRPCProtocol, - JsonRPCRequestMessage, - JsonRPCResponseMessage, -) -from pygls.protocol import deserialize_message as _deserialize_message +from pygls.protocol import JsonRPCProtocol, JsonRPCRequestMessage + +EXAMPLE_NOTIFICATION = "example/notification" +EXAMPLE_REQUEST = "example/request" -TEST_METHOD = "test_method" +@attrs.define +class IntResult: + id: str + result: int + jsonrpc: str = attrs.field(default='2.0') -class FeatureParams(Model): - class InnerType(Model): +@attrs.define +class ExampleParams: + @attrs.define + class InnerType: inner_field: str field_a: str field_b: Optional[InnerType] = None -TEST_LSP_METHODS_MAP = { - TEST_METHOD: (None, FeatureParams, None), +@attrs.define +class ExampleNotification: + jsonrpc: str = attrs.field(default='2.0') + method: str = EXAMPLE_NOTIFICATION + params: ExampleParams = attrs.field(default=None) + +@attrs.define +class ExampleRequest: + id: str + jsonrpc: str = attrs.field(default='2.0') + method: str = EXAMPLE_REQUEST + params: ExampleParams = attrs.field(default=None) + + +EXAMPLE_LSP_METHODS_MAP = { + EXAMPLE_NOTIFICATION: (ExampleNotification, None, ExampleParams, None), + EXAMPLE_REQUEST: (ExampleRequest, None, ExampleParams, None), } -deserialize_message = partial( - _deserialize_message, - get_params_type=partial( - get_method_params_type, lsp_methods_map=TEST_LSP_METHODS_MAP - ), -) +class ExampleProtocol(JsonRPCProtocol): + def get_message_type(self, method: str): + return EXAMPLE_LSP_METHODS_MAP.get(method, (None,))[0] -def test_deserialize_notification_message_valid_params(): - params = """ - { + +@pytest.fixture() +def protocol(): + return ExampleProtocol(None) + + +def test_deserialize_notification_message_valid_params(protocol): + params = f""" + {{ "jsonrpc": "2.0", - "method": "test_method", - "params": { - "field_a": "test_a", - "field_b": { - "inner_field": "test_inner" - } - } - } + "method": "{EXAMPLE_NOTIFICATION}", + "params": {{ + "fieldA": "test_a", + "fieldB": {{ + "innerField": "test_inner" + }} + }} + }} """ - result = json.loads(params, object_hook=deserialize_message) + result = json.loads(params, object_hook=protocol._deserialize_message) - assert isinstance(result, JsonRPCNotification) + assert isinstance(result, ExampleNotification), f"Expected FeatureRequest instance, got {result}" assert result.jsonrpc == "2.0" + assert result.method == EXAMPLE_NOTIFICATION - assert isinstance(result.params, FeatureParams) + assert isinstance(result.params, ExampleParams) assert result.params.field_a == "test_a" - assert isinstance(result.params.field_b, FeatureParams.InnerType) + assert isinstance(result.params.field_b, ExampleParams.InnerType) assert result.params.field_b.inner_field == "test_inner" -def test_deserialize_notification_message_bad_params_should_raise_error(): - params = """ - { +def test_deserialize_notification_message_bad_params_should_raise_error(protocol): + params = f""" + {{ "jsonrpc": "2.0", - "method": "test_method", - "params": { + "method": "{EXAMPLE_NOTIFICATION}", + "params": {{ "field_a": "test_a", - "field_b": { + "field_b": {{ "wrong_field_name": "test_inner" - } - } - } + }} + }} + }} """ with pytest.raises(JsonRpcInvalidParams): - json.loads(params, object_hook=deserialize_message) + json.loads(params, object_hook=protocol._deserialize_message) @pytest.mark.parametrize( @@ -117,6 +140,7 @@ def test_deserialize_notification_message_bad_params_should_raise_error(): ProgressParams( token="id1", value=WorkDoneProgressBegin( + kind='begin', title="Begin progress", percentage=0, ), @@ -154,7 +178,7 @@ def test_serialize_notification_message(params, expected): assert actual == expected -def test_deserialize_response_message(): +def test_deserialize_response_message(protocol): params = """ { "jsonrpc": "2.0", @@ -162,43 +186,44 @@ def test_deserialize_response_message(): "result": "1" } """ - result = json.loads(params, object_hook=deserialize_message) + protocol._result_types["id"] = IntResult + result = json.loads(params, object_hook=protocol._deserialize_message) - assert isinstance(result, JsonRPCResponseMessage) + assert isinstance(result, IntResult) assert result.jsonrpc == "2.0" assert result.id == "id" - assert result.result == "1" - assert result.error is None + assert result.result == 1 -def test_deserialize_request_message_with_registered_type(): - params = """ - { +def test_deserialize_request_message_with_registered_type(protocol): + params = f""" + {{ "jsonrpc": "2.0", "id": "id", - "method": "test_method", - "params": { - "field_a": "test_a", - "field_b": { - "inner_field": "test_inner" - } - } - } + "method": "{EXAMPLE_REQUEST}", + "params": {{ + "fieldA": "test_a", + "fieldB": {{ + "innerField": "test_inner" + }} + }} + }} """ - result = json.loads(params, object_hook=deserialize_message) + result = json.loads(params, object_hook=protocol._deserialize_message) - assert isinstance(result, JsonRPCRequestMessage) + assert isinstance(result, ExampleRequest) assert result.jsonrpc == "2.0" assert result.id == "id" + assert result.method == EXAMPLE_REQUEST - assert isinstance(result.params, FeatureParams) + assert isinstance(result.params, ExampleParams) assert result.params.field_a == "test_a" - assert isinstance(result.params.field_b, FeatureParams.InnerType) + assert isinstance(result.params.field_b, ExampleParams.InnerType) assert result.params.field_b.inner_field == "test_inner" -def test_deserialize_request_message_without_registered_type(): +def test_deserialize_request_message_without_registered_type(protocol): params = """ { "jsonrpc": "2.0", @@ -212,22 +237,23 @@ def test_deserialize_request_message_without_registered_type(): } } """ - result = json.loads(params, object_hook=deserialize_message) + result = json.loads(params, object_hook=protocol._deserialize_message) assert isinstance(result, JsonRPCRequestMessage) assert result.jsonrpc == "2.0" assert result.id == "id" + assert result.method == "random" - assert type(result.params).__name__ == "Object" assert result.params.field_a == "test_a" assert result.params.field_b.inner_field == "test_inner" @pytest.mark.parametrize( - "result, expected", + "msg_type, result, expected", [ - (None, {"jsonrpc": "2.0", "id": "1", "result": None}), + (ShutdownResponse, None, {"jsonrpc": "2.0", "id": "1", "result": None}), ( + TextDocumentCompletionResponse, [ CompletionItem(label="example-one"), CompletionItem( @@ -253,7 +279,7 @@ def test_deserialize_request_message_without_registered_type(): ), ], ) -def test_serialize_response_message(result, expected): +def test_serialize_response_message(msg_type, result, expected): """ Ensure that we can serialize response messages, retaining all expected fields. @@ -265,6 +291,8 @@ def test_serialize_response_message(result, expected): protocol._send_only_body = True protocol.connection_made(buffer) + protocol._result_types["1"] = msg_type + protocol._send_response("1", result=result) actual = json.loads(buffer.getvalue()) @@ -372,7 +400,7 @@ def test_data_received_error_should_raise_jsonrpc_error(client_server): body, ] ).encode("utf-8") - future = server.lsp._server_request_futures["err"] = Future() + future = server.lsp._request_futures["err"] = Future() server.lsp.data_received(message) with pytest.raises(JsonRpcException, match="message for you sir"): future.result() diff --git a/tests/test_types.py b/tests/test_types.py index 317fa397..b11c93ae 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -16,7 +16,7 @@ # See the License for the specific language governing permissions and # # limitations under the License. # ############################################################################ -from pygls.lsp.types import Location, Position, Range +from lsprotocol.types import Location, Position, Range def test_position(): diff --git a/tests/test_workspace.py b/tests/test_workspace.py index d0e47de0..4d7051f3 100644 --- a/tests/test_workspace.py +++ b/tests/test_workspace.py @@ -19,7 +19,7 @@ import os from pygls import uris -from pygls.lsp.types import TextDocumentItem, WorkspaceFolder +from lsprotocol.types import TextDocumentItem, WorkspaceFolder from pygls.workspace import Workspace DOC_URI = uris.from_fs_path(__file__) From b7373e741466781b73205ecc114d00c94ca302cc Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Fri, 14 Oct 2022 18:02:26 +0100 Subject: [PATCH 7/9] Make it possible to pick browser used for pyodide tests It's now possible to select which browser is used to run the testsuite by setting the `BROWSER` environment variable e.g. BROWSER=firefox python pyodide_testrunner/run.py If no variable is found, the script will default to use Chrome. --- pyodide_testrunner/run.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyodide_testrunner/run.py b/pyodide_testrunner/run.py index a426784e..26ac2afd 100644 --- a/pyodide_testrunner/run.py +++ b/pyodide_testrunner/run.py @@ -18,6 +18,10 @@ # Path to the root of the repo. REPO = pathlib.Path(__file__).parent.parent +BROWSERS = { + "chrome": (webdriver.Chrome, webdriver.ChromeOptions), + "firefox": (webdriver.Firefox, webdriver.FirefoxOptions), +} def build_wheel() -> str: @@ -82,10 +86,12 @@ def main(): print("Running tests...") try: - options = webdriver.ChromeOptions() + driver_cls, options_cls = BROWSERS[os.environ.get('BROWSER', 'chrome')] + + options = options_cls() options.headless = 'CI' in os.environ - driver = webdriver.Chrome(options=options) + driver = driver_cls(options=options) driver.get(f'http://localhost:{port}?whl={whl}') wait = WebDriverWait(driver, 120) From fb2c752c98dd4eaef941478bc87960e6ffc94784 Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Sun, 16 Oct 2022 18:49:27 +0100 Subject: [PATCH 8/9] Add some tests around `ClientCapabilities` As far as I can tell, there are no tests that depend on any of the values contained within `ClientCapabilities`. This commit adds some tests around the construction of the `TextDocumentSyncOptions` field for the server's capabilities. It also fixes a bug that was introduced in the previous commit --- pygls/capabilities.py | 3 +- tests/test_capabilities.py | 136 +++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 tests/test_capabilities.py diff --git a/pygls/capabilities.py b/pygls/capabilities.py index 030e1ac7..fa2d3240 100644 --- a/pygls/capabilities.py +++ b/pygls/capabilities.py @@ -62,8 +62,7 @@ def get_capability( 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 + return default if value is None else value class ServerCapabilitiesBuilder: diff --git a/tests/test_capabilities.py b/tests/test_capabilities.py new file mode 100644 index 00000000..cb69027a --- /dev/null +++ b/tests/test_capabilities.py @@ -0,0 +1,136 @@ +from typing import Set + +import pytest +from lsprotocol.types import ( + TEXT_DOCUMENT_DID_OPEN, + TEXT_DOCUMENT_DID_CLOSE, + TEXT_DOCUMENT_DID_SAVE, + TEXT_DOCUMENT_WILL_SAVE, + TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL, + ClientCapabilities, + SaveOptions, + TextDocumentClientCapabilities, + TextDocumentSaveRegistrationOptions, + TextDocumentSyncClientCapabilities, + TextDocumentSyncKind, + TextDocumentSyncOptions, +) + +from pygls.capabilities import ServerCapabilitiesBuilder + + +@pytest.mark.parametrize("capabilities,features,options,expected", [ + + # textDocument/didOpen + ( + ClientCapabilities(), + set(), + {}, + TextDocumentSyncOptions( + open_close=False, + change=TextDocumentSyncKind.Incremental, + save=False, + ) + ), + ( + ClientCapabilities(), + {TEXT_DOCUMENT_DID_OPEN}, + {}, + TextDocumentSyncOptions( + open_close=True, + change=TextDocumentSyncKind.Incremental, + save=False, + ) + ), + ( + ClientCapabilities(), + {TEXT_DOCUMENT_DID_CLOSE}, + {}, + TextDocumentSyncOptions( + open_close=True, + change=TextDocumentSyncKind.Incremental, + save=False, + ) + ), + # textDocument/willSave & textDocument/willSaveWaitUntil + ( + ClientCapabilities(), + {TEXT_DOCUMENT_WILL_SAVE}, + {}, + TextDocumentSyncOptions( + open_close=False, + change=TextDocumentSyncKind.Incremental, + save=False, + ) + ), + ( + ClientCapabilities( + text_document=TextDocumentClientCapabilities( + synchronization=TextDocumentSyncClientCapabilities( + will_save=True + ) + ) + ), + {TEXT_DOCUMENT_WILL_SAVE}, + {}, + TextDocumentSyncOptions( + open_close=False, + change=TextDocumentSyncKind.Incremental, + save=False, + will_save=True + ) + ), + ( + ClientCapabilities( + text_document=TextDocumentClientCapabilities( + synchronization=TextDocumentSyncClientCapabilities( + will_save_wait_until=True + ) + ) + ), + {TEXT_DOCUMENT_WILL_SAVE_WAIT_UNTIL}, + {}, + TextDocumentSyncOptions( + open_close=False, + change=TextDocumentSyncKind.Incremental, + save=False, + will_save_wait_until=True + ) + ), + # textDocument/didSave + ( + ClientCapabilities(), + {TEXT_DOCUMENT_DID_SAVE}, + {}, + TextDocumentSyncOptions( + open_close=False, + change=TextDocumentSyncKind.Incremental, + save=True, + ) + ), + ( + ClientCapabilities(), + {TEXT_DOCUMENT_DID_SAVE}, + {TEXT_DOCUMENT_DID_SAVE: TextDocumentSaveRegistrationOptions(include_text=True)}, + TextDocumentSyncOptions( + open_close=False, + change=TextDocumentSyncKind.Incremental, + save=SaveOptions(include_text=True), + ) + ) +]) +def test_text_doc_sync_capabilities( + capabilities: ClientCapabilities, + features: Set[str], + options, + expected: TextDocumentSyncOptions +): + """Ensure that `pygls` can correctly construct server capabilities for the + text document sync features.""" + + builder = ServerCapabilitiesBuilder( + capabilities, features, options, [], TextDocumentSyncKind.Incremental + ) + + actual = builder.build().text_document_sync + assert expected == actual From ffe4baeb87a8c0bce6d5bbc9bbc629fe0bfd8620 Mon Sep 17 00:00:00 2001 From: Thomas Buckley-Houston Date: Mon, 17 Oct 2022 16:56:34 -0300 Subject: [PATCH 9/9] feat: Bump for lsprotocol BREAKING CHANGES release --- CHANGELOG.md | 5 +++++ pygls/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90777468..9d0609ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ and this project adheres to [Semantic Versioning][semver]. ### Changed ### Fixed +## [1.0.0alpha] - 17/10/2022 +### Changed +🚧 Alpha Code (likely contains bugs) 🚧 +BREAKING CHANGE: Replaced `pydantic` with [`lsprotocol`](https://github.com/microsoft/lsprotocol) + ## [0.12.2] - 26/09/2022 ### Fixed - Relaxed the Python version upper bound to `<4` diff --git a/pygls/__init__.py b/pygls/__init__.py index b6f8f198..9ec1438a 100644 --- a/pygls/__init__.py +++ b/pygls/__init__.py @@ -19,7 +19,7 @@ import os import sys -__version__ = "0.12.2" +__version__ = "1.0.0alpha" IS_WIN = os.name == 'nt' IS_PYODIDE = 'pyodide' in sys.modules