From 820a3b66fc63910d03f284dfca3dd334cc3b265c Mon Sep 17 00:00:00 2001 From: Karthik Nadig Date: Fri, 1 Sep 2023 12:47:57 -0700 Subject: [PATCH] feat: adds type hierarchy request support --- pygls/capabilities.py | 8 ++ tests/lsp/test_type_hierarchy.py | 127 +++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 tests/lsp/test_type_hierarchy.py diff --git a/pygls/capabilities.py b/pygls/capabilities.py index 55a1df18..8adcb575 100644 --- a/pygls/capabilities.py +++ b/pygls/capabilities.py @@ -42,6 +42,7 @@ TEXT_DOCUMENT_SELECTION_RANGE, TEXT_DOCUMENT_SIGNATURE_HELP, TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, + TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY, TEXT_DOCUMENT_DID_CLOSE, TEXT_DOCUMENT_DID_OPEN, TEXT_DOCUMENT_DID_SAVE, @@ -307,6 +308,12 @@ def _with_call_hierarchy(self): self.server_cap.call_hierarchy_provider = value return self + def _with_type_hierarchy(self): + value = self._provider_options(TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY) + if value is not None: + self.server_cap.type_hierarchy_provider = value + return self + def _with_semantic_tokens(self): providers = [ TEXT_DOCUMENT_SEMANTIC_TOKENS_FULL, @@ -433,6 +440,7 @@ def build(self): ._with_execute_command() ._with_selection_range() ._with_call_hierarchy() + ._with_type_hierarchy() ._with_semantic_tokens() ._with_linked_editing_range() ._with_moniker() diff --git a/tests/lsp/test_type_hierarchy.py b/tests/lsp/test_type_hierarchy.py new file mode 100644 index 00000000..e186c7f5 --- /dev/null +++ b/tests/lsp/test_type_hierarchy.py @@ -0,0 +1,127 @@ +############################################################################ +# 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. # +############################################################################ +from typing import List, Optional + +from lsprotocol import types as lsp + +from ..conftest import ClientServer + + +TYPE_HIERARCHY_ITEM = lsp.TypeHierarchyItem( + name="test_name", + kind=lsp.SymbolKind.Class, + uri="test_uri", + range=lsp.Range( + start=lsp.Position(line=0, character=0), + end=lsp.Position(line=0, character=6), + ), + selection_range=lsp.Range( + start=lsp.Position(line=0, character=0), + end=lsp.Position(line=0, character=6), + ), +) + + +def check_type_hierarchy_item_response(item): + assert item.name == TYPE_HIERARCHY_ITEM.name + assert item.kind == TYPE_HIERARCHY_ITEM.kind + assert item.uri == TYPE_HIERARCHY_ITEM.uri + assert item.range == TYPE_HIERARCHY_ITEM.range + assert item.selection_range == TYPE_HIERARCHY_ITEM.selection_range + + +class ConfiguredLS(ClientServer): + def __init__(self): + super().__init__() + + @self.server.feature(lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY) + def f1( + params: lsp.TypeHierarchyPrepareParams, + ) -> Optional[List[lsp.TypeHierarchyItem]]: + if params.text_document.uri == "file://return.list": + return [TYPE_HIERARCHY_ITEM] + else: + return None + + @self.server.feature(lsp.TYPE_HIERARCHY_SUPERTYPES) + def f2( + params: lsp.TypeHierarchySupertypesParams, + ) -> Optional[List[lsp.TypeHierarchyItem]]: + return [TYPE_HIERARCHY_ITEM] + + @self.server.feature(lsp.TYPE_HIERARCHY_SUBTYPES) + def f3( + params: lsp.TypeHierarchySubtypesParams, + ) -> Optional[List[lsp.TypeHierarchyItem]]: + return [TYPE_HIERARCHY_ITEM] + + +@ConfiguredLS.decorate() +def test_capabilities(client_server): + _, server = client_server + capabilities = server.server_capabilities + assert capabilities.type_hierarchy_provider + + +@ConfiguredLS.decorate() +def test_type_hierarchy_prepare_return_list(client_server): + client, _ = client_server + response = client.lsp.send_request( + lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY, + lsp.TypeHierarchyPrepareParams( + text_document=lsp.TextDocumentIdentifier(uri="file://return.list"), + position=lsp.Position(line=0, character=0), + ), + ).result() + + check_type_hierarchy_item_response(response[0]) + + +@ConfiguredLS.decorate() +def test_type_hierarchy_prepare_return_none(client_server): + client, _ = client_server + response = client.lsp.send_request( + lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY, + lsp.TypeHierarchyPrepareParams( + text_document=lsp.TextDocumentIdentifier(uri="file://return.none"), + position=lsp.Position(line=0, character=0), + ), + ).result() + + assert response is None + + +@ConfiguredLS.decorate() +def test_type_hierarchy_supertypes(client_server): + client, _ = client_server + response = client.lsp.send_request( + lsp.TYPE_HIERARCHY_SUPERTYPES, + lsp.TypeHierarchySupertypesParams(item=TYPE_HIERARCHY_ITEM), + ).result() + + check_type_hierarchy_item_response(response[0]) + + +@ConfiguredLS.decorate() +def test_type_hierarchy_subtypes(client_server): + client, _ = client_server + response = client.lsp.send_request( + lsp.TYPE_HIERARCHY_SUBTYPES, + lsp.TypeHierarchySubtypesParams(item=TYPE_HIERARCHY_ITEM), + ).result() + + check_type_hierarchy_item_response(response[0])