From 0c90cef0f1986c80067e9eb9a0417cbd5e70aa4f Mon Sep 17 00:00:00 2001 From: Daniel Roseman Date: Sat, 24 Feb 2024 18:25:27 +0000 Subject: [PATCH] Implement Go to Declaration. This uses the Goto functionality but does not follow imports. --- README.md | 1 + jedi_language_server/server.py | 18 ++++++++++++++++++ tests/lsp_test_client/session.py | 9 ++++++++- tests/lsp_tests/test_definition.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4812260..1dba6df 100644 --- a/README.md +++ b/README.md @@ -456,6 +456,7 @@ jedi-language-server aims to support Jedi's capabilities and expose them through - [completionItem/resolve](https://microsoft.github.io/language-server-protocol/specification#completionItem_resolve) - [textDocument/codeAction](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeAction) (refactor.inline, refactor.extract) - [textDocument/completion](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion) +- [textDocument/declaration](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration) - [textDocument/definition](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition) - [textDocument/documentHighlight](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight) - [textDocument/documentSymbol](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol) diff --git a/jedi_language_server/server.py b/jedi_language_server/server.py index 77e6d00..66d3d8a 100644 --- a/jedi_language_server/server.py +++ b/jedi_language_server/server.py @@ -17,6 +17,7 @@ INITIALIZE, TEXT_DOCUMENT_CODE_ACTION, TEXT_DOCUMENT_COMPLETION, + TEXT_DOCUMENT_DECLARATION, TEXT_DOCUMENT_DEFINITION, TEXT_DOCUMENT_DID_CHANGE, TEXT_DOCUMENT_DID_CLOSE, @@ -306,6 +307,23 @@ def signature_help( ) +@SERVER.feature(TEXT_DOCUMENT_DECLARATION) +def declaration( + server: JediLanguageServer, params: TextDocumentPositionParams +) -> Optional[List[Location]]: + """Support Goto Declaration.""" + document = server.workspace.get_text_document(params.text_document.uri) + jedi_script = jedi_utils.script(server.project, document) + jedi_lines = jedi_utils.line_column(params.position) + names = jedi_script.goto(*jedi_lines) + definitions = [ + definition + for definition in (jedi_utils.lsp_location(name) for name in names) + if definition is not None + ] + return definitions if definitions else None + + @SERVER.feature(TEXT_DOCUMENT_DEFINITION) def definition( server: JediLanguageServer, params: TextDocumentPositionParams diff --git a/tests/lsp_test_client/session.py b/tests/lsp_test_client/session.py index 36ad89a..9ebe2aa 100644 --- a/tests/lsp_test_client/session.py +++ b/tests/lsp_test_client/session.py @@ -152,8 +152,15 @@ def text_document_signature_help(self, signature_help_params): ) return fut.result() + def text_document_declaration(self, declaration_params): + """Sends text document declaration request to LSP server.""" + fut = self._send_request( + "textDocument/declaration", params=declaration_params + ) + return fut.result() + def text_document_definition(self, definition_params): - """Sends text document defintion request to LSP server.""" + """Sends text document definition request to LSP server.""" fut = self._send_request( "textDocument/definition", params=definition_params ) diff --git a/tests/lsp_tests/test_definition.py b/tests/lsp_tests/test_definition.py index add80ae..28dc20a 100644 --- a/tests/lsp_tests/test_definition.py +++ b/tests/lsp_tests/test_definition.py @@ -36,3 +36,31 @@ def test_definition(): ] assert_that(actual, is_(expected)) + + +def test_declaration(): + """Tests declaration on an imported module. + + Test Data: tests/test_data/definition/definition_test1.py + """ + with session.LspSession() as ls_session: + ls_session.initialize() + uri = as_uri(DEFINITION_TEST_ROOT / "definition_test1.py") + actual = ls_session.text_document_declaration( + { + "textDocument": {"uri": uri}, + "position": {"line": 5, "character": 0}, + } + ) + + expected = [ + { + "uri": uri, + "range": { + "start": {"line": 2, "character": 26}, + "end": {"line": 2, "character": 37}, + }, + } + ] + + assert_that(actual, is_(expected))