87 lines
2.7 KiB
Python
87 lines
2.7 KiB
Python
# Copyright 2017-2020 Palantir Technologies, Inc.
|
|
# Copyright 2021- Python Language Server Contributors.
|
|
|
|
import logging
|
|
import re
|
|
|
|
from pylsp import _utils, hookimpl
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
SPHINX = re.compile(r"\s*:param\s+(?P<param>\w+):\s*(?P<doc>[^\n]+)")
|
|
EPYDOC = re.compile(r"\s*@param\s+(?P<param>\w+):\s*(?P<doc>[^\n]+)")
|
|
GOOGLE = re.compile(r"\s*(?P<param>\w+).*:\s*(?P<doc>[^\n]+)")
|
|
|
|
DOC_REGEX = [SPHINX, EPYDOC, GOOGLE]
|
|
|
|
|
|
@hookimpl
|
|
def pylsp_signature_help(config, document, position):
|
|
signature_config = config.settings().get("signature", {})
|
|
code_position = _utils.position_to_jedi_linecolumn(document, position)
|
|
signatures = document.jedi_script().get_signatures(**code_position)
|
|
|
|
if not signatures:
|
|
return {"signatures": []}
|
|
|
|
signature_capabilities = config.capabilities.get("textDocument", {}).get(
|
|
"signatureHelp", {}
|
|
)
|
|
signature_information_support = signature_capabilities.get(
|
|
"signatureInformation", {}
|
|
)
|
|
supported_markup_kinds = signature_information_support.get(
|
|
"documentationFormat", ["markdown"]
|
|
)
|
|
preferred_markup_kind = _utils.choose_markup_kind(supported_markup_kinds)
|
|
|
|
s = signatures[0]
|
|
|
|
docstring = s.docstring()
|
|
|
|
# Docstring contains one or more lines of signature, followed by empty line, followed by docstring
|
|
function_sig_lines = (docstring.split("\n\n") or [""])[0].splitlines()
|
|
function_sig = " ".join([line.strip() for line in function_sig_lines])
|
|
|
|
signature_docstring = s.docstring(raw=True)
|
|
if not signature_config.get("include_docstring", True):
|
|
signature_docstring = ""
|
|
|
|
sig = {
|
|
"label": function_sig,
|
|
"documentation": _utils.format_docstring(
|
|
signature_docstring, markup_kind=preferred_markup_kind
|
|
),
|
|
}
|
|
|
|
# If there are params, add those
|
|
if s.params:
|
|
sig["parameters"] = [
|
|
{
|
|
"label": p.name,
|
|
"documentation": _utils.format_docstring(
|
|
_param_docs(docstring, p.name), markup_kind=preferred_markup_kind
|
|
),
|
|
}
|
|
for p in s.params
|
|
]
|
|
|
|
# We only return a single signature because Python doesn't allow overloading
|
|
sig_info = {"signatures": [sig], "activeSignature": 0}
|
|
|
|
if s.index is not None and s.params:
|
|
# Then we know which parameter we're looking at
|
|
sig_info["activeParameter"] = s.index
|
|
|
|
return sig_info
|
|
|
|
|
|
def _param_docs(docstring, param_name):
|
|
for line in docstring.splitlines():
|
|
for regex in DOC_REGEX:
|
|
m = regex.match(line)
|
|
if not m:
|
|
continue
|
|
if m.group("param") != param_name:
|
|
continue
|
|
return m.group("doc") or ""
|