From bbf1d7d1b2c36daab8a694c96aa4914828450daa Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Thu, 14 Sep 2023 18:30:50 -0700 Subject: [PATCH 1/5] Add broad spectrum tests for python --- noxfile.py | 3 +++ tests/python/test_generated_data.py | 34 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/python/test_generated_data.py diff --git a/noxfile.py b/noxfile.py index 4717e0d..88cf122 100644 --- a/noxfile.py +++ b/noxfile.py @@ -23,6 +23,9 @@ def tests(session: nox.Session): """Run tests for generator and generated code in all languages.""" _install_requirements(session) + session.log("Running test data generator.") + session.run("python", "-m", "generator", "--plugin", "testdata") + session.log("Running tests: generator and generated Python code.") session.run("pytest", "./tests") diff --git a/tests/python/test_generated_data.py b/tests/python/test_generated_data.py new file mode 100644 index 0000000..0ecee3c --- /dev/null +++ b/tests/python/test_generated_data.py @@ -0,0 +1,34 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +import json +import pathlib +from typing import Generator, List, Union + +import pytest + +import lsprotocol.converters as cv +import lsprotocol.types as lsp + +TEST_DATA_ROOT = pathlib.Path(__file__).parent.parent.parent / "packages" / "testdata" + + +def get_all_json_files(root: Union[pathlib.Path, str]) -> List[pathlib.Path]: + root_path = pathlib.Path(root) + return list(root_path.glob("**/*.json")) + + +converter = cv.get_converter() + + +@pytest.mark.parametrize("json_file", get_all_json_files(TEST_DATA_ROOT)) +def test_generated_data(json_file: str) -> None: + type_name, result_type, _ = json_file.name.split("-", 2) + lsp_type = getattr(lsp, type_name) + data = json.loads(json_file.read_text(encoding="utf-8")) + + try: + converter.structure(data, lsp_type) + assert result_type == "True", "Expected error, but succeeded structuring" + except Exception as e: + assert result_type == "False", "Expected success, but failed structuring" From baaad7fd451e880114d8eb6dc0e45748e162b49d Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Thu, 14 Sep 2023 18:58:40 -0700 Subject: [PATCH 2/5] Some structuring fixes --- packages/python/lsprotocol/_hooks.py | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/python/lsprotocol/_hooks.py b/packages/python/lsprotocol/_hooks.py index dbd51f9..d696501 100644 --- a/packages/python/lsprotocol/_hooks.py +++ b/packages/python/lsprotocol/_hooks.py @@ -634,6 +634,28 @@ def _notebook_sync_option_selector_hook( object_, lsp_types.NotebookDocumentSyncOptionsNotebookSelectorType2 ) + def _semantic_token_registration_options_hook( + object_: Any, _: type + ) -> Optional[ + Union[OptionalPrimitive, lsp_types.SemanticTokensRegistrationOptionsFullType1] + ]: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure( + object_, lsp_types.SemanticTokensRegistrationOptionsFullType1 + ) + + def _inline_completion_provider_hook( + object_: Any, _: type + ) -> Optional[Union[OptionalPrimitive, lsp_types.InlineCompletionOptions]]: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure(object_, lsp_types.InlineCompletionOptions) + structure_hooks = [ ( Optional[ @@ -940,6 +962,14 @@ def _notebook_sync_option_selector_hook( ], _position_encoding_hook, ), + ( + Optional[Union[bool, lsp_types.SemanticTokensRegistrationOptionsFullType1]], + _semantic_token_registration_options_hook, + ), + ( + Optional[Union[bool, lsp_types.InlineCompletionOptions]], + _inline_completion_provider_hook, + ), ] for type_, hook in structure_hooks: converter.register_structure_hook(type_, hook) From 7f3ea3d3f5bf25990cecb8e804297984c05bbf4f Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Thu, 14 Sep 2023 19:12:28 -0700 Subject: [PATCH 3/5] Add inline completion list hook --- packages/python/lsprotocol/_hooks.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/packages/python/lsprotocol/_hooks.py b/packages/python/lsprotocol/_hooks.py index d696501..9c6dc6e 100644 --- a/packages/python/lsprotocol/_hooks.py +++ b/packages/python/lsprotocol/_hooks.py @@ -656,6 +656,20 @@ def _inline_completion_provider_hook( return object_ return converter.structure(object_, lsp_types.InlineCompletionOptions) + def _inline_completion_list_hook( + object_: Any, _: type + ) -> Optional[ + Union[lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem]] + ]: + if object_ is None: + return None + if isinstance(object_, list): + return [ + converter.structure(item, lsp_types.InlineCompletionItem) + for item in object_ + ] + return converter.structure(object_, lsp_types.InlineCompletionList) + structure_hooks = [ ( Optional[ @@ -970,6 +984,14 @@ def _inline_completion_provider_hook( Optional[Union[bool, lsp_types.InlineCompletionOptions]], _inline_completion_provider_hook, ), + ( + Optional[ + Union[ + lsp_types.InlineCompletionList, List[lsp_types.InlineCompletionItem] + ] + ], + _inline_completion_list_hook, + ), ] for type_, hook in structure_hooks: converter.register_structure_hook(type_, hook) From fa6a7d8a971e653d47b4c5d5dafb9ae61c7f18ce Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Thu, 14 Sep 2023 19:26:09 -0700 Subject: [PATCH 4/5] Add more hooks --- packages/python/lsprotocol/_hooks.py | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/packages/python/lsprotocol/_hooks.py b/packages/python/lsprotocol/_hooks.py index 9c6dc6e..a2f08a1 100644 --- a/packages/python/lsprotocol/_hooks.py +++ b/packages/python/lsprotocol/_hooks.py @@ -670,6 +670,35 @@ def _inline_completion_list_hook( ] return converter.structure(object_, lsp_types.InlineCompletionList) + def _string_value_hook( + object_: Any, _: type + ) -> Union[OptionalPrimitive, lsp_types.StringValue]: + if object_ is None: + return None + if isinstance(object_, (bool, int, str, float)): + return object_ + return converter.structure(object_, lsp_types.StringValue) + + def _symbol_list_hook( + object_: Any, _: type + ) -> Optional[ + Union[List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol]] + ]: + if object_ is None: + return None + assert isinstance(object_, list) + if len(object_) == 0: + return [] + if "location" in object_[0]: + return [ + converter.structure(item, lsp_types.SymbolInformation) + for item in object_ + ] + else: + return [ + converter.structure(item, lsp_types.WorkspaceSymbol) for item in object_ + ] + structure_hooks = [ ( Optional[ @@ -992,6 +1021,18 @@ def _inline_completion_list_hook( ], _inline_completion_list_hook, ), + ( + Union[str, lsp_types.StringValue], + _string_value_hook, + ), + ( + Optional[ + Union[ + List[lsp_types.SymbolInformation], List[lsp_types.WorkspaceSymbol] + ] + ], + _symbol_list_hook, + ), ] for type_, hook in structure_hooks: converter.register_structure_hook(type_, hook) From 0204701972ec79864e138247305b1224f4c39837 Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Thu, 14 Sep 2023 19:45:30 -0700 Subject: [PATCH 5/5] Add notebook sync registration option hook --- packages/python/lsprotocol/_hooks.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/python/lsprotocol/_hooks.py b/packages/python/lsprotocol/_hooks.py index a2f08a1..06ade48 100644 --- a/packages/python/lsprotocol/_hooks.py +++ b/packages/python/lsprotocol/_hooks.py @@ -688,7 +688,7 @@ def _symbol_list_hook( return None assert isinstance(object_, list) if len(object_) == 0: - return [] + return [] # type: ignore[return-value] if "location" in object_[0]: return [ converter.structure(item, lsp_types.SymbolInformation) @@ -699,6 +699,23 @@ def _symbol_list_hook( converter.structure(item, lsp_types.WorkspaceSymbol) for item in object_ ] + def _notebook_sync_registration_option_selector_hook( + object_: Any, _: type + ) -> Union[ + lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, + lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, + ]: + if "notebook" in object_: + return converter.structure( + object_, + lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, + ) + else: + return converter.structure( + object_, + lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, + ) + structure_hooks = [ ( Optional[ @@ -1033,6 +1050,13 @@ def _symbol_list_hook( ], _symbol_list_hook, ), + ( + Union[ + lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType1, + lsp_types.NotebookDocumentSyncRegistrationOptionsNotebookSelectorType2, + ], + _notebook_sync_registration_option_selector_hook, + ), ] for type_, hook in structure_hooks: converter.register_structure_hook(type_, hook)