Skip to content

Commit 8604c25

Browse files
committed
Add basic Goto Implementation Request support
1 parent 04fa3e5 commit 8604c25

File tree

7 files changed

+66
-2
lines changed

7 files changed

+66
-2
lines changed

CONFIGURATION.md

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ This server can be configured using the `workspace/didChangeConfiguration` metho
7272
| `pylsp.plugins.rope_autoimport.memory` | `boolean` | Make the autoimport database memory only. Drastically increases startup time. | `false` |
7373
| `pylsp.plugins.rope_completion.enabled` | `boolean` | Enable or disable the plugin. | `false` |
7474
| `pylsp.plugins.rope_completion.eager` | `boolean` | Resolve documentation and detail eagerly. | `false` |
75+
| `pylsp.plugins.rope_implementation.enabled` | `boolean` | Enable or disable the plugin. | `true` |
7576
| `pylsp.plugins.yapf.enabled` | `boolean` | Enable or disable the plugin. | `true` |
7677
| `pylsp.rope.extensionModules` | `string` | Builtin and c-extension modules that are allowed to be imported and inspected by rope. | `null` |
7778
| `pylsp.rope.ropeFolder` | `array` of unique `string` items | The name of the folder in which rope stores project configurations and data. Pass `null` for not using such a folder at all. | `null` |

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pip install python-lsp-server
1515
This will expose the command `pylsp` on your PATH. Confirm that installation succeeded by running `pylsp --help`.
1616

1717
If the respective dependencies are found, the following optional providers will be enabled:
18-
- [Rope](https://github.com/python-rope/rope) for Completions and renaming
18+
- [Rope](https://github.com/python-rope/rope) for Completions, Goto Implementation, and renaming
1919
- [Pyflakes](https://github.com/PyCQA/pyflakes) linter to detect various errors
2020
- [McCabe](https://github.com/PyCQA/mccabe) linter for complexity checking
2121
- [pycodestyle](https://github.com/PyCQA/pycodestyle) linter for style checking
@@ -151,7 +151,7 @@ pip install 'python-lsp-server[websockets]'
151151
* Code Linting
152152
* Code actions
153153
* Signature Help
154-
* Go to definition
154+
* Go to definition or implementation
155155
* Hover
156156
* Find References
157157
* Document Symbols

pylsp/config/schema.json

+5
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,11 @@
487487
"default": false,
488488
"description": "Resolve documentation and detail eagerly."
489489
},
490+
"pylsp.plugins.rope_implementation.enabled": {
491+
"type": "boolean",
492+
"default": true,
493+
"description": "Enable or disable the plugin."
494+
},
490495
"pylsp.plugins.yapf.enabled": {
491496
"type": "boolean",
492497
"default": true,

pylsp/hookspecs.py

+5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ def pylsp_hover(config, workspace, document, position) -> None:
9393
pass
9494

9595

96+
@hookspec
97+
def pylsp_implementations(config, workspace, document, position) -> None:
98+
pass
99+
100+
96101
@hookspec
97102
def pylsp_initialize(config, workspace) -> None:
98103
pass

pylsp/plugins/rope_implementation.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2017-2020 Palantir Technologies, Inc.
2+
# Copyright 2021- Python Language Server Contributors.
3+
import logging
4+
import os
5+
6+
from rope.contrib.findit import find_implementations
7+
8+
from pylsp import hookimpl, uris
9+
10+
log = logging.getLogger(__name__)
11+
12+
13+
@hookimpl
14+
def pylsp_settings():
15+
# Default to enabled (no reason not to)
16+
return {"plugins": {"rope_implementation": {"enabled": True}}}
17+
18+
19+
@hookimpl
20+
def pylsp_implementations(config, workspace, document, position):
21+
offset = document.offset_at_position(position)
22+
rope_config = config.settings(document_path=document.path).get("rope", {})
23+
rope_project = workspace._rope_project_builder(rope_config)
24+
rope_resource = document._rope_resource(rope_config)
25+
26+
impls = find_implementations(rope_project, rope_resource, offset)
27+
28+
return [
29+
{
30+
"uri": uris.uri_with(
31+
document.uri, path=str(os.path.abspath(impl.resource.path))
32+
),
33+
"range": {
34+
# TODO: `impl.region` seems to be from the start of the file
35+
# and offsets from the start of the line difficult to obtain,
36+
# so we just return the whole line for now:
37+
"start": {"line": impl.lineno - 1, "character": 0},
38+
"end": {"line": impl.lineno - 1, "character": 999},
39+
},
40+
}
41+
for impl in impls
42+
]

pylsp/python_lsp.py

+10
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ def capabilities(self):
280280
"commands": flatten(self._hook("pylsp_commands"))
281281
},
282282
"hoverProvider": True,
283+
"implementationProvider": True, # only when Rope is installed
283284
"referencesProvider": True,
284285
"renameProvider": True,
285286
"foldingRangeProvider": True,
@@ -436,6 +437,9 @@ def highlight(self, doc_uri, position):
436437
def hover(self, doc_uri, position):
437438
return self._hook("pylsp_hover", doc_uri, position=position) or {"contents": ""}
438439

440+
def implementations(self, doc_uri, position):
441+
return flatten(self._hook("pylsp_implementations", doc_uri, position=position))
442+
439443
@_utils.debounce(LINT_DEBOUNCE_S, keyed_by="doc_uri")
440444
def lint(self, doc_uri, is_saved) -> None:
441445
# Since we're debounced, the document may no longer be open
@@ -762,6 +766,12 @@ def m_text_document__definition(self, textDocument=None, position=None, **_kwarg
762766
return self._cell_document__definition(document, position, **_kwargs)
763767
return self.definitions(textDocument["uri"], position)
764768

769+
def m_text_document__implementation(self, textDocument=None, position=None, **_kwargs):
770+
# textDocument here is just a dict with a uri
771+
workspace = self._match_uri_to_workspace(textDocument["uri"])
772+
document = workspace.get_document(textDocument["uri"])
773+
return self.implementations(textDocument["uri"], position)
774+
765775
def m_text_document__document_highlight(
766776
self, textDocument=None, position=None, **_kwargs
767777
):

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pyflakes = "pylsp.plugins.pyflakes_lint"
8080
pylint = "pylsp.plugins.pylint_lint"
8181
rope_completion = "pylsp.plugins.rope_completion"
8282
rope_autoimport = "pylsp.plugins.rope_autoimport"
83+
rope_implementation = "pylsp.plugins.rope_implementation"
8384
yapf = "pylsp.plugins.yapf_format"
8485

8586
[project.scripts]

0 commit comments

Comments
 (0)