Skip to content

Commit 04cdb98

Browse files
committed
Allow to format signatures in docstrings
1 parent cc6d398 commit 04cdb98

File tree

5 files changed

+73
-15
lines changed

5 files changed

+73
-15
lines changed

pylsp/_utils.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import re
1010
import threading
1111
import time
12-
from typing import List, Optional
12+
from typing import Callable, List, Optional
1313

1414
import docstring_to_markdown
1515
import jedi
@@ -210,7 +210,10 @@ def choose_markup_kind(client_supported_markup_kinds: List[str]):
210210

211211

212212
def format_docstring(
213-
contents: str, markup_kind: str, signatures: Optional[List[str]] = None
213+
contents: str,
214+
markup_kind: str,
215+
signatures: Optional[List[str]] = None,
216+
signatures_to_markdown: Optional[Callable[[List[str]], str]] = None,
214217
):
215218
"""Transform the provided docstring into a MarkupContent object.
216219
@@ -232,7 +235,12 @@ def format_docstring(
232235
value = escape_markdown(contents)
233236

234237
if signatures:
235-
value = wrap_signature("\n".join(signatures)) + "\n\n" + value
238+
if signatures_to_markdown is None:
239+
wrapped_signatures = wrap_signature("\n".join(signatures))
240+
else:
241+
wrapped_signatures = signatures_to_markdown(signatures)
242+
243+
value = wrapped_signatures + "\n\n" + value
236244

237245
return {"kind": "markdown", "value": value}
238246
value = contents

pylsp/hookspecs.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,16 @@ def pylsp_commands(config, workspace) -> None:
2424

2525

2626
@hookspec
27-
def pylsp_completions(config, workspace, document, position, ignored_names) -> None:
27+
def pylsp_completions(
28+
config, workspace, document, position, ignored_names, signatures_to_markdown
29+
) -> None:
2830
pass
2931

3032

3133
@hookspec(firstresult=True)
32-
def pylsp_completion_item_resolve(config, workspace, document, completion_item) -> None:
34+
def pylsp_completion_item_resolve(
35+
config, workspace, document, completion_item, signatures_to_markdown
36+
) -> None:
3337
pass
3438

3539

@@ -89,7 +93,12 @@ def pylsp_format_range(config, workspace, document, range, options) -> None:
8993

9094

9195
@hookspec(firstresult=True)
92-
def pylsp_hover(config, workspace, document, position) -> None:
96+
def pylsp_hover(config, workspace, document, position, signatures_to_markdown) -> None:
97+
pass
98+
99+
100+
@hookspec(firstresult=True)
101+
def pylsp_signatures_to_markdown(signatures) -> None:
93102
pass
94103

95104

pylsp/plugins/hover.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
@hookimpl
12-
def pylsp_hover(config, document, position):
12+
def pylsp_hover(config, document, position, signatures_to_markdown=None):
1313
code_position = _utils.position_to_jedi_linecolumn(document, position)
1414
definitions = document.jedi_script(use_document_path=True).infer(**code_position)
1515
word = document.word_at_position(position)
@@ -46,5 +46,6 @@ def pylsp_hover(config, document, position):
4646
definition.docstring(raw=True),
4747
preferred_markup_kind,
4848
signatures=[signature] if signature else None,
49+
signatures_to_markdown=signatures_to_markdown,
4950
)
5051
}

pylsp/plugins/jedi_completion.py

+25-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import logging
55
import os
6+
from typing import Callable, List, Optional
67

78
import parso
89

@@ -36,7 +37,7 @@
3637

3738

3839
@hookimpl
39-
def pylsp_completions(config, document, position):
40+
def pylsp_completions(config, document, position, signatures_to_markdown=None):
4041
"""Get formatted completions for current code position"""
4142
settings = config.plugin_settings("jedi_completion", document_path=document.path)
4243
resolve_eagerly = settings.get("eager", False)
@@ -88,6 +89,7 @@ def pylsp_completions(config, document, position):
8889
resolve=resolve_eagerly,
8990
resolve_label_or_snippet=(i < max_to_resolve),
9091
snippet_support=snippet_support,
92+
signatures_to_markdown=signatures_to_markdown,
9193
)
9294
for i, c in enumerate(completions)
9395
]
@@ -103,6 +105,7 @@ def pylsp_completions(config, document, position):
103105
resolve=resolve_eagerly,
104106
resolve_label_or_snippet=(i < max_to_resolve),
105107
snippet_support=snippet_support,
108+
signatures_to_markdown=signatures_to_markdown,
106109
)
107110
completion_dict["kind"] = lsp.CompletionItemKind.TypeParameter
108111
completion_dict["label"] += " object"
@@ -118,6 +121,7 @@ def pylsp_completions(config, document, position):
118121
resolve=resolve_eagerly,
119122
resolve_label_or_snippet=(i < max_to_resolve),
120123
snippet_support=snippet_support,
124+
signatures_to_markdown=signatures_to_markdown,
121125
)
122126
completion_dict["kind"] = lsp.CompletionItemKind.TypeParameter
123127
completion_dict["label"] += " object"
@@ -137,7 +141,9 @@ def pylsp_completions(config, document, position):
137141

138142

139143
@hookimpl
140-
def pylsp_completion_item_resolve(config, completion_item, document):
144+
def pylsp_completion_item_resolve(
145+
config, completion_item, document, signatures_to_markdown=None
146+
):
141147
"""Resolve formatted completion for given non-resolved completion"""
142148
shared_data = document.shared_data["LAST_JEDI_COMPLETIONS"].get(
143149
completion_item["label"]
@@ -152,7 +158,12 @@ def pylsp_completion_item_resolve(config, completion_item, document):
152158

153159
if shared_data:
154160
completion, data = shared_data
155-
return _resolve_completion(completion, data, markup_kind=preferred_markup_kind)
161+
return _resolve_completion(
162+
completion,
163+
data,
164+
markup_kind=preferred_markup_kind,
165+
signatures_to_markdown=signatures_to_markdown,
166+
)
156167
return completion_item
157168

158169

@@ -207,13 +218,19 @@ def use_snippets(document, position):
207218
return expr_type not in _IMPORTS and not (expr_type in _ERRORS and "import" in code)
208219

209220

210-
def _resolve_completion(completion, d, markup_kind: str):
221+
def _resolve_completion(
222+
completion,
223+
d,
224+
markup_kind: str,
225+
signatures_to_markdown: Optional[Callable[[List[str]], str]] = None,
226+
):
211227
completion["detail"] = _detail(d)
212228
try:
213229
docs = _utils.format_docstring(
214230
d.docstring(raw=True),
215231
signatures=[signature.to_string() for signature in d.get_signatures()],
216232
markup_kind=markup_kind,
233+
signatures_to_markdown=signatures_to_markdown,
217234
)
218235
except Exception:
219236
docs = ""
@@ -228,6 +245,7 @@ def _format_completion(
228245
resolve=False,
229246
resolve_label_or_snippet=False,
230247
snippet_support=False,
248+
signatures_to_markdown=None,
231249
):
232250
completion = {
233251
"label": _label(d, resolve_label_or_snippet),
@@ -237,7 +255,9 @@ def _format_completion(
237255
}
238256

239257
if resolve:
240-
completion = _resolve_completion(completion, d, markup_kind)
258+
completion = _resolve_completion(
259+
completion, d, markup_kind, signatures_to_markdown
260+
)
241261

242262
# Adjustments for file completions
243263
if d.type == "path":

pylsp/python_lsp.py

+23-3
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,21 @@ def completions(self, doc_uri, position):
399399
notebook_document = workspace.get_maybe_document(document.notebook_uri)
400400
ignored_names = notebook_document.jedi_names(doc_uri)
401401
completions = self._hook(
402-
"pylsp_completions", doc_uri, position=position, ignored_names=ignored_names
402+
"pylsp_completions",
403+
doc_uri,
404+
position=position,
405+
ignored_names=ignored_names,
406+
signatures_to_markdown=self._signatures_to_markdown,
403407
)
404408
return {"isIncomplete": False, "items": flatten(completions)}
405409

406410
def completion_item_resolve(self, completion_item):
407411
doc_uri = completion_item.get("data", {}).get("doc_uri", None)
408412
return self._hook(
409-
"pylsp_completion_item_resolve", doc_uri, completion_item=completion_item
413+
"pylsp_completion_item_resolve",
414+
doc_uri,
415+
completion_item=completion_item,
416+
signatures_to_markdown=self._signatures_to_markdown,
410417
)
411418

412419
def definitions(self, doc_uri, position):
@@ -434,7 +441,12 @@ def highlight(self, doc_uri, position):
434441
)
435442

436443
def hover(self, doc_uri, position):
437-
return self._hook("pylsp_hover", doc_uri, position=position) or {"contents": ""}
444+
return self._hook(
445+
"pylsp_hover",
446+
doc_uri,
447+
position=position,
448+
signatures_to_markdown=self._signatures_to_markdown,
449+
) or {"contents": ""}
438450

439451
@_utils.debounce(LINT_DEBOUNCE_S, keyed_by="doc_uri")
440452
def lint(self, doc_uri, is_saved) -> None:
@@ -888,6 +900,14 @@ def m_workspace__did_change_watched_files(self, changes=None, **_kwargs):
888900
def m_workspace__execute_command(self, command=None, arguments=None):
889901
return self.execute_command(command, arguments)
890902

903+
@property
904+
def _signatures_to_markdown(self):
905+
if not hasattr(self, "_signatures_to_markdown_hook"):
906+
self._signatures_to_markdown_hook = self._hook(
907+
"pylsp_signatures_to_markdown"
908+
)
909+
return self._signatures_to_markdown_hook
910+
891911

892912
def flatten(list_of_lists):
893913
return [item for lst in list_of_lists for item in lst]

0 commit comments

Comments
 (0)