1
1
# Copyright 2017-2020 Palantir Technologies, Inc.
2
2
# Copyright 2021- Python Language Server Contributors.
3
3
4
+ import itertools
4
5
import logging
5
6
6
7
from pylsp import _utils , hookimpl
@@ -42,38 +43,49 @@ def _find_docstring(definitions):
42
43
return types [0 ].docstring (raw = True )
43
44
44
45
45
- def _find_signatures (definitions , word ):
46
- # Get the signatures of all definitions
47
- signatures = [
48
- signature .to_string ()
49
- for definition in definitions
50
- for signature in definition .get_signatures ()
51
- if signature .type not in ["module" ]
52
- ]
53
-
54
- if len (signatures ) != 0 :
46
+ def _find_signatures_and_types (definitions ):
47
+ def _line_number (definition ):
48
+ """Helper for sorting definitions by line number (which might be None)."""
49
+ return definition .line if definition .line is not None else 0
50
+
51
+ def _get_signatures (definition ):
52
+ """Get the signatures of functions and classes."""
53
+ return [
54
+ signature .to_string ()
55
+ for signature in definition .get_signatures ()
56
+ if signature .type in ["class" , "function" ]
57
+ ]
58
+
59
+ definitions = sorted (definitions , key = _line_number )
60
+ signatures_per_def = [_get_signatures (d ) for d in definitions ]
61
+ types_per_def = [d .infer () for d in definitions ]
62
+
63
+ # a flat list with all signatures
64
+ signatures = list (itertools .chain (* signatures_per_def ))
65
+
66
+ # We want to show the type if there is at least one type that does not
67
+ # correspond to a signature
68
+ if any (
69
+ len (s ) == 0 and len (t ) > 0 for s , t in zip (signatures_per_def , types_per_def )
70
+ ):
71
+ # Get all types (also the ones that correspond to a signature)
72
+ types = set (itertools .chain (* types_per_def ))
73
+ type_names = [t .name for t in sorted (types , key = _line_number )]
74
+
75
+ if len (type_names ) == 1 :
76
+ return [* signatures , type_names [0 ]]
77
+ elif len (type_names ) > 1 :
78
+ return [* signatures , f"Union[{ ', ' .join (type_names )} ]" ]
79
+
80
+ else :
81
+ # The type does not add any information because it is already in the signatures
55
82
return signatures
56
83
57
- # If we did not find a signature, infer the possible types of all definitions
58
- types = [
59
- t .name
60
- for d in sorted (definitions , key = lambda d : d .line )
61
- for t in sorted (d .infer (), key = lambda t : t .line )
62
- ]
63
- if len (types ) == 1 :
64
- return [types [0 ]]
65
- elif len (types ) > 1 :
66
- return [f"Union[{ ', ' .join (types )} ]" ]
67
-
68
84
69
85
@hookimpl
70
86
def pylsp_hover (config , document , position ):
71
87
code_position = _utils .position_to_jedi_linecolumn (document , position )
72
-
73
- # TODO(Review)
74
- # We could also use Script.help here. It would not resolve keywords
75
88
definitions = document .jedi_script (use_document_path = True ).help (** code_position )
76
- word = document .word_at_position (position )
77
89
78
90
hover_capabilities = config .capabilities .get ("textDocument" , {}).get ("hover" , {})
79
91
supported_markup_kinds = hover_capabilities .get ("contentFormat" , ["markdown" ])
@@ -83,6 +95,6 @@ def pylsp_hover(config, document, position):
83
95
"contents" : _utils .format_docstring (
84
96
_find_docstring (definitions ),
85
97
preferred_markup_kind ,
86
- signatures = _find_signatures (definitions , word ),
98
+ signatures = _find_signatures_and_types (definitions ),
87
99
)
88
100
}
0 commit comments