Skip to content

Commit e363239

Browse files
committed
Hierarchical documentSymbol support.
1 parent 96e08d8 commit e363239

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

pyls/plugins/symbols.py

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright 2017 Palantir Technologies, Inc.
22
import logging
3+
from jedi.api.classes import Definition
34
from pyls import hookimpl
45
from pyls.lsp import SymbolKind
56

@@ -8,27 +9,40 @@
89

910
@hookimpl
1011
def pyls_document_symbols(config, document):
11-
all_scopes = config.plugin_settings('jedi_symbols').get('all_scopes', True)
12-
definitions = document.jedi_names(all_scopes=all_scopes)
13-
return [{
14-
'name': d.name,
15-
'containerName': _container(d),
16-
'location': {
17-
'uri': document.uri,
12+
# all_scopes = config.plugin_settings('jedi_symbols').get('all_scopes', True)
13+
definitions = document.jedi_names(all_scopes=False)
14+
def transform(d: Definition):
15+
includeD = _include_def(d)
16+
if includeD is None:
17+
return None
18+
children = [dt for dt in (transform(d1) for d1 in d.defined_names()) if dt] if includeD else None
19+
detailName = d.full_name
20+
if detailName and detailName.startswith("__main__."):
21+
detailName = detailName[9:]
22+
return {
23+
'name': d.name,
24+
'detail': detailName,
1825
'range': _range(d),
19-
},
20-
'kind': _kind(d),
21-
} for d in definitions if _include_def(d)]
22-
26+
'selectionRange': _name_range(d),
27+
'kind': _kind(d),
28+
'children': children
29+
}
30+
return [dt for dt in (transform(d) for d in definitions) if dt]
2331

2432
def _include_def(definition):
25-
return (
26-
# Don't tend to include parameters as symbols
27-
definition.type != 'param' and
28-
# Unused vars should also be skipped
29-
definition.name != '_' and
30-
_kind(definition) is not None
31-
)
33+
# True: include def and sub-defs
34+
# False: include def but do not include sub-defs
35+
# None: Do not include def or sub-defs
36+
if (# Unused vars should also be skipped
37+
definition.name != '_' and
38+
not definition._name.is_import() and
39+
definition.is_definition() and
40+
not definition.in_builtin_module() and
41+
_kind(definition) is not None
42+
):
43+
# for `statement`, we do not enumerate its child nodes. It tends to cause Error.
44+
return definition.type not in ("statement",)
45+
return None
3246

3347

3448
def _container(definition):
@@ -56,6 +70,17 @@ def _range(definition):
5670
}
5771

5872

73+
def _name_range(definition):
74+
# Gets the range of symbol name (e.g. function name of a function)
75+
definition = definition._name.tree_name
76+
(start_line, start_column) = definition.start_pos
77+
(end_line, end_column) = definition.end_pos
78+
return {
79+
'start': {'line': start_line - 1, 'character': start_column},
80+
'end': {'line': end_line - 1, 'character': end_column}
81+
}
82+
83+
5984
_SYMBOL_KIND_MAP = {
6085
'none': SymbolKind.Variable,
6186
'type': SymbolKind.Class,
@@ -85,7 +110,8 @@ def _range(definition):
85110
'constant': SymbolKind.Constant,
86111
'variable': SymbolKind.Variable,
87112
'value': SymbolKind.Variable,
88-
'param': SymbolKind.Variable,
113+
# Don't tend to include parameters as symbols
114+
# 'param': SymbolKind.Variable,
89115
'statement': SymbolKind.Variable,
90116
'boolean': SymbolKind.Boolean,
91117
'int': SymbolKind.Number,

0 commit comments

Comments
 (0)