|
1 | 1 | # Copyright 2017 Palantir Technologies, Inc.
|
2 | 2 | import logging
|
| 3 | +from jedi.api.classes import Definition |
3 | 4 | from pyls import hookimpl
|
4 | 5 | from pyls.lsp import SymbolKind
|
5 | 6 |
|
|
8 | 9 |
|
9 | 10 | @hookimpl
|
10 | 11 | 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, |
18 | 25 | '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] |
23 | 31 |
|
24 | 32 | 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 |
32 | 46 |
|
33 | 47 |
|
34 | 48 | def _container(definition):
|
@@ -56,6 +70,17 @@ def _range(definition):
|
56 | 70 | }
|
57 | 71 |
|
58 | 72 |
|
| 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 | + |
59 | 84 | _SYMBOL_KIND_MAP = {
|
60 | 85 | 'none': SymbolKind.Variable,
|
61 | 86 | 'type': SymbolKind.Class,
|
@@ -85,7 +110,8 @@ def _range(definition):
|
85 | 110 | 'constant': SymbolKind.Constant,
|
86 | 111 | 'variable': SymbolKind.Variable,
|
87 | 112 | 'value': SymbolKind.Variable,
|
88 |
| - 'param': SymbolKind.Variable, |
| 113 | + # Don't tend to include parameters as symbols |
| 114 | + # 'param': SymbolKind.Variable, |
89 | 115 | 'statement': SymbolKind.Variable,
|
90 | 116 | 'boolean': SymbolKind.Boolean,
|
91 | 117 | 'int': SymbolKind.Number,
|
|
0 commit comments