84 lines
2.6 KiB
Python
84 lines
2.6 KiB
Python
# Copyright 2017-2020 Palantir Technologies, Inc.
|
|
# Copyright 2021- Python Language Server Contributors.
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
import jedi
|
|
|
|
from pylsp import _utils, hookimpl, uris
|
|
|
|
if TYPE_CHECKING:
|
|
from jedi.api import Script
|
|
from jedi.api.classes import Name
|
|
|
|
from pylsp.config.config import Config
|
|
from pylsp.workspace import Document
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
MAX_JEDI_GOTO_HOPS = 100
|
|
|
|
|
|
def _resolve_definition(
|
|
maybe_defn: Name, script: Script, settings: dict[str, Any]
|
|
) -> Name:
|
|
for _ in range(MAX_JEDI_GOTO_HOPS):
|
|
if maybe_defn.is_definition() or maybe_defn.module_path != script.path:
|
|
break
|
|
defns = script.goto(
|
|
follow_imports=settings.get("follow_imports", True),
|
|
follow_builtin_imports=settings.get("follow_builtin_imports", True),
|
|
line=maybe_defn.line,
|
|
column=maybe_defn.column,
|
|
)
|
|
if len(defns) == 1:
|
|
maybe_defn = defns[0]
|
|
else:
|
|
break
|
|
return maybe_defn
|
|
|
|
|
|
@hookimpl
|
|
def pylsp_definitions(
|
|
config: Config, document: Document, position: dict[str, int]
|
|
) -> list[dict[str, Any]]:
|
|
settings = config.plugin_settings("jedi_definition")
|
|
code_position = _utils.position_to_jedi_linecolumn(document, position)
|
|
script = document.jedi_script(use_document_path=True)
|
|
auto_import_modules = jedi.settings.auto_import_modules
|
|
|
|
try:
|
|
jedi.settings.auto_import_modules = []
|
|
definitions = script.goto(
|
|
follow_imports=settings.get("follow_imports", True),
|
|
follow_builtin_imports=settings.get("follow_builtin_imports", True),
|
|
**code_position,
|
|
)
|
|
definitions = [_resolve_definition(d, script, settings) for d in definitions]
|
|
finally:
|
|
jedi.settings.auto_import_modules = auto_import_modules
|
|
|
|
follow_builtin_defns = settings.get("follow_builtin_definitions", True)
|
|
return [
|
|
{
|
|
"uri": uris.uri_with(document.uri, path=str(d.module_path)),
|
|
"range": {
|
|
"start": {"line": d.line - 1, "character": d.column},
|
|
"end": {"line": d.line - 1, "character": d.column + len(d.name)},
|
|
},
|
|
}
|
|
for d in definitions
|
|
if d.is_definition() and (follow_builtin_defns or _not_internal_definition(d))
|
|
]
|
|
|
|
|
|
def _not_internal_definition(definition: Name) -> bool:
|
|
return (
|
|
definition.line is not None
|
|
and definition.column is not None
|
|
and definition.module_path is not None
|
|
and not definition.in_builtin_module()
|
|
)
|