1
0
forked from VimPlug/jedi

Merge branch 'master' into project

This commit is contained in:
Dave Halter
2020-02-03 09:26:43 +01:00
18 changed files with 182 additions and 14 deletions

View File

@@ -264,6 +264,9 @@ class Value(HelperValueMixin, BaseValue):
def py__name__(self):
return self.name.string_name
def get_type_hint(self, add_class_info=True):
return None
def iterate_values(values, contextualized_node=None, is_async=False):
"""
@@ -414,6 +417,26 @@ class ValueSet(BaseValueSet):
def get_signatures(self):
return [sig for c in self._set for sig in c.get_signatures()]
def get_type_hint(self, add_class_info=True):
t = [v.get_type_hint(add_class_info=add_class_info) for v in self._set]
type_hints = sorted(filter(None, t))
if len(type_hints) == 1:
return type_hints[0]
optional = 'None' in type_hints
if optional:
type_hints.remove('None')
if len(type_hints) == 0:
return None
elif len(type_hints) == 1:
s = type_hints[0]
else:
s = 'Union[%s]' % ', '.join(type_hints)
if optional:
s = 'Optional[%s]' % s
return s
NO_VALUES = ValueSet([])

View File

@@ -285,6 +285,11 @@ class CompiledValue(Value):
for k in self.access_handle.get_key_paths()
]
def get_type_hint(self, add_class_info=True):
if self.access_handle.get_repr() in ('None', "<class 'NoneType'>"):
return 'None'
return None
class CompiledModule(CompiledValue):
file_io = None # For modules

View File

@@ -278,17 +278,17 @@ def infer_type_vars_for_execution(function, arguments, annotation_dict):
def infer_return_for_callable(arguments, param_values, result_values):
result = NO_VALUES
all_type_vars = {}
for pv in param_values:
if pv.array_type == 'list':
type_var_dict = infer_type_vars_for_callable(arguments, pv.py__iter__())
all_type_vars.update(type_var_dict)
result |= ValueSet.from_sets(
v.define_generics(type_var_dict)
if isinstance(v, (DefineGenericBase, TypeVar)) else ValueSet({v})
for v in result_values
).execute_annotation()
return result
return ValueSet.from_sets(
v.define_generics(type_var_dict)
if isinstance(v, (DefineGenericBase, TypeVar)) else ValueSet({v})
for v in result_values
).execute_annotation()
def infer_type_vars_for_callable(arguments, lazy_params):

View File

@@ -165,6 +165,18 @@ class GenericClass(ClassMixin, DefineGenericBase):
def _get_wrapped_value(self):
return self._class_value
def get_type_hint(self, add_class_info=True):
n = self.py__name__()
# Not sure if this is the best way to do this, but all of these types
# are a bit special in that they have type aliases and other ways to
# become lower case. It's probably better to make them upper case,
# because that's what you can use in annotations.
n = dict(list="List", dict="Dict", set="Set", tuple="Tuple").get(n, n)
s = n + self._generics_manager.get_type_hint()
if add_class_info:
return 'Type[%s]' % s
return s
def get_type_var_filter(self):
return _TypeVarFilter(self.get_generics(), self.list_type_vars())
@@ -239,6 +251,9 @@ class _GenericInstanceWrapper(ValueWrapper):
return ValueSet([builtin_from_name(self.inference_state, u'None')])
return self._wrapped_value.py__stop_iteration_returns()
def get_type_hint(self, add_class_info=True):
return self._wrapped_value.class_value.get_type_hint(add_class_info=False)
class _PseudoTreeNameClass(Value):
"""

View File

@@ -73,7 +73,13 @@ def _try_stub_to_python_names(names, prefer_stub_to_compiled=False):
converted_names = converted.goto(name.get_public_name())
if converted_names:
for n in converted_names:
yield n
if n.get_root_context().is_stub():
# If it's a stub again, it means we're going in
# a circle. Probably some imports make it a
# stub again.
yield name
else:
yield n
continue
yield name

View File

@@ -31,6 +31,9 @@ class _AbstractGenericManager(object):
debug.warning('No param #%s found for annotation %s', index, self)
return NO_VALUES
def get_type_hint(self):
return '[%s]' % ', '.join(t.get_type_hint(add_class_info=False) for t in self.to_tuple())
class LazyGenericManager(_AbstractGenericManager):
def __init__(self, context_of_index, index_value):

View File

@@ -86,6 +86,33 @@ class FunctionMixin(object):
def py__name__(self):
return self.name.string_name
def get_type_hint(self, add_class_info=True):
return_annotation = self.tree_node.annotation
if return_annotation is None:
def param_name_to_str(n):
s = n.string_name
annotation = n.infer().get_type_hint()
if annotation is not None:
s += ': ' + annotation
if n.default_node is not None:
s += '=' + n.default_node.get_code(include_prefix=False)
return s
function_execution = self.as_context()
result = function_execution.infer()
return_hint = result.get_type_hint()
body = self.py__name__() + '(%s)' % ', '.join([
param_name_to_str(n)
for n in function_execution.get_param_names()
])
if return_hint is None:
return body
else:
return_hint = return_annotation.get_code(include_prefix=False)
body = self.py__name__() + self.tree_node.children[2].get_code(include_prefix=False)
return body + ' -> ' + return_hint
def py__call__(self, arguments):
function_execution = self.as_context(arguments)
return function_execution.infer()
@@ -399,6 +426,9 @@ class OverloadedFunctionValue(FunctionMixin, ValueWrapper):
def get_signature_functions(self):
return self._overloaded_functions
def get_type_hint(self, add_class_info=True):
return 'Union[%s]' % ', '.join(f.get_type_hint() for f in self._overloaded_functions)
def _find_overload_functions(context, tree_node):
def _is_overload_decorated(funcdef):

View File

@@ -130,6 +130,9 @@ class AbstractInstanceValue(Value):
for name in names
)
def get_type_hint(self, add_class_info=True):
return self.py__name__()
def __repr__(self):
return "<%s of %s>" % (self.__class__.__name__, self.class_value)

View File

@@ -221,6 +221,11 @@ class ClassMixin(object):
def _as_context(self):
return ClassContext(self)
def get_type_hint(self, add_class_info=True):
if add_class_info:
return 'Type[%s]' % self.py__name__()
return self.py__name__()
class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase)):
api_type = u'class'