summaryrefslogtreecommitdiffstats
path: root/docs/source/pages/migrating-to-v1.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/source/pages/migrating-to-v1.rst')
-rw-r--r--docs/source/pages/migrating-to-v1.rst241
1 files changed, 241 insertions, 0 deletions
diff --git a/docs/source/pages/migrating-to-v1.rst b/docs/source/pages/migrating-to-v1.rst
new file mode 100644
index 0000000..527a810
--- /dev/null
+++ b/docs/source/pages/migrating-to-v1.rst
@@ -0,0 +1,241 @@
+Migrating to v1.0
+=================
+
+The most notable change of the ``v1.0`` release of ``pygls`` is the removal of its hand written LSP type and method definitions in favour of relying on the types provided by the `lsprotocol`_ library which are automatically generated from the LSP specification.
+As as side effect this has also meant the removal of `pydantic`_ as a dependency, since ``lsprotocol`` uses `attrs`_ and `cattrs`_ for serialisation and validation.
+
+This guide outlines how to adapt an existing server to the breaking changes introduced in this release.
+
+Known Migrations
+----------------
+You may find insight and inspiration from these projects that have already successfully migrated to v1:
+
+* `jedi-language-server`_
+* `vscode-ruff`_
+* `esbonio`_
+* `yara-language-server`_
+
+Updating Imports
+----------------
+
+The ``pygls.lsp.methods`` and ``pygls.lsp.types`` modules no longer exist.
+Instead, all types and method names should now be imported from the ``lsprotocol.types`` module.
+
+Additionally, the following types and constants have been renamed.
+
+================================================================== ==============
+pygls lsprotocol
+================================================================== ==============
+``CODE_ACTION`` ``TEXT_DOCUMENT_CODE_ACTION``
+``CODE_LENS`` ``TEXT_DOCUMENT_CODE_LENS``
+``COLOR_PRESENTATION`` ``TEXT_DOCUMENT_COLOR_PRESENTATION``
+``COMPLETION`` ``TEXT_DOCUMENT_COMPLETION``
+``DECLARATION`` ``TEXT_DOCUMENT_DECLARATION``
+``DEFINITION`` ``TEXT_DOCUMENT_DEFINITION``
+``DOCUMENT_COLOR`` ``TEXT_DOCUMENT_DOCUMENT_COLOR``
+``DOCUMENT_HIGHLIGHT`` ``TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT``
+``DOCUMENT_LINK`` ``TEXT_DOCUMENT_DOCUMENT_LINK``
+``DOCUMENT_SYMBOL`` ``TEXT_DOCUMENT_DOCUMENT_SYMBOL``
+``FOLDING_RANGE`` ``TEXT_DOCUMENT_FOLDING_RANGE``
+``FORMATTING`` ``TEXT_DOCUMENT_FORMATTING``
+``HOVER`` ``TEXT_DOCUMENT_HOVER``
+``IMPLEMENTATION`` ``TEXT_DOCUMENT_IMPLEMENTATION``
+``LOG_TRACE_NOTIFICATION`` ``LOG_TRACE``
+``ON_TYPE_FORMATTING`` ``TEXT_DOCUMENT_ON_TYPE_FORMATTING``
+``PREPARE_RENAME`` ``TEXT_DOCUMENT_PREPARE_RENAME``
+``PROGRESS_NOTIFICATION`` ``PROGRESS``
+``RANGE_FORMATTING`` ``TEXT_DOCUMENT_RANGE_FORMATTING``
+``REFERENCES`` ``TEXT_DOCUMENT_REFERENCES``
+``RENAME`` ``TEXT_DOCUMENT_RENAME``
+``SELECTION_RANGE`` ``TEXT_DOCUMENT_SELECTION_RANGE``
+``SET_TRACE_NOTIFICATION`` ``SET_TRACE``
+``SIGNATURE_HELP`` ``TEXT_DOCUMENT_SIGNATURE_HELP``
+``TEXT_DOCUMENT_CALL_HIERARCHY_INCOMING_CALLS`` ``CALL_HIERARCHY_INCOMING_CALLS``
+``TEXT_DOCUMENT_CALL_HIERARCHY_OUTGOING_CALLS`` ``CALL_HIERARCHY_OUTGOING_CALLS``
+``TEXT_DOCUMENT_CALL_HIERARCHY_PREPARE`` ``TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY``
+``TYPE_DEFINITION`` ``TEXT_DOCUMENT_TYPE_DEFINITION``
+``WORKSPACE_FOLDERS`` ``WORKSPACE_WORKSPACE_FOLDERS``
+``ApplyWorkspaceEditResponse`` ``ApplyWorkspaceEditResult``
+``ClientInfo`` ``InitializeParamsClientInfoType``
+``CodeActionDisabled`` ``CodeActionDisabledType``
+``CodeActionLiteralSupportActionKindClientCapabilities`` ``CodeActionClientCapabilitiesCodeActionLiteralSupportTypeCodeActionKindType``
+``CodeActionLiteralSupportClientCapabilities`` ``CodeActionClientCapabilitiesCodeActionLiteralSupportType``
+``CompletionItemClientCapabilities`` ``CompletionClientCapabilitiesCompletionItemType``
+``CompletionItemKindClientCapabilities`` ``CompletionClientCapabilitiesCompletionItemKindType``
+``CompletionTagSupportClientCapabilities`` ``CompletionClientCapabilitiesCompletionItemTypeTagSupportType``
+``DocumentSymbolCapabilitiesTagSupport`` ``DocumentSymbolClientCapabilitiesTagSupportType``
+``InsertTextModeSupportClientCapabilities`` ``CompletionClientCapabilitiesCompletionItemTypeInsertTextModeSupportType``
+``MarkedStringType`` ``MarkedString``
+``MarkedString`` ``MarkedString_Type1``
+``PrepareRename`` ``PrepareRenameResult_Type1``
+``PublishDiagnosticsTagSupportClientCapabilities`` ``PublishDiagnosticsClientCapabilitiesTagSupportType``
+``ResolveSupportClientCapabilities`` ``CodeActionClientCapabilitiesResolveSupportType``
+``SemanticTokensRequestsFull`` ``SemanticTokensRegistrationOptionsFullType1``
+``SemanticTokensRequests`` ``SemanticTokensClientCapabilitiesRequestsType``
+``ServerInfo`` ``InitializeResultServerInfoType``
+``ShowMessageRequestActionItem`` ``ShowMessageRequestClientCapabilitiesMessageActionItemType``
+``SignatureHelpInformationClientCapabilities`` ``SignatureHelpClientCapabilitiesSignatureInformationType``
+``SignatureHelpInformationParameterInformationClientCapabilities`` ``SignatureHelpClientCapabilitiesSignatureInformationTypeParameterInformationType``
+``TextDocumentContentChangeEvent`` ``TextDocumentContentChangeEvent_Type1``
+``TextDocumentContentChangeTextEvent`` ``TextDocumentContentChangeEvent_Type2``
+``TextDocumentSyncOptionsServerCapabilities`` ``TextDocumentSyncOptions``
+``Trace`` ``TraceValues``
+``URI`` ``str``
+``WorkspaceCapabilitiesSymbolKind`` ``WorkspaceSymbolClientCapabilitiesSymbolKindType``
+``WorkspaceCapabilitiesTagSupport`` ``WorkspaceSymbolClientCapabilitiesTagSupportType``
+``WorkspaceFileOperationsServerCapabilities`` ``FileOperationOptions``
+``WorkspaceServerCapabilities`` ``ServerCapabilitiesWorkspaceType``
+================================================================== ==============
+
+Custom Models
+-------------
+
+One of the most obvious changes is the switch to `attrs`_ and `cattrs`_ for serialization and deserialisation.
+This means that any custom models used by your language server will need to be converted to an ``attrs`` style class.
+
+.. code-block:: python
+
+ # Before
+ from pydantic import BaseModel, Field
+
+ class ExampleConfig(BaseModel):
+ build_dir: Optional[str] = Field(None, alias="buildDir")
+
+ builder_name: str = Field("html", alias="builderName")
+
+ conf_dir: Optional[str] = Field(None, alias="confDir")
+
+.. code-block:: python
+
+ # After
+ import attrs
+
+ @attrs.define
+ class ExampleConfig:
+ build_dir: Optional[str] = attrs.field(default=None)
+
+ builder_name: str = attrs.field(default="html")
+
+ conf_dir: Optional[str] = attrs.field(default=None)
+
+
+Pygls provides a default `converter`_ that it will use when converting your models to/from JSON, which should be sufficient for most scenarios.
+
+.. code-block:: pycon
+
+ >>> from pygls.protocol import default_converter
+ >>> converter = default_converter()
+
+ >>> config = ExampleConfig(builder_name='epub', conf_dir='/path/to/conf')
+ >>> converter.unstructure(config)
+ {'builderName': 'epub', 'confDir': '/path/to/conf'} # Note how snake_case is converted to camelCase
+
+ >>> converter.structure({'builderName': 'epub', 'confDir': '/path/to/conf'}, ExampleConfig)
+ ExampleConfig(build_dir=None, builder_name='epub', conf_dir='/path/to/conf')
+
+However, depending on the complexity of your type definitions you may find the default converter fail to parse some of your types.
+
+.. code-block:: pycon
+
+ >>> from typing import Literal, Union
+
+ >>> @attrs.define
+ ... class ExampleConfig:
+ ... num_jobs: Union[Literal["auto"], int] = attrs.field(default='auto')
+ ...
+
+ >>> converter.structure({'numJobs': 'auto'}, ExampleConfig)
+ + Exception Group Traceback (most recent call last):
+ | File "<stdin>", line 1, in <module>
+ | File "/.../python3.10/site-packages/cattrs/converters.py", li
+ ne 309, in structure
+ | return self._structure_func.dispatch(cl)(obj, cl)
+ | File "<cattrs generated structure __main__.ExampleConfig-2>", line 10, in structure_ExampleConfig
+ | if errors: raise __c_cve('While structuring ' + 'ExampleConfig', errors, __cl)
+ | cattrs.errors.ClassValidationError: While structuring ExampleConfig (1 sub-exception)
+ +-+---------------- 1 ----------------
+ | Traceback (most recent call last):
+ | File "<cattrs generated structure __main__.ExampleConfig-2>", line 6, in structure_ExampleConfig
+ | res['num_jobs'] = __c_structure_num_jobs(o['numJobs'], __c_type_num_jobs)
+ | File "/.../python3.10/site-packages/cattrs/converters.py",
+ line 377, in _structure_error
+ | raise StructureHandlerNotFoundError(msg, type_=cl)
+ | cattrs.errors.StructureHandlerNotFoundError: Unsupported type: typing.Union[typing.Literal['auto'], int].
+ Register a structure hook for it.
+ | Structuring class ExampleConfig @ attribute num_jobs
+ +------------------------------------
+
+In which case you can extend the converter provided by ``pygls`` with your own `structure hooks`_
+
+.. code-block:: python
+
+ from pygls.protocol import default_converter
+
+ def custom_converter():
+ converter = default_converter()
+ converter.register_structure_hook(Union[Literal['auto', int], lambda obj, _: obj)
+
+ return converter
+
+You can then override the default converter used by ``pygls`` when constructing your language server instance
+
+.. code-block:: python
+
+ server = LanguageServer(
+ name="my-language-server", version="v1.0", converter_factory=custom_converter
+ )
+
+See the `hooks.py`_ module in ``lsprotocol`` for some example structure hooks
+
+Miscellaneous
+-------------
+
+Mandatory ``name`` and ``version``
+""""""""""""""""""""""""""""""""""
+
+It is now necessary to provide a name and version when constructing an instance of the ``LanguageServer`` class
+
+.. code-block:: python
+
+ from pygls.server import LanguageServer
+
+ server = LanguageServer(name="my-language-server", version="v1.0")
+
+
+``ClientCapabilities.get_capability`` is now ``get_capability``
+"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
+
+.. code-block:: python
+
+ # Before
+ from pygls.lsp.types import ClientCapabilities
+
+ client_capabilities = ClientCapabilities()
+ commit_character_support = client_capabilities.get_capability(
+ "text_document.completion.completion_item.commit_characters_support", False
+ )
+
+.. code-block:: python
+
+ # After
+ from lsprotocol.types import ClientCapabilities
+ from pygls.capabilities import get_capability
+
+ client_capabilities = ClientCapabilities()
+ commit_character_support = get_capability(
+ client_capabilities,
+ "text_document.completion.completion_item.commit_characters_support",
+ False
+ )
+
+.. _attrs: https://www.attrs.org/en/stable/index.html
+.. _cattrs: https://cattrs.readthedocs.io/en/stable/
+.. _converter: https://cattrs.readthedocs.io/en/stable/converters.html
+.. _hooks.py: https://github.com/microsoft/lsprotocol/blob/main/lsprotocol/_hooks.py
+.. _lsprotocol: https://github.com/microsoft/lsprotocol
+.. _pydantic: https://pydantic-docs.helpmanual.io/
+.. _structure hooks: https://cattrs.readthedocs.io/en/stable/structuring.html#registering-custom-structuring-hooks
+.. _jedi-language-server: https://github.com/pappasam/jedi-language-server/pull/230
+.. _yara-language-server: https://github.com/avast/yls/pull/34
+.. _vscode-ruff: https://github.com/charliermarsh/vscode-ruff/pull/37
+.. _esbonio: https://github.com/swyddfa/esbonio/pull/484