@@ -16,13 +16,16 @@ def pylsp_document_symbols(config, document):
1616 # pylint: disable=too-many-nested-blocks
1717 # pylint: disable=too-many-locals
1818 # pylint: disable=too-many-branches
19+ # pylint: disable=too-many-statements
20+
1921 symbols_settings = config .plugin_settings ('jedi_symbols' )
2022 all_scopes = symbols_settings .get ('all_scopes' , True )
2123 add_import_symbols = symbols_settings .get ('include_import_symbols' , True )
2224 definitions = document .jedi_names (all_scopes = all_scopes )
2325 symbols = []
2426 exclude = set ({})
2527 redefinitions = {}
28+
2629 while definitions != []:
2730 d = definitions .pop (0 )
2831
@@ -33,27 +36,47 @@ def pylsp_document_symbols(config, document):
3336 if ' import ' in code or 'import ' in code :
3437 continue
3538
36- # Skip comparing module names.
39+ # Skip imported symbols comparing module names.
3740 sym_full_name = d .full_name
38- module_name = document .dot_path
41+ document_dot_path = document .dot_path
3942 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.
4645 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
5073
5174 # 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
5376 # to tell if the symbol was declared in the same file: if
5477 # full_name starts by __main__.
5578 if imported_symbol :
56- if not sym_full_name .startswith ('__main__' ):
79+ if not sym_module_name .startswith ('__main__' ):
5780 continue
5881
5982 try :
0 commit comments