@@ -16,13 +16,16 @@ def pylsp_document_symbols(config, document):
16
16
# pylint: disable=too-many-nested-blocks
17
17
# pylint: disable=too-many-locals
18
18
# pylint: disable=too-many-branches
19
+ # pylint: disable=too-many-statements
20
+
19
21
symbols_settings = config .plugin_settings ('jedi_symbols' )
20
22
all_scopes = symbols_settings .get ('all_scopes' , True )
21
23
add_import_symbols = symbols_settings .get ('include_import_symbols' , True )
22
24
definitions = document .jedi_names (all_scopes = all_scopes )
23
25
symbols = []
24
26
exclude = set ({})
25
27
redefinitions = {}
28
+
26
29
while definitions != []:
27
30
d = definitions .pop (0 )
28
31
@@ -33,27 +36,47 @@ def pylsp_document_symbols(config, document):
33
36
if ' import ' in code or 'import ' in code :
34
37
continue
35
38
36
- # Skip comparing module names.
39
+ # Skip imported symbols comparing module names.
37
40
sym_full_name = d .full_name
38
- module_name = document .dot_path
41
+ document_dot_path = document .dot_path
39
42
if sym_full_name is not None :
40
- # module_name returns where the symbol is imported, whereas
41
- # full_name says where it really comes from. So if the parent
42
- # modules in full_name are not in module_name, it means the
43
- # symbol was not defined there.
44
- # Note: The last element of sym_full_name is the symbol itself,
45
- # so we don't need to use it below.
43
+ # We assume a symbol is imported from another module to start
44
+ # with.
46
45
imported_symbol = True
47
- for mod in sym_full_name .split ('.' )[:- 1 ]:
48
- if mod in module_name :
49
- imported_symbol = False
46
+
47
+ # The last element of sym_full_name is the symbol itself, so
48
+ # we need to discard it to do module comparisons below.
49
+ if '.' in sym_full_name :
50
+ sym_module_name = sym_full_name .rpartition ('.' )[0 ]
51
+
52
+ # This is necessary to display symbols in init files (the checks
53
+ # below fail without it).
54
+ if document_dot_path .endswith ('__init__' ):
55
+ document_dot_path = document_dot_path .rpartition ('.' )[0 ]
56
+
57
+ # document_dot_path is the module where the symbol is imported,
58
+ # whereas sym_module_name is the one where it was declared.
59
+ if sym_module_name .startswith (document_dot_path ):
60
+ # If sym_module_name starts with the same string as document_dot_path,
61
+ # we can safely assume it was declared in the document.
62
+ imported_symbol = False
63
+ elif sym_module_name .split ('.' )[0 ] in document_dot_path .split ('.' ):
64
+ # If the first module in sym_module_name is one of the modules in
65
+ # document_dot_path, we need to check if sym_module_name starts
66
+ # with the modules in document_dot_path.
67
+ document_mods = document_dot_path .split ('.' )
68
+ for i in range (1 , len (document_mods ) + 1 ):
69
+ submod = '.' .join (document_mods [- i :])
70
+ if sym_module_name .startswith (submod ):
71
+ imported_symbol = False
72
+ break
50
73
51
74
# When there's no __init__.py next to a file or in one of its
52
- # parents, the check above fails . However, Jedi has a nice way
75
+ # parents, the checks above fail . However, Jedi has a nice way
53
76
# to tell if the symbol was declared in the same file: if
54
77
# full_name starts by __main__.
55
78
if imported_symbol :
56
- if not sym_full_name .startswith ('__main__' ):
79
+ if not sym_module_name .startswith ('__main__' ):
57
80
continue
58
81
59
82
try :
0 commit comments